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