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