[TASK] Add a system check for external downloads
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / SystemEnvironment / Check.php
1 <?php
2 namespace TYPO3\CMS\Install\SystemEnvironment;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 use TYPO3\CMS\Install\Status;
28
29 /**
30 * Check system environment status
31 *
32 * This class is a hardcoded requirement check of the underlying
33 * server and PHP system.
34 *
35 * The class *must not* check for any TYPO3 specific things like
36 * specific configuration values or directories. It should not fail
37 * if there is no TYPO3 at all.
38 *
39 * The only core code used is the class loader
40 *
41 * This class is instantiated as the *very first* class during
42 * installation. It is meant to be *standalone* und must not have
43 * any requirements, except the status classes. It must be possible
44 * to run this script separated from the rest of the core, without
45 * dependencies.
46 *
47 * This means especially:
48 * * No hooks or anything like that
49 * * No usage of *any* TYPO3 code like GeneralUtility
50 * * No require of anything but the status classes
51 * * No localization
52 *
53 * The status messages and title *must not* include HTML, use plain
54 * text only. The return values of this class are not bound to HTML
55 * and can be used in different scopes (eg. as json array).
56 *
57 * @author Christian Kuhn <lolli@schwarzbu.ch>
58 */
59 class Check {
60
61 /**
62 * @var array List of required PHP extensions
63 */
64 protected $requiredPhpExtensions = array(
65 'fileinfo',
66 'filter',
67 'gd',
68 'hash',
69 'json',
70 'mysqli',
71 'openssl',
72 'pcre',
73 'session',
74 'soap',
75 'SPL',
76 'standard',
77 'xml',
78 'zip',
79 'zlib',
80 );
81
82 /**
83 * Get all status information as array with status objects
84 *
85 * @return array<\TYPO3\CMS\Install\Status\StatusInterface>
86 */
87 public function getStatus() {
88 $statusArray = array();
89 $statusArray[] = $this->checkCurrentDirectoryIsInIncludePath();
90 $statusArray[] = $this->checkFileUploadEnabled();
91 $statusArray[] = $this->checkMaximumFileUploadSize();
92 $statusArray[] = $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize();
93 $statusArray[] = $this->checkMemorySettings();
94 $statusArray[] = $this->checkPhpVersion();
95 $statusArray[] = $this->checkMaxExecutionTime();
96 $statusArray[] = $this->checkDisableFunctions();
97 $statusArray[] = $this->checkDownloadsPossible();
98 $statusArray[] = $this->checkSafeMode();
99 $statusArray[] = $this->checkDocRoot();
100 $statusArray[] = $this->checkOpenBaseDir();
101 $statusArray[] = $this->checkXdebugMaxNestingLevel();
102 $statusArray[] = $this->checkOpenSslInstalled();
103 $statusArray[] = $this->checkSuhosinLoaded();
104 $statusArray[] = $this->checkSuhosinRequestMaxVars();
105 $statusArray[] = $this->checkSuhosinPostMaxVars();
106 $statusArray[] = $this->checkSuhosinGetMaxValueLength();
107 $statusArray[] = $this->checkSuhosinExecutorIncludeWhitelistContainsPhar();
108 $statusArray[] = $this->checkSuhosinExecutorIncludeWhitelistContainsVfs();
109 $statusArray[] = $this->checkSomePhpOpcodeCacheIsLoaded();
110 $statusArray[] = $this->checkReflectionDocComment();
111 $statusArray[] = $this->checkSystemLocale();
112 $statusArray[] = $this->checkLocaleWithUTF8filesystem();
113 $statusArray[] = $this->checkWindowsApacheThreadStackSize();
114 foreach ($this->requiredPhpExtensions as $extension) {
115 $statusArray[] = $this->checkRequiredPhpExtension($extension);
116 }
117 $statusArray[] = $this->checkGdLibTrueColorSupport();
118 $statusArray[] = $this->checkGdLibGifSupport();
119 $statusArray[] = $this->checkGdLibJpgSupport();
120 $statusArray[] = $this->checkGdLibPngSupport();
121 $statusArray[] = $this->checkGdLibFreeTypeSupport();
122 $statusArray[] = $this->checkPhpMagicQuotes();
123 $statusArray[] = $this->checkRegisterGlobals();
124 $statusArray[] = $this->checkLibXmlBug();
125 $statusArray[] = $this->isTrueTypeFontDpiStandard();
126 return $statusArray;
127 }
128
129 /**
130 * Checks if current directory (.) is in PHP include path
131 *
132 * @return Status\StatusInterface
133 */
134 protected function checkCurrentDirectoryIsInIncludePath() {
135 $includePath = ini_get('include_path');
136 $delimiter = $this->isWindowsOs() ? ';' : ':';
137 $pathArray = $this->trimExplode($delimiter, $includePath);
138 if (!in_array('.', $pathArray)) {
139 $status = new Status\WarningStatus();
140 $status->setTitle('Current directory (./) is not within PHP include path');
141 $status->setMessage(
142 'include_path = ' . implode(' ', $pathArray) . LF .
143 'Normally the current path \'.\' is included in the' .
144 ' include_path of PHP. Although TYPO3 does not rely on this,' .
145 ' it is an unusual setting that may introduce problems for' .
146 ' some extensions.'
147 );
148 } else {
149 $status = new Status\OkStatus();
150 $status->setTitle('Current directory (./) is within PHP include path.');
151 }
152 return $status;
153 }
154
155 /**
156 * Check if file uploads are enabled in PHP
157 *
158 * @return Status\StatusInterface
159 */
160 protected function checkFileUploadEnabled() {
161 if (!ini_get('file_uploads')) {
162 $status = new Status\ErrorStatus();
163 $status->setTitle('File uploads not allowed in PHP');
164 $status->setMessage(
165 'file_uploads=' . ini_get('file_uploads') . LF .
166 'TYPO3 uses the ability to upload files from the browser in various cases.' .
167 ' If this flag is disabled in PHP, you won\'t be able to upload files.' .
168 ' But it doesn\'t end here, because not only are files not accepted by' .
169 ' the server - ALL content in the forms are discarded and therefore' .
170 ' nothing at all will be editable if you don\'t set this flag!' .
171 ' However if you cannot enable fileupload for some reason in PHP, alternatively' .
172 ' change the default form encoding value with \\$TYPO3_CONF_VARS[SYS][form_enctype].'
173 );
174 } else {
175 $status = new Status\OkStatus();
176 $status->setTitle('File uploads allowed in PHP');
177 }
178 return $status;
179 }
180
181 /**
182 * Check maximum file upload size against default value of 10MB
183 *
184 * @return Status\StatusInterface
185 */
186 protected function checkMaximumFileUploadSize() {
187 $maximumUploadFilesize = $this->getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
188 $configuredMaximumUploadFilesize = 1024 * $GLOBALS['TYPO3_CONF_VARS']['BE']['maxFileSize'];
189 if ($maximumUploadFilesize < $configuredMaximumUploadFilesize) {
190 $status = new Status\ErrorStatus();
191 $status->setTitle('PHP Maximum upload filesize too small');
192 $status->setMessage(
193 'PHP upload_max_filesize = ' . (int)ini_get('upload_max_filesize') . ' MB' . LF .
194 'TYPO3_CONF_VARS[BE][maxFileSize] = ' . (int)($configuredMaximumUploadFilesize / 1024 / 1024) . ' MB' . LF . LF .
195 'Currently PHP determines the limits for uploaded file\'s sizes and not TYPO3.' .
196 ' It is recommended that the value of upload_max_filesize is at least equal to the value' .
197 ' of TYPO3_CONF_VARS[BE][maxFileSize].'
198 );
199 } else {
200 $status = new Status\OkStatus();
201 $status->setTitle('PHP Maximum file upload size is higher than or equal to [BE][maxFileSize]');
202 }
203 return $status;
204 }
205
206 /**
207 * Check maximum post upload size correlates with maximum file upload
208 *
209 * @return Status\StatusInterface
210 */
211 protected function checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize() {
212 $maximumUploadFilesize = $this->getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
213 $maximumPostSize = $this->getBytesFromSizeMeasurement(ini_get('post_max_size'));
214 if ($maximumPostSize < $maximumUploadFilesize) {
215 $status = new Status\ErrorStatus();
216 $status->setTitle('Maximum size for POST requests is smaller than maximum upload filesize in PHP');
217 $status->setMessage(
218 'upload_max_filesize=' . ini_get('upload_max_filesize') . LF .
219 'post_max_size=' . ini_get('post_max_size') . LF .
220 'You have defined a maximum size for file uploads in PHP which' .
221 ' exceeds the allowed size for POST requests. Therefore the' .
222 ' file uploads can also not be larger than ' . ini_get('post_max_size') . '.'
223 );
224 } else {
225 $status = new Status\OkStatus();
226 $status->setTitle('Maximum post upload size correlates with maximum upload file size in PHP');
227 }
228 return $status;
229 }
230
231 /**
232 * Check memory settings
233 *
234 * @return Status\StatusInterface
235 */
236 protected function checkMemorySettings() {
237 $minimumMemoryLimit = 32;
238 $recommendedMemoryLimit = 64;
239 $memoryLimit = $this->getBytesFromSizeMeasurement(ini_get('memory_limit'));
240 if ($memoryLimit <= 0) {
241 $status = new Status\WarningStatus();
242 $status->setTitle('Unlimited memory limit for PHP');
243 $status->setMessage(
244 'PHP is configured not to limit memory usage at all. This is a risk' .
245 ' and should be avoided in production setup. In general it\'s best practice to limit this.' .
246 ' To be safe, set a limit in PHP, but with a minimum of ' . $recommendedMemoryLimit . 'MB:' . LF .
247 'memory_limit=' . $recommendedMemoryLimit . 'M'
248 );
249 } elseif ($memoryLimit < 1024 * 1024 * $minimumMemoryLimit) {
250 $status = new Status\ErrorStatus();
251 $status->setTitle('PHP Memory limit below ' . $minimumMemoryLimit . 'MB');
252 $status->setMessage(
253 'memory_limit=' . ini_get('memory_limit') . LF .
254 'Your system is configured to enforce a memory limit for PHP scripts lower than ' .
255 $minimumMemoryLimit . 'MB. It is required to raise the limit.' .
256 ' We recommend a minimum PHP memory limit of ' . $recommendedMemoryLimit . 'MB:' . LF .
257 'memory_limit=' . $recommendedMemoryLimit . 'M'
258 );
259 } elseif ($memoryLimit < 1024 * 1024 * $recommendedMemoryLimit) {
260 $status = new Status\WarningStatus();
261 $status->setTitle('PHP Memory limit below ' . $recommendedMemoryLimit . 'MB');
262 $status->setMessage(
263 'memory_limit=' . ini_get('memory_limit') . LF .
264 'Your system is configured to enforce a memory limit for PHP scripts lower than ' .
265 $recommendedMemoryLimit . 'MB.' .
266 ' A slim TYPO3 instance without many extensions will probably work, but you should monitor your' .
267 ' system for "allowed memory size of X bytes exhausted" messages, especially if using the backend.' .
268 ' To be on the safe side,' . ' we recommend a minimum PHP memory limit of ' .
269 $recommendedMemoryLimit . 'MB:' . LF .
270 'memory_limit=' . $recommendedMemoryLimit . 'M'
271 );
272 } else {
273 $status = new Status\OkStatus();
274 $status->setTitle('PHP Memory limit is equal to or more than ' . $recommendedMemoryLimit . 'MB');
275 }
276 return $status;
277 }
278
279 /**
280 * Check minimum PHP version
281 *
282 * @return Status\StatusInterface
283 */
284 protected function checkPhpVersion() {
285 $minimumPhpVersion = '5.3.7';
286 $currentPhpVersion = phpversion();
287 if (version_compare($currentPhpVersion, $minimumPhpVersion) < 0) {
288 $status = new Status\ErrorStatus();
289 $status->setTitle('PHP version too low');
290 $status->setMessage(
291 'Your PHP version ' . $currentPhpVersion . ' is too old. TYPO3 CMS does not run' .
292 ' with this version. Update to at least PHP ' . $minimumPhpVersion
293 );
294 } else {
295 $status = new Status\OkStatus();
296 $status->setTitle('PHP version is fine');
297 }
298 return $status;
299 }
300
301 /**
302 * Check maximum execution time
303 *
304 * @return Status\StatusInterface
305 */
306 protected function checkMaxExecutionTime() {
307 $minimumMaximumExecutionTime = 30;
308 $recommendedMaximumExecutionTime = 240;
309 $currentMaximumExecutionTime = ini_get('max_execution_time');
310 if ($currentMaximumExecutionTime == 0) {
311 if (PHP_SAPI === 'cli') {
312 $status = new Status\OkStatus();
313 $status->setTitle('Infinite PHP script execution time');
314 $status->setMessage(
315 'Maximum PHP script execution time is always set to infinite (0) in cli mode.' .
316 ' The setting used for web requests cannot be checked from command line.'
317 );
318 } else {
319 $status = new Status\WarningStatus();
320 $status->setTitle('Infinite PHP script execution time');
321 $status->setMessage(
322 'max_execution_time=' . $currentMaximumExecutionTime . LF .
323 'While TYPO3 is fine with this, you risk a denial-of-service for your system if for whatever' .
324 ' reason some script hangs in an infinite loop. You are usually on the safe side ' .
325 ' if it is reduced to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF .
326 'max_execution_time=' . $recommendedMaximumExecutionTime
327 );
328 }
329 } elseif ($currentMaximumExecutionTime < $minimumMaximumExecutionTime) {
330 $status = new Status\ErrorStatus();
331 $status->setTitle('Low PHP script execution time');
332 $status->setMessage(
333 'max_execution_time=' . $currentMaximumExecutionTime . LF .
334 'Your max_execution_time is too low. Some expensive operations in TYPO3 can take longer than that.' .
335 ' It is recommended to raise the limit to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF .
336 'max_execution_time=' . $recommendedMaximumExecutionTime
337 );
338 } elseif ($currentMaximumExecutionTime < $recommendedMaximumExecutionTime) {
339 $status = new Status\WarningStatus();
340 $status->setTitle('Low PHP script execution time');
341 $status->setMessage(
342 'max_execution_time=' . $currentMaximumExecutionTime . LF .
343 'Your max_execution_time is low. While TYPO3 often runs without problems' .
344 ' with ' . $minimumMaximumExecutionTime . ' seconds,' .
345 ' it may still happen that script execution is stopped before finishing' .
346 ' calculations. You should monitor the system for messages in this area' .
347 ' and maybe raise the limit to ' . $recommendedMaximumExecutionTime . ' seconds:' . LF .
348 'max_execution_time=' . $recommendedMaximumExecutionTime
349 );
350 } else {
351 $status = new Status\OkStatus();
352 $status->setTitle('Maximum PHP script execution time is equal to or more than '
353 . $recommendedMaximumExecutionTime);
354 }
355 return $status;
356 }
357
358 /**
359 * Check for disabled functions
360 *
361 * @return Status\StatusInterface
362 */
363 protected function checkDisableFunctions() {
364 $disabledFunctions = trim(ini_get('disable_functions'));
365
366 // Filter "disable_functions"
367 $disabledFunctionsArray = $this->trimExplode(',', $disabledFunctions);
368
369 // Array with strings to find
370 $findStrings = array(
371 // Disabled by default on Ubuntu OS but this is okay since the Core does not use them
372 'pcntl_',
373 );
374 foreach ($disabledFunctionsArray as $key => $disabledFunction) {
375 foreach ($findStrings as $findString) {
376 if (strpos($disabledFunction, $findString) !== FALSE) {
377 unset($disabledFunctionsArray[$key]);
378 }
379 }
380 }
381
382 if (strlen($disabledFunctions) > 0 && count($disabledFunctionsArray) > 0) {
383 $status = new Status\ErrorStatus();
384 $status->setTitle('Some PHP functions disabled');
385 $status->setMessage(
386 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . LF .
387 'These function(s) are disabled. TYPO3 uses some of those, so there might be trouble.' .
388 ' TYPO3 is designed to use the default set of PHP functions plus some common extensions.' .
389 ' Possibly these functions are disabled' .
390 ' due to security considerations and most likely the list would include a function like' .
391 ' exec() which is used by TYPO3 at various places. Depending on which exact functions' .
392 ' are disabled, some parts of the system may just break without further notice.'
393 );
394 } elseif (strlen($disabledFunctions) > 0 && count($disabledFunctionsArray) === 0) {
395 $status = new Status\NoticeStatus();
396 $status->setTitle('Some PHP functions currently disabled but OK');
397 $status->setMessage(
398 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . LF .
399 'These function(s) are disabled. TYPO3 uses currently none of those, so you are good to go.'
400 );
401 } else {
402 $status = new Status\OkStatus();
403 $status->setTitle('No disabled PHP functions');
404 }
405 return $status;
406 }
407
408 /**
409 * Check if it is possible to download external data (e.g. TER)
410 * Either allow_url_fopen must be enabled or curl must be used
411 *
412 * @return Status\OkStatus|Status\WarningStatus
413 */
414 protected function checkDownloadsPossible() {
415 $allowUrlFopen = (bool)ini_get('allow_url_fopen');
416 $curlEnabled = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse']);
417 if ($allowUrlFopen || $curlEnabled) {
418 $status = new Status\OkStatus();
419 $status->setTitle('Fetching external URLs is allowed');
420 } else {
421 $status = new Status\WarningStatus();
422 $status->setTitle('Fetching external URLs is not allowed');
423 $status->setMessage(
424 'Either enable PHP runtime setting "allow_url_fopen"' . LF . 'or enable curl by setting [SYS][curlUse] accordingly.'
425 );
426 }
427 return $status;
428 }
429
430 /**
431 * Check if safe mode is enabled
432 *
433 * @return Status\StatusInterface
434 */
435 protected function checkSafeMode() {
436 $safeModeEnabled = FALSE;
437 if (version_compare(phpversion(), '5.4', '<')) {
438 $safeModeEnabled = filter_var(
439 ini_get('safe_mode'),
440 FILTER_VALIDATE_BOOLEAN,
441 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
442 );
443 }
444 if ($safeModeEnabled) {
445 $status = new Status\ErrorStatus();
446 $status->setTitle('PHP safe mode on');
447 $status->setMessage(
448 'PHP safe_mode enabled. This is unsupported by TYPO3 CMS, it must be turned off:' . LF .
449 'safe_mode=Off'
450 );
451 } else {
452 $status = new Status\OkStatus();
453 $status->setTitle('PHP safe mode off');
454 }
455 return $status;
456 }
457
458 /**
459 * Check for doc_root ini setting
460 *
461 * @return Status\StatusInterface
462 */
463 protected function checkDocRoot() {
464 $docRootSetting = trim(ini_get('doc_root'));
465 if (strlen($docRootSetting) > 0) {
466 $status = new Status\NoticeStatus();
467 $status->setTitle('doc_root is set');
468 $status->setMessage(
469 'doc_root=' . $docRootSetting . LF .
470 'PHP cannot execute scripts' .
471 ' outside this directory. This setting is seldom used and must correlate' .
472 ' with your actual document root. You might be in trouble if your' .
473 ' TYPO3 CMS core code is linked to some different location.' .
474 ' If that is a problem, the setting must be changed.'
475 );
476 } else {
477 $status = new Status\OkStatus();
478 $status->setTitle('PHP doc_root is not set');
479 }
480 return $status;
481 }
482
483 /**
484 * Check open_basedir
485 *
486 * @return Status\StatusInterface
487 */
488 protected function checkOpenBaseDir() {
489 $openBaseDirSetting = trim(ini_get('open_basedir'));
490 if (strlen($openBaseDirSetting) > 0) {
491 $status = new Status\NoticeStatus();
492 $status->setTitle('PHP open_basedir is set');
493 $status->setMessage(
494 'open_basedir = ' . ini_get('open_basedir') . LF .
495 'This restricts TYPO3 to open and include files only in this' .
496 ' path. Please make sure that this does not prevent TYPO3 from running,' .
497 ' if for example your TYPO3 CMS core is linked to a different directory' .
498 ' not included in this path.'
499 );
500 } else {
501 $status = new Status\OkStatus();
502 $status->setTitle('PHP open_basedir is off');
503 }
504 return $status;
505 }
506
507 /**
508 * If xdebug is loaded, the default max_nesting_level of 100 must be raised
509 *
510 * @return Status\StatusInterface
511 */
512 protected function checkXdebugMaxNestingLevel() {
513 if (extension_loaded('xdebug')) {
514 $recommendedMaxNestingLevel = 250;
515 $currentMaxNestingLevel = ini_get('xdebug.max_nesting_level');
516 if ($currentMaxNestingLevel < $recommendedMaxNestingLevel) {
517 $status = new Status\ErrorStatus();
518 $status->setTitle('PHP xdebug.max_nesting_level too low');
519 $status->setMessage(
520 'xdebug.max_nesting_level=' . $currentMaxNestingLevel . LF .
521 'This setting controls the maximum number of nested function calls to protect against' .
522 ' infinite recursion. The current value is too low for TYPO3 CMS and must' .
523 ' be either raised or xdebug unloaded. A value of ' . $recommendedMaxNestingLevel .
524 ' is recommended. Warning: Expect fatal PHP errors in central parts of the CMS' .
525 ' if the value is not raised significantly to:' . LF .
526 'xdebug.max_nesting_level=' . $recommendedMaxNestingLevel
527 );
528 } else {
529 $status = new Status\OkStatus();
530 $status->setTitle('PHP xdebug.max_nesting_level ok');
531 }
532 } else {
533 $status = new Status\OkStatus();
534 $status->setTitle('PHP xdebug extension not loaded');
535 }
536 return $status;
537 }
538
539 /**
540 * Check accessibility and functionality of OpenSSL
541 *
542 * @return Status\StatusInterface
543 */
544 protected function checkOpenSslInstalled() {
545 if (extension_loaded('openssl')) {
546 $testKey = @openssl_pkey_new();
547 if (is_resource($testKey)) {
548 openssl_free_key($testKey);
549 $status = new Status\OkStatus();
550 $status->setTitle('PHP OpenSSL extension installed properly');
551 } else {
552 $status = new Status\ErrorStatus();
553 $status->setTitle('PHP OpenSSL extension not working');
554 $status->setMessage(
555 'Something went wrong while trying to create a new private key for testing.' .
556 ' Please check the integration of the PHP OpenSSL extension and if it is installed correctly.'
557 );
558 }
559 } else {
560 $status = new Status\ErrorStatus();
561 $status->setTitle('PHP OpenSSL extension not loaded');
562 $status->setMessage(
563 'OpenSSL is a PHP extension to encrypt/decrypt data between requests.' .
564 ' TYPO3 CMS requires it to be able to encrypt stored passwords to improve the security in the' .
565 ' database layer.'
566 );
567 }
568
569 return $status;
570 }
571
572 /**
573 * Check enabled suhosin
574 *
575 * @return Status\StatusInterface
576 */
577 protected function checkSuhosinLoaded() {
578 if ($this->isSuhosinLoaded()) {
579 $status = new Status\OkStatus();
580 $status->setTitle('PHP suhosin extension loaded');
581 } else {
582 $status = new Status\NoticeStatus();
583 $status->setTitle('PHP suhosin extension not loaded');
584 $status->setMessage(
585 'suhosin is an extension to harden the PHP environment. In general, it is' .
586 ' good to have it from a security point of view. While TYPO3 CMS works' .
587 ' fine with suhosin, it has some requirements different from the default settings' .
588 ' to be set if enabled.'
589 );
590 }
591 return $status;
592 }
593
594 /**
595 * Check suhosin.request.max_vars
596 *
597 * @return Status\StatusInterface
598 */
599 protected function checkSuhosinRequestMaxVars() {
600 $recommendedRequestMaxVars = 400;
601 if ($this->isSuhosinLoaded()) {
602 $currentRequestMaxVars = ini_get('suhosin.request.max_vars');
603 if ($currentRequestMaxVars < $recommendedRequestMaxVars) {
604 $status = new Status\ErrorStatus();
605 $status->setTitle('PHP suhosin.request.max_vars too low');
606 $status->setMessage(
607 'suhosin.request.max_vars=' . $currentRequestMaxVars . LF .
608 'This setting can lead to lost information if submitting forms with lots of data in TYPO3 CMS' .
609 ' (as the install tool does). It is highly recommended to raise this' .
610 ' to at least ' . $recommendedRequestMaxVars . ':' . LF .
611 'suhosin.request.max_vars=' . $recommendedRequestMaxVars
612 );
613 } else {
614 $status = new Status\OkStatus();
615 $status->setTitle('PHP suhosin.request.max_vars ok');
616 }
617 } else {
618 $status = new Status\InfoStatus();
619 $status->setTitle('Suhosin not loaded');
620 $status->setMessage(
621 'If enabling suhosin, suhosin.request.max_vars' .
622 ' should be set to at least ' . $recommendedRequestMaxVars . ':' . LF .
623 'suhosin.request.max_vars=' . $recommendedRequestMaxVars
624 );
625 }
626 return $status;
627 }
628
629 /**
630 * Check suhosin.post.max_vars
631 *
632 * @return Status\StatusInterface
633 */
634 protected function checkSuhosinPostMaxVars() {
635 $recommendedPostMaxVars = 400;
636 if ($this->isSuhosinLoaded()) {
637 $currentPostMaxVars = ini_get('suhosin.post.max_vars');
638 if ($currentPostMaxVars < $recommendedPostMaxVars) {
639 $status = new Status\ErrorStatus();
640 $status->setTitle('PHP suhosin.post.max_vars too low');
641 $status->setMessage(
642 'suhosin.post.max_vars=' . $currentPostMaxVars . LF .
643 'This setting can lead to lost information if submitting forms with lots of data in TYPO3 CMS' .
644 ' (as the install tool does). It is highly recommended to raise this' .
645 ' to at least ' . $recommendedPostMaxVars . ':' . LF .
646 'suhosin.post.max_vars=' . $recommendedPostMaxVars
647 );
648 } else {
649 $status = new Status\OkStatus();
650 $status->setTitle('PHP suhosin.post.max_vars ok');
651 }
652 } else {
653 $status = new Status\InfoStatus();
654 $status->setTitle('Suhosin not loaded');
655 $status->setMessage(
656 'If enabling suhosin, suhosin.post.max_vars' .
657 ' should be set to at least ' . $recommendedPostMaxVars . ':' . LF .
658 'suhosin.post.max_vars=' . $recommendedPostMaxVars
659 );
660 }
661 return $status;
662 }
663
664 /**
665 * Check suhosin.get.max_value_length
666 *
667 * @return Status\StatusInterface
668 */
669 protected function checkSuhosinGetMaxValueLength() {
670 $recommendedGetMaxValueLength = 2000;
671 if ($this->isSuhosinLoaded()) {
672 $currentGetMaxValueLength = ini_get('suhosin.get.max_value_length');
673 if ($currentGetMaxValueLength < $recommendedGetMaxValueLength) {
674 $status = new Status\ErrorStatus();
675 $status->setTitle('PHP suhosin.get.max_value_length too low');
676 $status->setMessage(
677 'suhosin.get.max_value_length=' . $currentGetMaxValueLength . LF .
678 'This setting can lead to lost information if submitting forms with lots of data in TYPO3 CMS' .
679 ' (as the install tool does). It is highly recommended to raise this' .
680 ' to at least ' . $recommendedGetMaxValueLength . ':' . LF .
681 'suhosin.get.max_value_length=' . $recommendedGetMaxValueLength
682 );
683 } else {
684 $status = new Status\OkStatus();
685 $status->setTitle('PHP suhosin.get.max_value_length ok');
686 }
687 } else {
688 $status = new Status\InfoStatus();
689 $status->setTitle('Suhosin not loaded');
690 $status->setMessage(
691 'If enabling suhosin, suhosin.get.max_value_length' .
692 ' should be set to at least ' . $recommendedGetMaxValueLength . ':' . LF .
693 'suhosin.get.max_value_length=' . $recommendedGetMaxValueLength
694 );
695 }
696 return $status;
697 }
698
699 /**
700 * Check suhosin.executor.include.whitelist contains phar
701 *
702 * @return Status\StatusInterface
703 */
704 protected function checkSuhosinExecutorIncludeWhiteListContainsPhar() {
705 if ($this->isSuhosinLoaded()) {
706 $currentWhiteListArray = $this->trimExplode(' ', ini_get('suhosin.executor.include.whitelist'));
707 if (!in_array('phar', $currentWhiteListArray)) {
708 $status = new Status\NoticeStatus();
709 $status->setTitle('PHP suhosin.executor.include.whitelist does not contain phar');
710 $status->setMessage(
711 'suhosin.executor.include.whitelist= ' . implode(' ', $currentWhiteListArray) . LF .
712 '"phar" is currently not a hard requirement of TYPO3 CMS but is nice to have and a possible' .
713 ' requirement in future versions. A useful setting is:' . LF .
714 'suhosin.executor.include.whitelist=phar vfs'
715 );
716 } else {
717 $status = new Status\OkStatus();
718 $status->setTitle('PHP suhosin.executor.include.whitelist contains phar');
719 }
720 } else {
721 $status = new Status\InfoStatus();
722 $status->setTitle('Suhosin not loaded');
723 $status->setMessage(
724 'If enabling suhosin, a useful setting is:' . LF .
725 'suhosin.executor.include.whitelist=phar vfs'
726 );
727 }
728 return $status;
729 }
730
731 /**
732 * Check suhosin.executor.include.whitelist contains vfs
733 *
734 * @return Status\StatusInterface
735 */
736 protected function checkSuhosinExecutorIncludeWhiteListContainsVfs() {
737 if ($this->isSuhosinLoaded()) {
738 $currentWhiteListArray = $this->trimExplode(' ', ini_get('suhosin.executor.include.whitelist'));
739 if (!in_array('vfs', $currentWhiteListArray)) {
740 $status = new Status\WarningStatus();
741 $status->setTitle('PHP suhosin.executor.include.whitelist does not contain vfs');
742 $status->setMessage(
743 'suhosin.executor.include.whitelist= ' . implode(' ', $currentWhiteListArray) . LF .
744 '"vfs" is currently not a hard requirement of TYPO3 CMS but tons of unit tests rely on it.' .
745 ' Furthermore, vfs will likely be a base for an additional compatibility layer in the future.' .
746 ' A useful setting is:' . LF .
747 'suhosin.executor.include.whitelist=phar vfs'
748 );
749 } else {
750 $status = new Status\OkStatus();
751 $status->setTitle('PHP suhosin.executor.include.whitelist contains vfs');
752 }
753 } else {
754 $status = new Status\InfoStatus();
755 $status->setTitle('Suhosin not loaded');
756 $status->setMessage(
757 'If enabling suhosin, a useful setting is:' . LF .
758 'suhosin.executor.include.whitelist=phar vfs'
759 );
760 }
761 return $status;
762 }
763
764 /**
765 * Check if some opcode cache is loaded
766 *
767 * @return Status\StatusInterface
768 */
769 protected function checkSomePhpOpcodeCacheIsLoaded() {
770 // Link to our wiki page, so we can update opcode cache issue information independent of TYPO3 CMS releases.
771 $wikiLink = 'For more information take a look in our wiki ' . TYPO3_URL_WIKI_OPCODECACHE . '.';
772 $opcodeCaches = \TYPO3\CMS\Core\Utility\OpcodeCacheUtility::getAllActive();
773 if (count($opcodeCaches) === 0) {
774 // Set status to notice. It needs to be notice so email won't be triggered.
775 $status = new Status\NoticeStatus();
776 $status->setTitle('No PHP opcode cache loaded');
777 $status->setMessage(
778 'PHP opcode caches hold a compiled version of executed PHP scripts in' .
779 ' memory and do not require to recompile a script each time it is accessed.' .
780 ' This can be a massive performance improvement and can reduce the load on a' .
781 ' server in general. A parse time reduction by factor three for fully cached' .
782 ' pages can be achieved easily if using an opcode cache.' .
783 LF . $wikiLink
784 );
785 } else {
786 $status = new Status\OkStatus();
787 $message = '';
788
789 foreach ($opcodeCaches as $opcodeCache => $properties) {
790 $message .= 'Name: ' . $opcodeCache . ' Version: ' . $properties['version'];
791 $message .= LF;
792
793 if ($properties['error']) {
794 // Set status to error if not already set
795 if ($status->getSeverity() !== 'error') {
796 $status = new Status\ErrorStatus();
797 }
798 $message .= ' This opcode cache is marked as malfunctioning by the TYPO3 CMS Team.';
799 } elseif ($properties['canInvalidate']) {
800 $message .= ' This opcode cache should work correctly and has good performance.';
801 } else {
802 // Set status to notice if not already error set. It needs to be notice so email won't be triggered.
803 if ($status->getSeverity() !== 'error' || $status->getSeverity() !== 'warning') {
804 $status = new Status\NoticeStatus();
805 }
806 $message .= ' This opcode cache may work correctly but has medium performance.';
807 }
808 $message .= LF;
809 }
810
811 $message .= $wikiLink;
812
813 // Set title of status depending on serverity
814 switch ($status->getSeverity()) {
815 case 'error':
816 $status->setTitle('A possibly malfunctioning PHP opcode cache is loaded');
817 break;
818 case 'warning':
819 $status->setTitle('A PHP opcode cache is loaded which may cause problems');
820 break;
821 case 'ok':
822 default:
823 $status->setTitle('A PHP opcode cache is loaded');
824 break;
825 }
826 $status->setMessage($message);
827 }
828 return $status;
829 }
830
831 /**
832 * Check doc comments can be fetched by reflection
833 *
834 * @return Status\StatusInterface
835 */
836 protected function checkReflectionDocComment() {
837 $testReflection = new \ReflectionMethod(get_class($this), __FUNCTION__);
838 if ($testReflection->getDocComment() === FALSE) {
839 $status = new Status\AlertStatus();
840 $status->setTitle('PHP Doc comment reflection broken');
841 $status->setMessage(
842 'TYPO3 CMS core extensions like extbase and fluid heavily rely on method'
843 . ' comment parsing to fetch annotations and add magic belonging to them.'
844 . ' This does not work in the current environment and so we cannot install'
845 . ' TYPO3 CMS.' . LF
846 . ' Here are some possibilities: ' . LF
847 . '* In Zend OPcache you can disable saving/loading comments. If you are using'
848 . ' Zend OPcache (included since PHP 5.5) then check your php.ini settings for'
849 . ' opcache.save_comments and opcache.load_comments and enable them.' . LF
850 . '* In Zend Optimizer+ you can disable saving comments. If you are using'
851 . ' Zend Optimizer+ then check your php.ini settings for'
852 . ' zend_optimizerplus.save_comments and enable it.' . LF
853 . '* The PHP extension eaccelerator is known to break this if'
854 . ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.'
855 . ' This compile flag must be specified, otherwise TYPO3 CMS will not work.' . LF
856 . 'For more information take a look in our wiki ' . TYPO3_URL_WIKI_OPCODECACHE . '.'
857 );
858 } else {
859 $status = new Status\OkStatus();
860 $status->setTitle('PHP Doc comment reflection works');
861 }
862 return $status;
863 }
864
865 /**
866 * Check if systemLocale setting is correct (locale exists in the OS)
867 *
868 * @return Status\StatusInterface
869 */
870 protected function checkSystemLocale() {
871
872 $currentLocale = setlocale(LC_CTYPE, 0);
873
874 // On Windows an empty locale value uses the regional settings from the Control Panel
875 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') {
876 $status = new Status\InfoStatus();
877 $status->setTitle('Empty systemLocale setting');
878 $status->setMessage(
879 '$GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is not set. This is fine as long as no UTF-8' .
880 ' file system is used.'
881 );
882 } elseif (setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']) === FALSE) {
883 $status = new Status\ErrorStatus();
884 $status->setTitle('Incorrect systemLocale setting');
885 $status->setMessage(
886 'Current value of the $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is incorrect. A locale with' .
887 ' this name doesn\'t exist in the operating system.'
888 );
889 setlocale(LC_CTYPE, $currentLocale);
890 } else {
891 $status = new Status\OkStatus();
892 $status->setTitle('System locale is correct');
893 }
894
895 return $status;
896 }
897
898 /**
899 * Checks whether we can use file names with UTF-8 characters.
900 * Configured system locale must support UTF-8 when UTF8filesystem is set
901 *
902 * @return Status\StatusInterface
903 */
904 protected function checkLocaleWithUTF8filesystem() {
905
906 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
907
908 // On Windows an empty local value uses the regional settings from the Control Panel
909 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') {
910 $status = new Status\ErrorStatus();
911 $status->setTitle('System locale not set on UTF-8 file system');
912 $status->setMessage(
913 '$GLOBALS[TYPO3_CONF_VARS][SYS][UTF8filesystem] is set, but $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale]' .
914 ' is empty. Make sure a valid locale which supports UTF-8 is set.'
915 );
916 } else {
917 $testString = 'ÖöĄĆŻĘĆćążąęó.jpg';
918 $currentLocale = setlocale(LC_CTYPE, 0);
919 $quote = TYPO3_OS === 'WIN' ? '"' : '\'';
920
921 setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
922
923 if (escapeshellarg($testString) === $quote . $testString . $quote) {
924 $status = new Status\OkStatus();
925 $status->setTitle('File names with UTF-8 characters can be used.');
926 } else {
927 $status = new Status\ErrorStatus();
928 $status->setTitle('System locale setting doesn\'t support UTF-8 file names.');
929 $status->setMessage(
930 'Please check your $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] setting.'
931 );
932 }
933
934 setlocale(LC_CTYPE, $currentLocale);
935 }
936
937
938 } else {
939 $status = new Status\OkStatus();
940 $status->setTitle('Skipping test, as UTF8filesystem is not enabled.');
941 }
942
943 return $status;
944 }
945
946 /**
947 * Checks thread stack size if on windows with apache
948 *
949 * @return Status\StatusInterface
950 */
951 protected function checkWindowsApacheThreadStackSize() {
952 if (
953 $this->isWindowsOs()
954 && substr($_SERVER['SERVER_SOFTWARE'], 0, 6) === 'Apache'
955 ) {
956 $status = new Status\WarningStatus();
957 $status->setTitle('Windows apache thread stack size');
958 $status->setMessage(
959 'This current value cannot be checked by the system, so please ignore this warning if it' .
960 ' is already taken care of: Fluid uses complex regular expressions which require a lot' .
961 ' of stack space during the first processing.' .
962 ' On Windows the default stack size for Apache is a lot smaller than on UNIX.' .
963 ' You can increase the size to 8MB (default on UNIX) by adding the following configuration' .
964 ' to httpd.conf and restarting Apache afterwards:' . LF .
965 '<IfModule mpm_winnt_module>' . LF .
966 'ThreadStackSize 8388608' . LF .
967 '</IfModule>'
968 );
969 } else {
970 $status = new Status\OkStatus();
971 $status->setTitle('Apache ThreadStackSize is not an issue on UNIX systems');
972 }
973 return $status;
974 }
975
976 /**
977 * Check if a specific required PHP extension is loaded
978 *
979 * @param string $extension
980 * @return Status\StatusInterface
981 */
982 protected function checkRequiredPhpExtension($extension) {
983 if (!extension_loaded($extension)) {
984 $status = new Status\ErrorStatus();
985 $status->setTitle('PHP extension ' . $extension . ' not loaded');
986 $status->setMessage(
987 'TYPO3 CMS uses PHP extension ' . $extension . ' but it is not loaded' .
988 ' in your environment. Change your environment to provide this extension.'
989 );
990 } else {
991 $status = new Status\OkStatus();
992 $status->setTitle('PHP extension ' . $extension . ' loaded');
993 }
994 return $status;
995 }
996
997 /**
998 * Check imagecreatetruecolor to verify gdlib works as expected
999 *
1000 * @return Status\StatusInterface
1001 */
1002 protected function checkGdLibTrueColorSupport() {
1003 if (function_exists('imagecreatetruecolor')) {
1004 $imageResource = @imagecreatetruecolor(50, 100);
1005 if (is_resource($imageResource)) {
1006 imagedestroy($imageResource);
1007 $status = new Status\OkStatus();
1008 $status->setTitle('PHP GD library true color works');
1009 } else {
1010 $status = new Status\ErrorStatus();
1011 $status->setTitle('PHP GD library true color support broken');
1012 $status->setMessage(
1013 'GD is loaded, but calling imagecreatetruecolor() fails.' .
1014 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
1015 );
1016 }
1017 } else {
1018 $status = new Status\ErrorStatus();
1019 $status->setTitle('PHP GD library true color support missing');
1020 $status->setMessage(
1021 'Gdlib is essential for TYPO3 CMS to work properly.'
1022 );
1023 }
1024 return $status;
1025 }
1026
1027 /**
1028 * Check gif support of GD library
1029 *
1030 * @return Status\StatusInterface
1031 */
1032 protected function checkGdLibGifSupport() {
1033 if (
1034 function_exists('imagecreatefromgif')
1035 && function_exists('imagegif')
1036 && (imagetypes() & IMG_GIF)
1037 ) {
1038 $imageResource = @imagecreatefromgif(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.gif');
1039 if (is_resource($imageResource)) {
1040 imagedestroy($imageResource);
1041 $status = new Status\OkStatus();
1042 $status->setTitle('PHP GD library has gif support');
1043 } else {
1044 $status = new Status\ErrorStatus();
1045 $status->setTitle('PHP GD library gif support broken');
1046 $status->setMessage(
1047 'GD is loaded, but calling imagecreatefromgif() fails.' .
1048 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
1049 );
1050 }
1051 } else {
1052 $status = new Status\ErrorStatus();
1053 $status->setTitle('PHP GD library gif support missing');
1054 $status->setMessage(
1055 'GD must be compiled with gif support. This is essential for' .
1056 ' TYPO3 CMS to work properly.'
1057 );
1058 }
1059 return $status;
1060 }
1061
1062 /**
1063 * Check jgp support of GD library
1064 *
1065 * @return Status\StatusInterface
1066 */
1067 protected function checkGdLibJpgSupport() {
1068 if (
1069 function_exists('imagecreatefromjpeg')
1070 && function_exists('imagejpeg')
1071 && (imagetypes() & IMG_JPG)
1072 ) {
1073 $status = new Status\OkStatus();
1074 $status->setTitle('PHP GD library has jpg support');
1075 } else {
1076 $status = new Status\ErrorStatus();
1077 $status->setTitle('PHP GD library jpg support missing');
1078 $status->setMessage(
1079 'GD must be compiled with jpg support. This is essential for' .
1080 ' TYPO3 CMS to work properly.'
1081 );
1082 }
1083 return $status;
1084 }
1085
1086 /**
1087 * Check png support of GD library
1088 *
1089 * @return Status\StatusInterface
1090 */
1091 protected function checkGdLibPngSupport() {
1092 if (
1093 function_exists('imagecreatefrompng')
1094 && function_exists('imagepng')
1095 && (imagetypes() & IMG_PNG)
1096 ) {
1097 $imageResource = @imagecreatefrompng(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.png');
1098 if (is_resource($imageResource)) {
1099 imagedestroy($imageResource);
1100 $status = new Status\OkStatus();
1101 $status->setTitle('PHP GD library has png support');
1102 } else {
1103 $status = new Status\ErrorStatus();
1104 $status->setTitle('PHP GD library png support broken');
1105 $status->setMessage(
1106 'GD is compiled with png support, but calling imagecreatefrompng() fails.' .
1107 ' Check your environment and fix it, png in GD lib is important' .
1108 ' for TYPO3 CMS to work properly.'
1109 );
1110 }
1111 } else {
1112 $status = new Status\ErrorStatus();
1113 $status->setTitle('PHP GD library png support missing');
1114 $status->setMessage(
1115 'GD must be compiled with png support. This is essential for' .
1116 ' TYPO3 CMS to work properly'
1117 );
1118 }
1119 return $status;
1120 }
1121
1122 /**
1123 * Check gdlib supports freetype
1124 *
1125 * @return Status\StatusInterface
1126 */
1127 protected function checkGdLibFreeTypeSupport() {
1128 if (function_exists('imagettftext')) {
1129 $status = new Status\OkStatus();
1130 $status->setTitle('PHP GD library has freetype font support');
1131 $status->setMessage(
1132 'There is a difference between the font size setting which the GD' .
1133 ' library should be supplied with. If installation is completed' .
1134 ' a test in the install tool helps to find out the value you need.'
1135 );
1136 } else {
1137 $status = new Status\ErrorStatus();
1138 $status->setTitle('PHP GD library freetype support missing');
1139 $status->setMessage(
1140 'Some core functionality and extension rely on the GD' .
1141 ' to render fonts on images. This support is missing' .
1142 ' in your environment. Install it.'
1143 );
1144 }
1145 return $status;
1146 }
1147
1148 /**
1149 * Create true type font test image
1150 *
1151 * @return Status\StatusInterface
1152 */
1153 protected function isTrueTypeFontDpiStandard() {
1154 if (function_exists('imageftbbox')) {
1155 // 20 Pixels at 96 DPI - the DefaultConfiguration
1156 $fontSize = (20 / 96 * 72);
1157 $textDimensions = @imageftbbox(
1158 $fontSize,
1159 0,
1160 __DIR__ . '/../../Resources/Private/Font/vera.ttf',
1161 'Testing true type support'
1162 );
1163 $fontBoxWidth = $textDimensions[2] - $textDimensions[0];
1164 if ($fontBoxWidth < 300 && $fontBoxWidth > 200) {
1165 $status = new Status\OkStatus();
1166 $status->setTitle('FreeType True Type Font DPI');
1167 $status->setMessage('Fonts are rendered by FreeType library. ' .
1168 'We need to ensure that the final dimensions are as expected. ' .
1169 'This server renderes fonts based on 96 DPI correctly'
1170 );
1171 } else {
1172 $status = new Status\NoticeStatus();
1173 $status->setTitle('FreeType True Type Font DPI');
1174 $status->setMessage('Fonts are rendered by FreeType library. ' .
1175 'This server does not render fonts as expected. ' .
1176 'Please configure FreeType or TYPO3_CONF_VARS[GFX][TTFdpi]'
1177 );
1178 }
1179 } else {
1180 $status = new Status\ErrorStatus();
1181 $status->setTitle('PHP GD library freetype2 support missing');
1182 $status->setMessage(
1183 'The core relies on GD library compiled into PHP with freetype2' .
1184 ' support. This is missing on your system. Please install it.'
1185 );
1186 }
1187
1188 return $status;
1189 }
1190
1191 /**
1192 * Check php magic quotes
1193 *
1194 * @return Status\StatusInterface
1195 */
1196 protected function checkPhpMagicQuotes() {
1197 $magicQuotesGpc = get_magic_quotes_gpc();
1198 if ($magicQuotesGpc) {
1199 $status = new Status\WarningStatus();
1200 $status->setTitle('PHP magic quotes on');
1201 $status->setMessage(
1202 'magic_quotes_gpc=' . $magicQuotesGpc . LF .
1203 'Setting magic_quotes_gpc is deprecated since PHP 5.3.' .
1204 ' You are advised to disable it until it is completely removed:' . LF .
1205 'magic_quotes_gpc=Off'
1206 );
1207 } else {
1208 $status = new Status\OkStatus();
1209 $status->setTitle('PHP magic quotes off');
1210 }
1211 return $status;
1212 }
1213
1214 /**
1215 * Check register globals
1216 *
1217 * @return Status\StatusInterface
1218 */
1219 protected function checkRegisterGlobals() {
1220 $registerGlobalsEnabled = filter_var(
1221 ini_get('register_globals'),
1222 FILTER_VALIDATE_BOOLEAN,
1223 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
1224 );
1225 if ($registerGlobalsEnabled === TRUE) {
1226 $status = new Status\ErrorStatus();
1227 $status->setTitle('PHP register globals on');
1228 $status->setMessage(
1229 'register_globals=' . ini_get('register_globals') . LF .
1230 'TYPO3 requires PHP setting "register_globals" set to off.' .
1231 ' This ancient PHP setting is a big security problem and should' .
1232 ' never be enabled:' . LF .
1233 'register_globals=Off'
1234 );
1235 } else {
1236 $status = new Status\OkStatus();
1237 $status->setTitle('PHP register globals off');
1238 }
1239 return $status;
1240 }
1241
1242 /**
1243 * Check for bug in libxml
1244 *
1245 * @return Status\StatusInterface
1246 */
1247 protected function checkLibXmlBug() {
1248 $sampleArray = array('Test>><<Data');
1249
1250 $xmlContent = '<numIndex index="0">Test&gt;&gt;&lt;&lt;Data</numIndex>' . LF;
1251
1252 $xml = \TYPO3\CMS\Core\Utility\GeneralUtility::array2xml($sampleArray, '', -1);
1253
1254 if ($xmlContent !== $xml) {
1255 $status = new Status\ErrorStatus();
1256 $status->setTitle('PHP libxml bug present');
1257 $status->setMessage(
1258 'Some hosts have problems saving ">><<" in a flexform.' .
1259 ' To fix this, enable [BE][flexformForceCDATA] in' .
1260 ' All Configuration.'
1261 );
1262 } else {
1263 $status = new Status\OkStatus();
1264 $status->setTitle('PHP libxml bug not present');
1265 }
1266 return $status;
1267 }
1268
1269 /**
1270 * Helper methods
1271 */
1272
1273 /**
1274 * Validate a given IP address.
1275 *
1276 * @param string $ip IP address to be tested
1277 * @return boolean
1278 */
1279 protected function isValidIp($ip) {
1280 return filter_var($ip, FILTER_VALIDATE_IP) !== FALSE;
1281 }
1282
1283 /**
1284 * Test if this instance runs on windows OS
1285 *
1286 * @return boolean TRUE if operating system is windows
1287 */
1288 protected function isWindowsOs() {
1289 $windowsOs = FALSE;
1290 if (!stristr(PHP_OS, 'darwin') && stristr(PHP_OS, 'win')) {
1291 $windowsOs = TRUE;
1292 }
1293 return $windowsOs;
1294 }
1295
1296 /**
1297 * Helper method to find out if suhosin extension is loaded
1298 *
1299 * @return boolean TRUE if suhosin PHP extension is loaded
1300 */
1301 protected function isSuhosinLoaded() {
1302 $suhosinLoaded = FALSE;
1303 if (extension_loaded('suhosin')) {
1304 $suhosinLoaded = TRUE;
1305 }
1306 return $suhosinLoaded;
1307 }
1308
1309 /**
1310 * Helper method to explode a string by delimeter and throw away empty values.
1311 * Removes empty values from result array.
1312 *
1313 * @param string $delimiter Delimiter string to explode with
1314 * @param string $string The string to explode
1315 * @return array Exploded values
1316 */
1317 protected function trimExplode($delimiter, $string) {
1318 $explodedValues = explode($delimiter, $string);
1319 $resultWithPossibleEmptyValues = array_map('trim', $explodedValues);
1320 $result = array();
1321 foreach ($resultWithPossibleEmptyValues as $value) {
1322 if ($value !== '') {
1323 $result[] = $value;
1324 }
1325 }
1326 return $result;
1327 }
1328
1329 /**
1330 * Helper method to get the bytes value from a measurement string like "100k".
1331 *
1332 * @param string $measurement The measurement (e.g. "100k")
1333 * @return integer The bytes value (e.g. 102400)
1334 */
1335 protected function getBytesFromSizeMeasurement($measurement) {
1336 $bytes = doubleval($measurement);
1337 if (stripos($measurement, 'G')) {
1338 $bytes *= 1024 * 1024 * 1024;
1339 } elseif (stripos($measurement, 'M')) {
1340 $bytes *= 1024 * 1024;
1341 } elseif (stripos($measurement, 'K')) {
1342 $bytes *= 1024;
1343 }
1344 return $bytes;
1345 }
1346 }