[TASK] Fix some typos in environment check.
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / SystemEnvironment / Check.php
1 <?php
2 namespace TYPO3\CMS\Install\SystemEnvironment;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Check system environment status
29 *
30 * This class is a hardcoded requirement check of the underlying
31 * server and PHP system.
32 *
33 * The class *must not* check for any TYPO3 specific things like
34 * specific configuration values or directories. It should not fail
35 * if there is no TYPO3 at all.
36 *
37 * This class is instantiated as the *very first* class during
38 * installation. It is meant to be *standalone* und must not have
39 * any requirements, except the status classes. It must be possible
40 * to run this script separated from the rest of the core, without
41 * dependencies.
42 *
43 * This means especially:
44 * * No hooks or anything like that
45 * * No usage of *any* TYPO3 code like GeneralUtility
46 * * No require of anything but the status classes
47 * * No localization
48 *
49 * The status messages and title *must not* include HTML, use plain
50 * text only. The return values of this class are not bound to HTML
51 * and can be used in different scopes (eg. as json array).
52 *
53 * @author Christian Kuhn <lolli@schwarzbu.ch>
54 */
55 class Check {
56
57 /**
58 * @var array List of required PHP extensions
59 */
60 protected $requiredPhpExtensions = array(
61 'fileinfo',
62 'filter',
63 'gd',
64 'hash',
65 'json',
66 'mysqli',
67 'openssl',
68 'pcre',
69 'session',
70 'soap',
71 'SPL',
72 'standard',
73 'xml',
74 'zip',
75 'zlib'
76 );
77
78 /**
79 * Constructor to load further classes
80 */
81 public function __construct() {
82 require(__DIR__ . '/StatusInterface.php');
83 require(__DIR__ . '/AbstractStatus.php');
84 require(__DIR__ . '/NoticeStatus.php');
85 require(__DIR__ . '/InfoStatus.php');
86 require(__DIR__ . '/OkStatus.php');
87 require(__DIR__ . '/WarningStatus.php');
88 require(__DIR__ . '/ErrorStatus.php');
89 }
90
91 /**
92 * Get all status information as array with status objects
93 *
94 * @return array<\TYPO3\CMS\Install\SystemEnvironment\StatusInterface>
95 */
96 public function getStatus() {
97 $statusArray = array();
98 $statusArray[] = $this->checkCurrentDirectoryIsInIncludePath();
99 $statusArray[] = $this->checkFileUploadEnabled();
100 $statusArray[] = $this->checkMaximumFileUploadSize();
101 $statusArray[] = $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize();
102 $statusArray[] = $this->checkMemorySettings();
103 $statusArray[] = $this->checkPhpVersion();
104 $statusArray[] = $this->checkMaxExecutionTime();
105 $statusArray[] = $this->checkDisableFunctions();
106 $statusArray[] = $this->checkSafeMode();
107 $statusArray[] = $this->checkDocRoot();
108 $statusArray[] = $this->checkSqlSafeMode();
109 $statusArray[] = $this->checkOpenBaseDir();
110 $statusArray[] = $this->checkOpenSslInstalled();
111 $statusArray[] = $this->checkSuhosinLoaded();
112 $statusArray[] = $this->checkSuhosinRequestMaxVars();
113 $statusArray[] = $this->checkSuhosinPostMaxVars();
114 $statusArray[] = $this->checkSuhosinGetMaxValueLength();
115 $statusArray[] = $this->checkSuhosinExecutorIncludeWhitelistContainsPhar();
116 $statusArray[] = $this->checkSuhosinExecutorIncludeWhitelistContainsVfs();
117 $statusArray[] = $this->checkSomePhpOpcodeCacheIsLoaded();
118 $statusArray[] = $this->checkReflectionDocComment();
119 $statusArray[] = $this->checkWindowsApacheThreadStackSize();
120 foreach ($this->requiredPhpExtensions as $extension) {
121 $statusArray[] = $this->checkRequiredPhpExtension($extension);
122 }
123 $statusArray[] = $this->checkMailCapabilities();
124 $statusArray[] = $this->checkGdLibTrueColorSupport();
125 $statusArray[] = $this->checkGdLibGifSupport();
126 $statusArray[] = $this->checkGdLibJpgSupport();
127 $statusArray[] = $this->checkGdLibPngSupport();
128 $statusArray[] = $this->checkGdLibFreeTypeSupport();
129 $statusArray[] = $this->checkPhpMagicQuotes();
130 $statusArray[] = $this->checkRegisterGlobals();
131 return $statusArray;
132 }
133
134 /**
135 * Checks if current directory (.) is in PHP include path
136 *
137 * @return WarningStatus|OkStatus
138 */
139 protected function checkCurrentDirectoryIsInIncludePath() {
140 $includePath = ini_get('include_path');
141 $delimiter = $this->isWindowsOs() ? ';' : ':';
142 $pathArray = $this->trimExplode($delimiter, $includePath);
143 if (!in_array('.', $pathArray)) {
144 $status = new WarningStatus();
145 $status->setTitle('Current directory (./) is not in include path');
146 $status->setMessage(
147 'include_path = ' . implode(' ', $pathArray) .
148 ' Normally the current path, \'.\', is included in the' .
149 ' include_path of PHP. Although TYPO3 does not rely on this,' .
150 ' it is an unusual setting that may introduce problems for' .
151 ' some extensions.'
152 );
153 } else {
154 $status = new OkStatus();
155 $status->setTitle('Current directory (./) is in include path.');
156 }
157 return $status;
158 }
159
160 /**
161 * Check if file uploads are enabled in PHP
162 *
163 * @return ErrorStatus|OkStatus
164 */
165 protected function checkFileUploadEnabled() {
166 if (!ini_get('file_uploads')) {
167 $status = new ErrorStatus();
168 $status->setTitle('File uploads not allowed');
169 $status->setMessage(
170 'file_uploads=' . ini_get('file_uploads') .
171 ' TYPO3 uses the ability to upload files from the browser in various cases.' .
172 ' As long as this flag is disabled, you\'ll not be able to upload files.' .
173 ' But it doesn\'t end here, because not only are files not accepted by' .
174 ' the server - ALL content in the forms are discarded and therefore' .
175 ' nothing at all will be editable if you don\'t set this flag!' .
176 ' However if you cannot enable fileupload for some reason alternatively' .
177 ' you change the default form encoding value with \\$TYPO3_CONF_VARS[SYS][form_enctype].'
178 );
179 } else {
180 $status = new OkStatus();
181 $status->setTitle('File uploads allowed');
182 }
183 return $status;
184 }
185
186 /**
187 * Check maximum file upload size against default value of 10MB
188 *
189 * @return ErrorStatus|OkStatus
190 */
191 protected function checkMaximumFileUploadSize() {
192 $maximumUploadFilesize = $this->getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
193 if ($maximumUploadFilesize < 1024 * 1024 * 10) {
194 $status = new ErrorStatus();
195 $status->setTitle('Maximum upload filesize too small');
196 $status->setMessage(
197 'upload_max_filesize=' . ini_get('upload_max_filesize') .
198 '. By default TYPO3 supports uploading, copying and moving' .
199 ' files of sizes up to 10MB (you can alter the TYPO3 defaults' .
200 ' by the config option TYPO3_CONF_VARS[BE][maxFileSize]).' .
201 ' Your current value is below this, so at this point, PHP sets' .
202 ' the limits for uploaded filesizes and not TYPO3.'
203 );
204 } else {
205 $status = new OkStatus();
206 $status->setTitle('Maximum file upload size is higher or equal to 10MB');
207 }
208 return $status;
209 }
210
211 /**
212 * Check maximum post upload size correlates with maximum file upload
213 *
214 * @return ErrorStatus|OkStatus
215 */
216 protected function checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize() {
217 $maximumUploadFilesize = $this->getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
218 $maximumPostSize = $this->getBytesFromSizeMeasurement(ini_get('post_max_size'));
219 if ($maximumPostSize < $maximumUploadFilesize) {
220 $status = new ErrorStatus();
221 $status->setTitle('Maximum size for POST requests is smaller than max. upload filesize');
222 $status->setMessage(
223 'upload_max_filesize=' . ini_get('upload_max_filesize') .
224 ', post_max_size=' . ini_get('post_max_size') .
225 ' You have defined a maximum size for file uploads which' .
226 ' exceeds the allowed size for POST requests. Therefore the' .
227 ' file uploads can not be larger than ' . ini_get('post_max_size') . '.'
228 );
229 } else {
230 $status = new OkStatus();
231 $status->setTitle('Maximum post upload size correlates with maximum upload file size');
232 }
233 return $status;
234 }
235
236 /**
237 * Check memory settings
238 *
239 * @return ErrorStatus|WarningStatus|OkStatus
240 */
241 protected function checkMemorySettings() {
242 $memoryLimit = $this->getBytesFromSizeMeasurement(ini_get('memory_limit'));
243 if ($memoryLimit <= 0) {
244 $status = new WarningStatus();
245 $status->setTitle('Unlimited memory limit!');
246 $status->setMessage(
247 'Your webserver is configured to not limit PHP memory usage at all. This is a risk' .
248 ' and should be avoided in production setup. In general it\'s best practice to limit this' .
249 ' in the configuration of your webserver. To be safe, ask the system administrator of the' .
250 ' webserver to raise the limit to something over 64MB'
251 );
252 } elseif ($memoryLimit < 1024 * 1024 * 32) {
253 $status = new ErrorStatus();
254 $status->setTitle('Memory limit below 32MB');
255 $status->setMessage(
256 'memory_limit=' . ini_get('memory_limit') .
257 ' Your system is configured to enforce a memory limit of PHP scripts lower than 32MB.' .
258 ' There is nothing else to do than raise the limit. To be safe, ask the system' .
259 ' administrator of the webserver to raise the limit to 64MB.'
260 );
261 } elseif ($memoryLimit < 1024 * 1024 * 64) {
262 $status = new WarningStatus();
263 $status->setTitle('Memory limit below 64MB');
264 $status->setMessage(
265 'memory_limit=' . ini_get('memory_limit') .
266 ' Your system is configured to enforce a memory limit of PHP scripts lower than 64MB.' .
267 ' A slim TYPO3 instance without many extensions will probably work, but you should ' .
268 ' monitor your system for exhausted messages, especially if using the backend. ' .
269 ' To be on the safe side, it would be better to raise the PHP memory limit to 64MB or more.'
270 );
271 } else {
272 $status = new OkStatus();
273 $status->setTitle('Memory limit equal 64MB or more');
274 }
275 return $status;
276 }
277
278 /**
279 * Check minimum PHP version
280 *
281 * @return ErrorStatus|OkStatus
282 */
283 protected function checkPhpVersion() {
284 $minimumPhpVersion = '5.3.0';
285 $recommendedPhpVersion = '5.3.7';
286 $currentPhpVersion = phpversion();
287 if (version_compare($currentPhpVersion, $minimumPhpVersion) < 0) {
288 $status = new ErrorStatus();
289 $status->setTitle('PHP version too low');
290 $status->setMessage(
291 'Your PHP version ' . $currentPhpVersion . ' is too old. TYPO3 CMS does not run' .
292 ' with this version. Update to at least PHP ' . $recommendedPhpVersion
293 );
294 } elseif (version_compare($currentPhpVersion, $recommendedPhpVersion) < 0) {
295 $status = new WarningStatus();
296 $status->setTitle('PHP version below recommended version');
297 $status->setMessage(
298 'Your PHP version ' . $currentPhpVersion . ' is below the recommended version' .
299 ' ' . $recommendedPhpVersion . '. TYPO3 CMS will mostly run with your PHP' .
300 ' version, but it is not officially supported. Expect some problems,' .
301 ' and a performance penalty, monitor your system for errors and watch' .
302 ' out for an upgrade, soon.'
303 );
304 } else {
305 $status = new OkStatus();
306 $status->setTitle('PHP version is fine');
307 }
308 return $status;
309 }
310
311 /**
312 * Check maximum execution time
313 *
314 * @return ErrorStatus|WarningStatus|OkStatus
315 */
316 protected function checkMaxExecutionTime() {
317 $minimumMaximumExecutionTime = 30;
318 $recommendedMaximumExecutionTime = 240;
319 $currentMaximumExecutionTime = ini_get('max_execution_time');
320 if ($currentMaximumExecutionTime == 0 && PHP_SAPI !== 'cli') {
321 $status = new WarningStatus();
322 $status->setTitle('Infinite PHP script execution time');
323 $status->setMessage(
324 'Your max_execution_time is set to 0 (infinite). While TYPO3 is fine' .
325 ' with this, you risk a denial-of-service of you system if for whatever' .
326 ' reason some script hangs in an infinite loop. You are usually on safe side ' .
327 ' if max_execution_time is reduced to ' . $recommendedMaximumExecutionTime
328 );
329 } elseif ($currentMaximumExecutionTime < $minimumMaximumExecutionTime) {
330 $status = new ErrorStatus();
331 $status->setTitle('Low PHP script execution time');
332 $status->setMessage(
333 'Your max_execution_time is set to ' . $currentMaximumExecutionTime .
334 '. Some expensive operation in TYPO3 can take longer than that. It is advised' .
335 ' to raise max_execution_time to ' . $recommendedMaximumExecutionTime
336 );
337 } elseif ($currentMaximumExecutionTime < $recommendedMaximumExecutionTime) {
338 $status = new WarningStatus();
339 $status->setTitle('Low PHP script execution time');
340 $status->setMessage(
341 'Your max_execution_time is set to ' . $currentMaximumExecutionTime .
342 '. While TYPO3 often runs without problems with ' . $minimumMaximumExecutionTime .
343 ' it still may happen that script execution is stopped before finishing' .
344 ' calculations. You should monitor the system for messages in this area' .
345 ' and maybe raise the limit to ' . $recommendedMaximumExecutionTime . '.'
346 );
347 } else {
348 $status = new OkStatus();
349 $status->setTitle('Maximum PHP script execution equals ' . $recommendedMaximumExecutionTime . ' or more');
350 }
351 return $status;
352 }
353
354 /**
355 * Check for disabled functions
356 *
357 * @return ErrorStatus|OkStatus
358 */
359 protected function checkDisableFunctions() {
360 $disabledFunctions = trim(ini_get('disable_functions'));
361
362 // Filter "disable_functions"
363 $disabledFunctionsArray = $this->trimExplode(',', $disabledFunctions);
364
365 // Array with strings to find
366 $findStrings = array(
367 // Disabled by default on Ubuntu OS but this is okay since the Core does not use them
368 'pcntl_',
369 );
370 foreach ($disabledFunctionsArray as $key => $disabledFunction) {
371 foreach ($findStrings as $findString) {
372 if (strpos($disabledFunction, $findString) !== FALSE) {
373 unset($disabledFunctionsArray[$key]);
374 }
375 }
376 }
377
378 if (strlen($disabledFunctions) > 0 && count($disabledFunctionsArray) > 0) {
379 $status = new ErrorStatus();
380 $status->setTitle('Some PHP functions disabled');
381 $status->setMessage(
382 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . '. These function(s)' .
383 ' are disabled. TYPO3 uses some of those, so there might be trouble. TYPO3 is designed to use the' .
384 ' default set of PHP functions plus some common extensions. 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 NoticeStatus();
391 $status->setTitle('Some PHP functions currently disabled but OK');
392 $status->setMessage(
393 'disable_functions=' . implode(' ', explode(',', $disabledFunctions)) . '. These function(s)' .
394 ' are disabled. TYPO3 uses currently none of those, so you are good to go.'
395 );
396 } else {
397 $status = new OkStatus();
398 $status->setTitle('No disabled PHP functions');
399 }
400 return $status;
401 }
402
403 /**
404 * Check if safe mode is enabled
405 *
406 * @return ErrorStatus|OkStatus
407 */
408 protected function checkSafeMode() {
409 $safeModeEnabled = FALSE;
410 if (version_compare(phpversion(), '5.4', '<')) {
411 $safeModeEnabled = filter_var(
412 ini_get('safe_mode'),
413 FILTER_VALIDATE_BOOLEAN,
414 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
415 );
416 }
417 if ($safeModeEnabled) {
418 $status = new ErrorStatus();
419 $status->setTitle('PHP safe mode on');
420 $status->setMessage(
421 'safe_mode enabled. This is unsupported by TYPO3 CMS, it must be turned off.'
422 );
423 } else {
424 $status = new OkStatus();
425 $status->setTitle('PHP safe mode off');
426 }
427 return $status;
428 }
429
430 /**
431 * Check for doc_root ini setting
432 *
433 * @return NoticeStatus|OkStatus
434 */
435 protected function checkDocRoot() {
436 $docRootSetting = trim(ini_get('doc_root'));
437 if (strlen($docRootSetting) > 0) {
438 $status = new NoticeStatus();
439 $status->setTitle('doc_root is set');
440 $status->setMessage(
441 'doc_root=' . $docRootSetting . ' PHP cannot execute scripts' .
442 ' outside this directory. This setting is used seldom and must correlate' .
443 ' with your actual document root. You might be in trouble if your' .
444 ' TYPO3 CMS core code is linked to some different location.' .
445 ' If that is a problem, the setting must be adapted.'
446 );
447 } else {
448 $status = new OkStatus();
449 $status->setTitle('PHP doc_root is not set');
450 }
451 return $status;
452 }
453
454 /**
455 * Check sql.safe_mode
456 *
457 * @return OkStatus|WarningStatus
458 */
459 protected function checkSqlSafeMode() {
460 $sqlSafeModeEnabled = FALSE;
461 if (version_compare(phpversion(), '5.4', '<')) {
462 $sqlSafeModeEnabled = filter_var(
463 ini_get('sql.safe_mode'),
464 FILTER_VALIDATE_BOOLEAN,
465 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
466 );
467 }
468 if ($sqlSafeModeEnabled) {
469 $status = new WarningStatus();
470 $status->setTitle('sql.safe_mode is enabled');
471 $status->setMessage(
472 'This means that you can only connect to the database with a' .
473 ' username corresponding to the user of the webserver process' .
474 ' or file owner. Consult your ISP for information about this.' .
475 ' The owner of the current file is: ' . get_current_user()
476 );
477 } else {
478 $status = new OkStatus();
479 $status->setTitle('PHP sql.safe_mode is off');
480 }
481 return $status;
482 }
483
484 /**
485 * Check open_basedir
486 *
487 * @return NoticeStatus|OkStatus
488 */
489 protected function checkOpenBaseDir() {
490 $openBaseDirSetting = trim(ini_get('open_basedir'));
491 if (strlen($openBaseDirSetting) > 0) {
492 $status = new NoticeStatus();
493 $status->setTitle('open_basedir set');
494 $status->setMessage(
495 'open_basedir = ' . ini_get('open_basedir') .
496 ' This restricts TYPO3 to open and include files only in this' .
497 ' path. Please make sure that this does not prevent TYPO3 from running,' .
498 ' if for example your TYPO3 CMS core is linked to a different directory' .
499 ' not included in this path.'
500 );
501 } else {
502 $status = new OkStatus();
503 $status->setTitle('PHP open_basedir is off');
504 }
505 return $status;
506 }
507
508 /**
509 * Check accessibility and functionality of OpenSSL
510 */
511 protected function checkOpenSslInstalled() {
512 if (extension_loaded('openssl')) {
513 $testKey = @openssl_pkey_new();
514 if (is_resource($testKey)) {
515 openssl_free_key($testKey);
516 $status = new OkStatus();
517 $status->setTitle('OpenSSL installed properly');
518 } else {
519 $status = new ErrorStatus();
520 $status->setTitle('OpenSSL extension not working');
521 $status->setMessage(
522 'Something went wrong while trying to create a new private key. ' .
523 'Please check your OpenSSL integration to verify the extension is installed correctly.'
524 );
525 }
526 } else {
527 $status = new ErrorStatus();
528 $status->setTitle('OpenSSL extension not loaded');
529 $status->setMessage(
530 'OpenSSL is an extension to encrypt/decrypt data between requests. ' .
531 'TYPO3 CMS needs it to be able to store passwords encrypted to improve the security on database layer.'
532 );
533 }
534
535 return $status;
536 }
537
538 /**
539 * Check enabled suhosin
540 *
541 * @return NoticeStatus|OkStatus
542 */
543 protected function checkSuhosinLoaded() {
544 if ($this->isSuhosinLoaded()) {
545 $status = new OkStatus();
546 $status->setTitle('PHP suhosin extension loaded');
547 } else {
548 $status = new NoticeStatus();
549 $status->setTitle('PHP suhosin extension not loaded');
550 $status->setMessage(
551 'suhosin is an extension to harden the PHP environment. In general, it is' .
552 ' good to have it from a security point of view. While TYPO3 CMS works' .
553 ' fine with suhosin, it has some requirements different from default settings' .
554 ' to be set if enabled.'
555 );
556 }
557 return $status;
558 }
559
560 /**
561 * Check suhosin.request.max_vars
562 *
563 * @return ErrorStatus|InfoStatus|OkStatus
564 */
565 protected function checkSuhosinRequestMaxVars() {
566 $recommendedRequestMaxVars = 400;
567 if ($this->isSuhosinLoaded()) {
568 $currentRequestMaxVars = ini_get('suhosin.request.max_vars');
569 if ($currentRequestMaxVars < $recommendedRequestMaxVars) {
570 $status = new ErrorStatus();
571 $status->setTitle('PHP suhosin.request.max_vars not high enough');
572 $status->setMessage(
573 'suhosin.request.max_vars=' . $currentRequestMaxVars . '. This setting' .
574 ' can lead to lost information if submitting big forms in TYPO3 CMS like' .
575 ' it is done in the install tool. It is heavily recommended to raise this' .
576 ' to at least ' . $recommendedRequestMaxVars
577 );
578 } else {
579 $status = new OkStatus();
580 $status->setTitle('PHP suhosin.request.max_vars ok');
581 }
582 } else {
583 $status = new 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 . '.'
588 );
589 }
590 return $status;
591 }
592
593 /**
594 * Check suhosin.post.max_vars
595 *
596 * @return ErrorStatus|InfoStatus|OkStatus
597 */
598 protected function checkSuhosinPostMaxVars() {
599 $recommendedPostMaxVars = 400;
600 if ($this->isSuhosinLoaded()) {
601 $currentPostMaxVars = ini_get('suhosin.post.max_vars');
602 if ($currentPostMaxVars < $recommendedPostMaxVars) {
603 $status = new ErrorStatus();
604 $status->setTitle('PHP suhosin.post.max_vars not high enough');
605 $status->setMessage(
606 'suhosin.post.max_vars=' . $currentPostMaxVars . '. This setting' .
607 ' can lead to lost information if submitting big forms in TYPO3 CMS like' .
608 ' it is done in the install tool. It is heavily recommended to raise this' .
609 ' to at least ' . $recommendedPostMaxVars . '.'
610 );
611 } else {
612 $status = new OkStatus();
613 $status->setTitle('PHP suhosin.post.max_vars ok');
614 }
615 } else {
616 $status = new InfoStatus();
617 $status->setTitle('Suhosin not loaded');
618 $status->setMessage(
619 'If enabling suhosin, suhosin.post.max_vars' .
620 ' should be set to at least ' . $recommendedPostMaxVars . '.'
621 );
622 }
623 return $status;
624 }
625
626 /**
627 * Check suhosin.get.max_value_length
628 *
629 * @return ErrorStatus|InfoStatus|OkStatus
630 */
631 protected function checkSuhosinGetMaxValueLength() {
632 $recommendedGetMaxValueLength = 2000;
633 if ($this->isSuhosinLoaded()) {
634 $currentGetMaxValueLength = ini_get('suhosin.get.max_value_length');
635 if ($currentGetMaxValueLength < $recommendedGetMaxValueLength) {
636 $status = new ErrorStatus();
637 $status->setTitle('PHP suhosin.get.max_value_length not high enough');
638 $status->setMessage(
639 'suhosin.get.max_value_length=' . $currentGetMaxValueLength . '. This setting' .
640 ' can lead to lost information if submitting big forms in TYPO3 CMS like' .
641 ' it is done in the install tool. It is heavily recommended to raise this' .
642 ' to at least ' . $recommendedGetMaxValueLength . '.'
643 );
644 } else {
645 $status = new OkStatus();
646 $status->setTitle('PHP suhosin.get.max_value_length ok');
647 }
648 } else {
649 $status = new InfoStatus();
650 $status->setTitle('Suhosin not loaded');
651 $status->setMessage(
652 'If enabling suhosin, suhosin.get.max_value_length' .
653 ' should be set to at least ' . $recommendedGetMaxValueLength
654 );
655 }
656 return $status;
657 }
658
659 /**
660 * Check suhosin.executor.include.whitelist contains phar
661 *
662 * @return NoticeStatus|InfoStatus|OkStatus
663 */
664 protected function checkSuhosinExecutorIncludeWhiteListContainsPhar() {
665 if ($this->isSuhosinLoaded()) {
666 $currentWhiteListArray = $this->trimExplode(' ', ini_get('suhosin.executor.include.whitelist'));
667 if (!in_array('phar', $currentWhiteListArray)) {
668 $status = new NoticeStatus();
669 $status->setTitle('PHP suhosin.executor.include.whitelist does not contain phar');
670 $status->setMessage(
671 'suhosin.executor.include.whitelist= ' . implode(' ', $currentWhiteListArray) . '. phar' .
672 ' is currently not a hard requirement of TYPO3 CMS but is nice to have and a possible requirement' .
673 ' in future versions. A useful setting is "suhosin.executor.include.whitelist = phar vfs".'
674 );
675 } else {
676 $status = new OkStatus();
677 $status->setTitle('PHP suhosin.executor.include.whitelist contains phar');
678 }
679 } else {
680 $status = new InfoStatus();
681 $status->setTitle('Suhosin not loaded');
682 $status->setMessage(
683 'If enabling suhosin, a useful setting is "suhosin.executor.include.whitelist = phar vfs".'
684 );
685 }
686 return $status;
687 }
688
689 /**
690 * Check suhosin.executor.include.whitelist contains vfs
691 *
692 * @return NoticeStatus|InfoStatus|OkStatus
693 */
694 protected function checkSuhosinExecutorIncludeWhiteListContainsVfs() {
695 if ($this->isSuhosinLoaded()) {
696 $currentWhiteListArray = $this->trimExplode(' ', ini_get('suhosin.executor.include.whitelist'));
697 if (!in_array('vfs', $currentWhiteListArray)) {
698 $status = new WarningStatus();
699 $status->setTitle('PHP suhosin.executor.include.whitelist does not contain vfs');
700 $status->setMessage(
701 'suhosin.executor.include.whitelist= ' . implode(' ', $currentWhiteListArray) . '. vfs' .
702 ' is currently not a hard requirement of TYPO3 CMS but tons of unit tests rely on it.' .
703 ' Furthermore, vfs is likely a base for an additional compatibilyt layer in the future.' .
704 ' A useful setting is "suhosin.executor.include.whitelist = phar vfs".'
705 );
706 } else {
707 $status = new OkStatus();
708 $status->setTitle('PHP suhosin.executor.include.whitelist contains vfs');
709 }
710 } else {
711 $status = new InfoStatus();
712 $status->setTitle('Suhosin not loaded');
713 $status->setMessage(
714 'If enabling suhosin, a useful setting is "suhosin.executor.include.whitelist = phar vfs".'
715 );
716 }
717 return $status;
718 }
719
720 /**
721 * Check if some opcode cache is loaded
722 *
723 * @return WarningStatus|OkStatus
724 */
725 protected function checkSomePhpOpcodeCacheIsLoaded() {
726 if (
727 // Currently APCu identifies itself both as "apcu" and "apc" (for compatibility) although it doesn't provide the APC-opcache functionality
728 extension_loaded('eaccelerator')
729 || extension_loaded('xcache')
730 || (extension_loaded('apc') && !extension_loaded('apcu'))
731 || extension_loaded('Zend Optimizer+')
732 || extension_loaded('Zend OPcache')
733 || extension_loaded('wincache')
734 ) {
735 $status = new OkStatus();
736 $status->setTitle('A PHP opcode cache is loaded');
737 } else {
738 $status = new WarningStatus();
739 $status->setTitle('No PHP opcode cache loaded');
740 $status->setMessage(
741 'PHP opcode caches hold a compiled version of executed PHP scripts in' .
742 ' memory and do not require to recompile any script on each access.' .
743 ' This can be a massive performance improvement and can put load off a' .
744 ' server in general, a parse time reduction by factor three for full cached' .
745 ' pages can be achieved easily if using some opcode cache.' .
746 ' If in doubt choosing one, APC runs well and can be used as data' .
747 ' cache layer in TYPO3 CMS as additional feature.'
748 );
749 }
750 return $status;
751 }
752
753 /**
754 * Check doc comments can be fetched by reflection
755 *
756 * @return ErrorStatus|OkStatus
757 */
758 protected function checkReflectionDocComment() {
759 $testReflection = new \ReflectionMethod(get_class($this), __FUNCTION__);
760 if (strlen($testReflection->getDocComment()) === 0) {
761 $status = new ErrorStatus();
762 $status->setTitle('Doc comment reflection broken');
763 $status->setMessage(
764 'TYPO3 CMS core extensions like extbase and fluid heavily rely on method' .
765 ' comment parsing to fetch annotations and add magic according to them.' .
766 ' This does not work in the current environment and will lead to a lot of' .
767 ' broken extensions. The PHP extension eaccelerator is known to break this if' .
768 ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.' .
769 ' This compile flag must be given, otherwise TYPO3 CMS is no fun.'
770 );
771 } else {
772 $status = new OkStatus();
773 $status->setTitle('Document comment reflection works');
774 }
775 return $status;
776 }
777
778 /**
779 * Checks thread stack size if on windows with apache
780 *
781 * @return WarningStatus|OkStatus
782 */
783 protected function checkWindowsApacheThreadStackSize() {
784 if (
785 $this->isWindowsOs()
786 && substr($_SERVER['SERVER_SOFTWARE'], 0, 6) === 'Apache'
787 ) {
788 $status = new WarningStatus();
789 $status->setTitle('Windows apache thread stack size');
790 $status->setMessage(
791 'This current value can not be checked by the system, so please ignore this warning if it' .
792 ' is already taken care off: Fluid uses complex regular expressions which require a lot' .
793 ' of stack space during the first processing.' .
794 ' On Windows the default stack size for Apache is a lot smaller than on unix.' .
795 ' You can increase the size to 8MB (default on unix) by adding to the httpd.conf:' .
796 ' ThreadStackSize 8388608. Restart Apache after this change.'
797 );
798 } else {
799 $status = new OkStatus();
800 $status->setTitle('ThreadStackSize is not an issue on unix systems');
801 }
802 return $status;
803 }
804
805 /**
806 * Check if a specific required PHP extension is loaded
807 *
808 * @param string $extension
809 * @return ErrorStatus|OkStatus
810 */
811 protected function checkRequiredPhpExtension($extension) {
812 if (!extension_loaded($extension)) {
813 $status = new ErrorStatus();
814 $status->setTitle('PHP extension ' . $extension . ' not loaded');
815 $status->setMessage(
816 'TYPO3 CMS uses PHP extension ' . $extension . ' but it is not loaded' .
817 ' in your environment. Change your environment to provide this extension.'
818 );
819 } else {
820 $status = new OkStatus();
821 $status->setTitle('PHP extension ' . $extension . ' loaded');
822 }
823 return $status;
824 }
825
826 /**
827 * Check smtp settings
828 *
829 * @return ErrorStatus|OkStatus|WarningStatus
830 */
831 protected function checkMailCapabilities() {
832 if ($this->isWindowsOs()) {
833 $smtpIni = ini_get('SMTP');
834 $brokenSmtp = FALSE;
835 $smtpIpAddress = '';
836 if (!$this->isValidIp($smtpIni)) {
837 if (!$this->isValidIp(@gethostbyname($smtpIni))) {
838 $brokenSmtp = TRUE;
839 } else {
840 $smtpIpAddress = @gethostbyname($smtpIni);
841 }
842 } else {
843 $smtpIpAddress = $smtpIni;
844 }
845
846 $smtpPortIni = intval(ini_get('smtp_port'));
847 $brokenSmtpPort = FALSE;
848 if (intval($smtpPortIni) < 1 || intval($smtpPortIni) > 65535) {
849 $brokenSmtpPort = TRUE;
850 }
851
852 if ($brokenSmtp || $brokenSmtpPort) {
853 $status = new ErrorStatus();
854 $status->setTitle('Mail configuration is not set correctly');
855 $status->setMessage(
856 'PHP mail() function requires SMTP and smtp_port to have' .
857 ' correct values on Windows. If installation is completed,' .
858 ' the mail system can be tested in the install tool.'
859 );
860 } elseif ($smtpIpAddress === '127.0.0.1' || $smtpIpAddress === '::1') {
861 $status = new WarningStatus();
862 $status->setTitle('Mail is configured, potential problem exists');
863 $status->setMessage(
864 'smtp=' . $smtpIni . ' - This server! Are you sure it runs SMTP server?' .
865 ' If installation is completed, the mail system can be tested in the install tool.'
866 );
867 } else {
868 $status = new OkStatus();
869 $status->setTitle('Mail is configured');
870 $status->setMessage(
871 'smtp=' . $smtpIni . ', smtp_port=' . ini_get('smtp_port') . '.' .
872 ' Values for mail setup look ok. If installation is completed,' .
873 ' the mail system can be tested in the install tool. '
874 );
875 }
876 } elseif (!ini_get('sendmail_path')) {
877 $status = new WarningStatus();
878 $status->setTitle('PHP sendmail_path not defined');
879 $status->setMessage(
880 'This may be critical to TYPO3\'s use of the mail() function.' .
881 ' Your setup is rather uncommon. If installation is completed, the' .
882 ' mail system can be tested in the install tool.'
883 );
884 } else {
885 list($mailBinary) = explode(' ', ini_get('sendmail_path'));
886 if (!@is_executable($mailBinary)) {
887 $status = new ErrorStatus();
888 $status->setTitle('Mail program not found or not executable');
889 $status->setMessage(
890 'sendmail_path = ' . ini_get('sendmail_path') .
891 ' This may be critical to TYPO3\'s use of the mail() function. Please' .
892 ' be sure that the mail() function in your php-installation works. If' .
893 ' installation is completed, the mail system can be tested in the install tool.'
894 );
895 } else {
896 $status = new OkStatus();
897 $status->setTitle('PHP sendmail path given');
898 $status->setMessage(
899 'sendmail_path = ' . ini_get('sendmail_path') . '.' .
900 ' This setting is crucial for TYPO3\'s use of the mail() function. The' .
901 ' current value looks fine. The mail system can be tested in the' .
902 ' install tool if the installation is completed.'
903 );
904 }
905 }
906 return $status;
907 }
908
909 /**
910 * Check imagecreatetruecolor to verify gdlib works as expected
911 *
912 * @return ErrorStatus|OkStatus
913 */
914 protected function checkGdLibTrueColorSupport() {
915 if (function_exists('imagecreatetruecolor')) {
916 $imageResource = @imagecreatetruecolor(50, 100);
917 if (is_resource($imageResource)) {
918 imagedestroy($imageResource);
919 $status = new OkStatus();
920 $status->setTitle('PHP GD library true color works');
921 } else {
922 $status = new ErrorStatus();
923 $status->setTitle('PHP GD library true color support broken');
924 $status->setMessage(
925 'GD is loaded, but calling a imagecreatetruecolor returned an error.' .
926 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
927 );
928 }
929 } else {
930 $status = new ErrorStatus();
931 $status->setTitle('PHP GD library true color support missing');
932 $status->setMessage(
933 'Gdlib is essential for TYPO3 CMS to work properly.'
934 );
935 }
936 return $status;
937 }
938
939 /**
940 * Check gif support of GD library
941 *
942 * @return ErrorStatus|OkStatus
943 */
944 protected function checkGdLibGifSupport() {
945 if (
946 function_exists('imagecreatefromgif')
947 && function_exists('imagegif')
948 && (imagetypes() & IMG_GIF)
949 ) {
950 $imageResource = @imagecreatefromgif(__DIR__ . '/TestImages/jesus.gif');
951 if (is_resource($imageResource)) {
952 imagedestroy($imageResource);
953 $status = new OkStatus();
954 $status->setTitle('PHP GD library has gif support');
955 } else {
956 $status = new ErrorStatus();
957 $status->setTitle('PHP GD library gif support broken');
958 $status->setMessage(
959 'GD is loaded, but calling a gif related message gives errors.' .
960 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
961 );
962 }
963 } else {
964 $status = new ErrorStatus();
965 $status->setTitle('PHP GD library gif support missing');
966 $status->setMessage(
967 'GD must be compiled with gif support. This is essential for' .
968 ' TYPO3 CMS to work properly.'
969 );
970 }
971 return $status;
972 }
973
974 /**
975 * Check jgp support of GD library
976 *
977 * @return ErrorStatus|OkStatus
978 */
979 protected function checkGdLibJpgSupport() {
980 if (
981 function_exists('imagecreatefromjpeg')
982 && function_exists('imagejpeg')
983 && (imagetypes() & IMG_JPG)
984 ) {
985 $status = new OkStatus();
986 $status->setTitle('PHP GD library has jpg support');
987 } else {
988 $status= new ErrorStatus();
989 $status->setTitle('PHP GD library jpg support missing');
990 $status->setMessage(
991 'GD must be compiled with jpg support. This is essential for' .
992 ' TYPO3 CMS to work properly.'
993 );
994 }
995 return $status;
996 }
997
998 /**
999 * Check png support of GD library
1000 *
1001 * @return ErrorStatus|OkStatus
1002 */
1003 protected function checkGdLibPngSupport() {
1004 if (
1005 function_exists('imagecreatefrompng')
1006 && function_exists('imagepng')
1007 && (imagetypes() & IMG_PNG)
1008 ) {
1009 $imageResource = @imagecreatefrompng(__DIR__ . '/TestImages/jesus.png');
1010 if (is_resource($imageResource)) {
1011 imagedestroy($imageResource);
1012 $status = new OkStatus();
1013 $status->setTitle('PHP GD library has png support');
1014 } else {
1015 $status = new ErrorStatus();
1016 $status->setTitle('PHP GD library png support broken');
1017 $status->setMessage(
1018 'GD is compiled with png support, but a test call fails.' .
1019 ' Check your environment and fix it, png in GD lib is important' .
1020 ' for TYPO3 CMS to work properly.'
1021 );
1022 }
1023 } else {
1024 $status = new ErrorStatus();
1025 $status->setTitle('PHP GD library png support missing');
1026 $status->setMessage(
1027 'GD must be compiled with png support. This is essential for' .
1028 ' TYPO3 CMS to work properly'
1029 );
1030 }
1031 return $status;
1032 }
1033
1034 /**
1035 * Check gdlib supports freetype
1036 *
1037 * @return ErrorStatus|OkStatus
1038 */
1039 protected function checkGdLibFreeTypeSupport() {
1040 if (function_exists('imagettftext')) {
1041 $status = new OkStatus();
1042 $status->setTitle('PHP GD library has freetype font support');
1043 $status->setMessage(
1044 'There is a difference between the font size setting the GD' .
1045 ' library should be feeded with. If installation is completed' .
1046 ' a test in the install tool helps to find out the value you need.'
1047 );
1048 } else {
1049 $status = new ErrorStatus();
1050 $status->setTitle('PHP GD library freetype support missing');
1051 $status->setMessage(
1052 'Some core functionality and extension rely on the GD' .
1053 ' to render fonts on images. This support is missing' .
1054 ' in your environment. Install it.'
1055 );
1056 }
1057 return $status;
1058 }
1059
1060 /**
1061 * Check php magic quotes
1062 *
1063 * @return OkStatus|WarningStatus
1064 */
1065 protected function checkPhpMagicQuotes() {
1066 if (get_magic_quotes_gpc()) {
1067 $status = new WarningStatus();
1068 $status->setTitle('PHP magic quotes on');
1069 $status->setMessage(
1070 'PHP ini setting magic_quotes_gpc in on. The setting is deprecated since PHP 5.3.' .
1071 ' You are advised to set it to "Off" until it gets completely removed.'
1072 );
1073 } else {
1074 $status = new OkStatus();
1075 $status->setTitle('PHP magic quotes off');
1076 }
1077 return $status;
1078 }
1079
1080 /**
1081 * Check register globals
1082 *
1083 * @return ErrorStatus|OkStatus
1084 */
1085 protected function checkRegisterGlobals() {
1086 $registerGlobalsEnabled = filter_var(
1087 ini_get('register_globals'),
1088 FILTER_VALIDATE_BOOLEAN,
1089 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
1090 );
1091 if ($registerGlobalsEnabled === TRUE) {
1092 $status = new ErrorStatus();
1093 $status->setTitle('PHP register globals on');
1094 $status->setMessage(
1095 'TYPO3 requires PHP setting "register_globals" set to off.' .
1096 ' This ancient PHP setting is a big security problem and should' .
1097 ' never be enabled.'
1098 );
1099 } else {
1100 $status = new OkStatus();
1101 $status->setTitle('PHP register globals off');
1102 }
1103 return $status;
1104 }
1105
1106 /**
1107 * Helper methods
1108 */
1109
1110 /**
1111 * Validate a given IP address.
1112 *
1113 * @param string $ip IP address to be tested
1114 * @return boolean
1115 */
1116 protected function isValidIp($ip) {
1117 return filter_var($ip, FILTER_VALIDATE_IP) !== FALSE;
1118 }
1119
1120 /**
1121 * Test if this instance runs on windows OS
1122 *
1123 * @return boolean TRUE if operating system is windows
1124 */
1125 protected function isWindowsOs() {
1126 $windowsOs = FALSE;
1127 if (!stristr(PHP_OS, 'darwin') && stristr(PHP_OS, 'win')) {
1128 $windowsOs = TRUE;
1129 }
1130 return $windowsOs;
1131 }
1132
1133 /**
1134 * Helper method to find out if suhosin extension is loaded
1135 *
1136 * @return boolean TRUE if suhosin PHP extension is loaded
1137 */
1138 protected function isSuhosinLoaded() {
1139 $suhosinLoaded = FALSE;
1140 if (extension_loaded('suhosin')) {
1141 $suhosinLoaded = TRUE;
1142 }
1143 return $suhosinLoaded;
1144 }
1145
1146 /**
1147 * Helper method to explode a string by delimeter and throw away empty values.
1148 * Removes empty values from result array.
1149 *
1150 * @param string $delimiter Delimiter string to explode with
1151 * @param string $string The string to explode
1152 * @return array Exploded values
1153 */
1154 protected function trimExplode($delimiter, $string) {
1155 $explodedValues = explode($delimiter, $string);
1156 $resultWithPossibleEmptyValues = array_map('trim', $explodedValues);
1157 $result = array();
1158 foreach ($resultWithPossibleEmptyValues as $value) {
1159 if ($value !== '') {
1160 $result[] = $value;
1161 }
1162 }
1163 return $result;
1164 }
1165
1166 /**
1167 * Helper method to get the bytes value from a measurement string like "100k".
1168 *
1169 * @param string $measurement The measurement (e.g. "100k")
1170 * @return integer The bytes value (e.g. 102400)
1171 */
1172 protected function getBytesFromSizeMeasurement($measurement) {
1173 $bytes = doubleval($measurement);
1174 if (stripos($measurement, 'G')) {
1175 $bytes *= 1024 * 1024 * 1024;
1176 } elseif (stripos($measurement, 'M')) {
1177 $bytes *= 1024 * 1024;
1178 } elseif (stripos($measurement, 'K')) {
1179 $bytes *= 1024;
1180 }
1181 return $bytes;
1182 }
1183
1184
1185 }
1186 ?>