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