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