[BUGFIX] Introduce failsafe view in install tool
[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 $status = new Status\WarningStatus();
749 $status->setTitle('No PHP opcode cache loaded');
750 $status->setMessage(
751 'PHP opcode caches hold a compiled version of executed PHP scripts in' .
752 ' memory and do not require to recompile any script on each access.' .
753 ' This can be a massive performance improvement and can put load off a' .
754 ' server in general. A parse time reduction by factor three for fully cached' .
755 ' pages can be achieved easily if using some opcode cache.' .
756 ' If in doubt choosing one, APC runs well and can be used as data' .
757 ' cache layer in TYPO3 CMS as additional feature.'
758 );
759 } else {
760 $status = new Status\OkStatus();
761 $message = '';
762
763 foreach ($opcodeCaches as $opcodeCache => $properties) {
764 $message .= 'Name: ' . $opcodeCache . ' Version: ' . $properties['version'];
765 $message .= LF;
766
767 if ($properties['error']) {
768 // Set status to error if not already set
769 if ($status->getSeverity() !== 'error') {
770 $status = new Status\ErrorStatus();
771 }
772 $message .= ' This opcode cache is marked as malfunctioning by the TYPO3 CMS Team.';
773 } elseif ($properties['canInvalidate']) {
774 $message .= ' This opcode cache should work correctly and has good performance.';
775 } else {
776 // Set status to warning if not already error set
777 if ($status->getSeverity() !== 'error' || $status->getSeverity() !== 'warning') {
778 $status = new Status\WarningStatus();
779 }
780 $message .= ' This opcode cache may work correctly but has medium performance.';
781 }
782 $message .= LF;
783 }
784
785 // Set title of status depending on serverity
786 switch ($status->getSeverity()) {
787 case 'error':
788 $status->setTitle('A possibly malfunctioning PHP opcode cache is loaded');
789 break;
790 case 'warning':
791 $status->setTitle('A PHP opcode cache is loaded, which may cause problems');
792 break;
793 case 'ok':
794 default:
795 $status->setTitle('A PHP opcode cache is loaded');
796 break;
797 }
798 $status->setMessage($message);
799 }
800 return $status;
801 }
802
803 /**
804 * Check doc comments can be fetched by reflection
805 *
806 * @return Status\StatusInterface
807 */
808 protected function checkReflectionDocComment() {
809 $testReflection = new \ReflectionMethod(get_class($this), __FUNCTION__);
810 if ($testReflection->getDocComment() === FALSE) {
811 $status = new Status\AlertStatus();
812 $status->setTitle('PHP Doc comment reflection broken');
813 $status->setMessage(
814 'TYPO3 CMS core extensions like extbase and fluid heavily rely on method'
815 . ' comment parsing to fetch annotations and add magic belonging to them.'
816 . ' This does not work in the current environment and so we can not install'
817 . ' TYPO3 CMS.' . LF
818 . ' Here are some possibilities: ' . LF
819 . '* In Zend OPcache you can disable to save/load comment. If you are using'
820 . ' Zend OPcache (included since PHP 5.5) then check your php.ini settings for'
821 . ' opcache.save_comments and opcache.load_comments and enable them.' . LF
822 . '* In Zend Optimizer+ you can disable to save comment. If you are using'
823 . ' Zend Optimizer+ then check your php.ini settings for'
824 . ' zend_optimizerplus.save_comments and enable it.' . LF
825 . '* The PHP extension eaccelerator is known to break this if'
826 . ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.'
827 . ' This compile flag must be given, otherwise TYPO3 CMS will not work.'
828 );
829 } else {
830 $status = new Status\OkStatus();
831 $status->setTitle('PHP Doc comment reflection works');
832 }
833 return $status;
834 }
835
836 /**
837 * Check if systemLocale setting is correct (locale exists in the OS)
838 *
839 * @return Status\StatusInterface
840 */
841 protected function checkSystemLocale() {
842
843 $currentLocale = setlocale(LC_CTYPE, 0);
844
845 // On Windows an empty locale value uses the regional settings from the Control Panel
846 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') {
847 $status = new Status\InfoStatus();
848 $status->setTitle('Empty systemLocale setting');
849 $status->setMessage(
850 '$GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is not set. This is fine as long as no UTF-8 file system is used.'
851 );
852 } elseif (setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']) === FALSE) {
853 $status = new Status\ErrorStatus();
854 $status->setTitle('Incorrect systemLocale setting');
855 $status->setMessage(
856 'Current value of the $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is incorrect. Locale with this name doesn\'t exist in the operating system.'
857 );
858 setlocale(LC_CTYPE, $currentLocale);
859 } else {
860 $status = new Status\OkStatus();
861 $status->setTitle('System locale is correct');
862 }
863
864 return $status;
865 }
866
867 /**
868 * Checks whether we can use file names with UTF-8 characters.
869 * Configured system locale must support UTF-8 when UTF8filesystem is set
870 *
871 * @return Status\StatusInterface
872 */
873 protected function checkLocaleWithUTF8filesystem() {
874
875 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
876
877 // On Windows an empty local value uses the regional settings from the Control Panel
878 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') {
879 $status = new Status\ErrorStatus();
880 $status->setTitle('System locale not set on UTF-8 file system');
881 $status->setMessage(
882 '$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.'
883 );
884 } else {
885 $testString = 'ÖöĄĆŻĘĆćążąęó.jpg';
886 $currentLocale = setlocale(LC_CTYPE, 0);
887 $quote = TYPO3_OS === 'WIN' ? '"' : '\'';
888
889 setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
890
891 if (escapeshellarg($testString) === $quote . $testString . $quote) {
892 $status = new Status\OkStatus();
893 $status->setTitle('File names with UTF-8 characters can be used.');
894 } else {
895 $status = new Status\ErrorStatus();
896 $status->setTitle('System locale setting doesn\'t support UTF-8 file names.');
897 $status->setMessage(
898 'Please check your $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] setting.'
899 );
900 }
901
902 setlocale(LC_CTYPE, $currentLocale);
903 }
904
905
906 } else {
907 $status = new Status\OkStatus();
908 $status->setTitle('Skipping test, as UTF8filesystem is not enabled.');
909 }
910
911 return $status;
912 }
913
914 /**
915 * Checks thread stack size if on windows with apache
916 *
917 * @return Status\StatusInterface
918 */
919 protected function checkWindowsApacheThreadStackSize() {
920 if (
921 $this->isWindowsOs()
922 && substr($_SERVER['SERVER_SOFTWARE'], 0, 6) === 'Apache'
923 ) {
924 $status = new Status\WarningStatus();
925 $status->setTitle('Windows apache thread stack size');
926 $status->setMessage(
927 'This current value can not be checked by the system, so please ignore this warning if it' .
928 ' is already taken care of: Fluid uses complex regular expressions which require a lot' .
929 ' of stack space during the first processing.' .
930 ' On Windows the default stack size for Apache is a lot smaller than on UNIX.' .
931 ' You can increase the size to 8MB (default on UNIX) by adding the following configuration' .
932 ' to httpd.conf and restart Apache afterwards:' . LF .
933 '<IfModule mpm_winnt_module>' . LF .
934 'ThreadStackSize 8388608' . LF .
935 '</IfModule>'
936 );
937 } else {
938 $status = new Status\OkStatus();
939 $status->setTitle('Apache ThreadStackSize is not an issue on UNIX systems');
940 }
941 return $status;
942 }
943
944 /**
945 * Check if a specific required PHP extension is loaded
946 *
947 * @param string $extension
948 * @return Status\StatusInterface
949 */
950 protected function checkRequiredPhpExtension($extension) {
951 if (!extension_loaded($extension)) {
952 $status = new Status\ErrorStatus();
953 $status->setTitle('PHP extension ' . $extension . ' not loaded');
954 $status->setMessage(
955 'TYPO3 CMS uses PHP extension ' . $extension . ' but it is not loaded' .
956 ' in your environment. Change your environment to provide this extension.'
957 );
958 } else {
959 $status = new Status\OkStatus();
960 $status->setTitle('PHP extension ' . $extension . ' loaded');
961 }
962 return $status;
963 }
964
965 /**
966 * Check imagecreatetruecolor to verify gdlib works as expected
967 *
968 * @return Status\StatusInterface
969 */
970 protected function checkGdLibTrueColorSupport() {
971 if (function_exists('imagecreatetruecolor')) {
972 $imageResource = @imagecreatetruecolor(50, 100);
973 if (is_resource($imageResource)) {
974 imagedestroy($imageResource);
975 $status = new Status\OkStatus();
976 $status->setTitle('PHP GD library true color works');
977 } else {
978 $status = new Status\ErrorStatus();
979 $status->setTitle('PHP GD library true color support broken');
980 $status->setMessage(
981 'GD is loaded, but calling imagecreatetruecolor() fails.' .
982 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
983 );
984 }
985 } else {
986 $status = new Status\ErrorStatus();
987 $status->setTitle('PHP GD library true color support missing');
988 $status->setMessage(
989 'Gdlib is essential for TYPO3 CMS to work properly.'
990 );
991 }
992 return $status;
993 }
994
995 /**
996 * Check gif support of GD library
997 *
998 * @return Status\StatusInterface
999 */
1000 protected function checkGdLibGifSupport() {
1001 if (
1002 function_exists('imagecreatefromgif')
1003 && function_exists('imagegif')
1004 && (imagetypes() & IMG_GIF)
1005 ) {
1006 $imageResource = @imagecreatefromgif(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.gif');
1007 if (is_resource($imageResource)) {
1008 imagedestroy($imageResource);
1009 $status = new Status\OkStatus();
1010 $status->setTitle('PHP GD library has gif support');
1011 } else {
1012 $status = new Status\ErrorStatus();
1013 $status->setTitle('PHP GD library gif support broken');
1014 $status->setMessage(
1015 'GD is loaded, but calling imagecreatefromgif() fails.' .
1016 ' This must be fixed, TYPO3 CMS won\'t work well otherwise.'
1017 );
1018 }
1019 } else {
1020 $status = new Status\ErrorStatus();
1021 $status->setTitle('PHP GD library gif support missing');
1022 $status->setMessage(
1023 'GD must be compiled with gif support. This is essential for' .
1024 ' TYPO3 CMS to work properly.'
1025 );
1026 }
1027 return $status;
1028 }
1029
1030 /**
1031 * Check jgp support of GD library
1032 *
1033 * @return Status\StatusInterface
1034 */
1035 protected function checkGdLibJpgSupport() {
1036 if (
1037 function_exists('imagecreatefromjpeg')
1038 && function_exists('imagejpeg')
1039 && (imagetypes() & IMG_JPG)
1040 ) {
1041 $status = new Status\OkStatus();
1042 $status->setTitle('PHP GD library has jpg support');
1043 } else {
1044 $status = new Status\ErrorStatus();
1045 $status->setTitle('PHP GD library jpg support missing');
1046 $status->setMessage(
1047 'GD must be compiled with jpg support. This is essential for' .
1048 ' TYPO3 CMS to work properly.'
1049 );
1050 }
1051 return $status;
1052 }
1053
1054 /**
1055 * Check png support of GD library
1056 *
1057 * @return Status\StatusInterface
1058 */
1059 protected function checkGdLibPngSupport() {
1060 if (
1061 function_exists('imagecreatefrompng')
1062 && function_exists('imagepng')
1063 && (imagetypes() & IMG_PNG)
1064 ) {
1065 $imageResource = @imagecreatefrompng(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.png');
1066 if (is_resource($imageResource)) {
1067 imagedestroy($imageResource);
1068 $status = new Status\OkStatus();
1069 $status->setTitle('PHP GD library has png support');
1070 } else {
1071 $status = new Status\ErrorStatus();
1072 $status->setTitle('PHP GD library png support broken');
1073 $status->setMessage(
1074 'GD is compiled with png support, but calling imagecreatefrompng() fails.' .
1075 ' Check your environment and fix it, png in GD lib is important' .
1076 ' for TYPO3 CMS to work properly.'
1077 );
1078 }
1079 } else {
1080 $status = new Status\ErrorStatus();
1081 $status->setTitle('PHP GD library png support missing');
1082 $status->setMessage(
1083 'GD must be compiled with png support. This is essential for' .
1084 ' TYPO3 CMS to work properly'
1085 );
1086 }
1087 return $status;
1088 }
1089
1090 /**
1091 * Check gdlib supports freetype
1092 *
1093 * @return Status\StatusInterface
1094 */
1095 protected function checkGdLibFreeTypeSupport() {
1096 if (function_exists('imagettftext')) {
1097 $status = new Status\OkStatus();
1098 $status->setTitle('PHP GD library has freetype font support');
1099 $status->setMessage(
1100 'There is a difference between the font size setting the GD' .
1101 ' library should be feeded with. If installation is completed' .
1102 ' a test in the install tool helps to find out the value you need.'
1103 );
1104 } else {
1105 $status = new Status\ErrorStatus();
1106 $status->setTitle('PHP GD library freetype support missing');
1107 $status->setMessage(
1108 'Some core functionality and extension rely on the GD' .
1109 ' to render fonts on images. This support is missing' .
1110 ' in your environment. Install it.'
1111 );
1112 }
1113 return $status;
1114 }
1115
1116 /**
1117 * Create true type font test image
1118 *
1119 * @return Status\StatusInterface
1120 */
1121 protected function isTrueTypeFontDpiStandard() {
1122 if (function_exists('imageftbbox')) {
1123 // 20 Pixels at 96 DPI - the DefaultConfiguration
1124 $fontSize = (20 / 96 * 72);
1125 $textDimensions = @imageftbbox(
1126 $fontSize,
1127 0,
1128 __DIR__ . '/../../Resources/Private/Font/vera.ttf',
1129 'Testing true type support'
1130 );
1131 $fontBoxWidth = $textDimensions[2] - $textDimensions[0];
1132 if ($fontBoxWidth < 300 && $fontBoxWidth > 200) {
1133 $status = new Status\OkStatus();
1134 $status->setTitle('FreeType True Type Font DPI');
1135 $status->setMessage('Fonts are rendered by FreeType library. ' .
1136 'We need to ensure that the final dimensions are as expected. ' .
1137 'This server renderes fonts based on 96 DPI correctly'
1138 );
1139 } else {
1140 $status = new Status\NoticeStatus();
1141 $status->setTitle('FreeType True Type Font DPI');
1142 $status->setMessage('Fonts are rendered by FreeType library. ' .
1143 'This server renders fonts not as expected. ' .
1144 'Please configure FreeType or TYPO3_CONF_VARS[GFX][TTFdpi]'
1145 );
1146 }
1147 } else {
1148 $status = new Status\ErrorStatus();
1149 $status->setTitle('PHP GD library freetype2 support missing');
1150 $status->setMessage(
1151 'The core relies on GD library compiled into PHP with freetype2' .
1152 ' support. This is missing on your system. Please install it.'
1153 );
1154 }
1155
1156 return $status;
1157 }
1158
1159 /**
1160 * Check php magic quotes
1161 *
1162 * @return Status\StatusInterface
1163 */
1164 protected function checkPhpMagicQuotes() {
1165 $magicQuotesGpc = get_magic_quotes_gpc();
1166 if ($magicQuotesGpc) {
1167 $status = new Status\WarningStatus();
1168 $status->setTitle('PHP magic quotes on');
1169 $status->setMessage(
1170 'magic_quotes_gpc=' . $magicQuotesGpc . LF .
1171 'Setting magic_quotes_gpc is deprecated since PHP 5.3.' .
1172 ' You are advised to disable it until it gets completely removed:' . LF .
1173 'magic_quotes_gpc=Off'
1174 );
1175 } else {
1176 $status = new Status\OkStatus();
1177 $status->setTitle('PHP magic quotes off');
1178 }
1179 return $status;
1180 }
1181
1182 /**
1183 * Check register globals
1184 *
1185 * @return Status\StatusInterface
1186 */
1187 protected function checkRegisterGlobals() {
1188 $registerGlobalsEnabled = filter_var(
1189 ini_get('register_globals'),
1190 FILTER_VALIDATE_BOOLEAN,
1191 array(FILTER_REQUIRE_SCALAR, FILTER_NULL_ON_FAILURE)
1192 );
1193 if ($registerGlobalsEnabled === TRUE) {
1194 $status = new Status\ErrorStatus();
1195 $status->setTitle('PHP register globals on');
1196 $status->setMessage(
1197 'register_globals=' . ini_get('register_globals') . LF .
1198 'TYPO3 requires PHP setting "register_globals" set to off.' .
1199 ' This ancient PHP setting is a big security problem and should' .
1200 ' never be enabled:' . LF .
1201 'register_globals=Off'
1202 );
1203 } else {
1204 $status = new Status\OkStatus();
1205 $status->setTitle('PHP register globals off');
1206 }
1207 return $status;
1208 }
1209
1210 /**
1211 * Check for bug in libxml
1212 *
1213 * @return Status\StatusInterface
1214 */
1215 protected function checkLibXmlBug() {
1216 $sampleArray = array('Test>><<Data');
1217
1218 $xmlContent = '<numIndex index="0">Test&gt;&gt;&lt;&lt;Data</numIndex>' . LF;
1219
1220 $xml = \TYPO3\CMS\Core\Utility\GeneralUtility::array2xml($sampleArray, '', -1);
1221
1222 if ($xmlContent !== $xml) {
1223 $status = new Status\ErrorStatus();
1224 $status->setTitle('PHP libxml bug present');
1225 $status->setMessage(
1226 'Some hosts have problems saving ">><<" in a flexform.' .
1227 ' To fix this, enable [BE][flexformForceCDATA] in' .
1228 ' All Configuration.'
1229 );
1230 } else {
1231 $status = new Status\OkStatus();
1232 $status->setTitle('PHP libxml bug not present');
1233 }
1234 return $status;
1235 }
1236
1237 /**
1238 * Helper methods
1239 */
1240
1241 /**
1242 * Validate a given IP address.
1243 *
1244 * @param string $ip IP address to be tested
1245 * @return boolean
1246 */
1247 protected function isValidIp($ip) {
1248 return filter_var($ip, FILTER_VALIDATE_IP) !== FALSE;
1249 }
1250
1251 /**
1252 * Test if this instance runs on windows OS
1253 *
1254 * @return boolean TRUE if operating system is windows
1255 */
1256 protected function isWindowsOs() {
1257 $windowsOs = FALSE;
1258 if (!stristr(PHP_OS, 'darwin') && stristr(PHP_OS, 'win')) {
1259 $windowsOs = TRUE;
1260 }
1261 return $windowsOs;
1262 }
1263
1264 /**
1265 * Helper method to find out if suhosin extension is loaded
1266 *
1267 * @return boolean TRUE if suhosin PHP extension is loaded
1268 */
1269 protected function isSuhosinLoaded() {
1270 $suhosinLoaded = FALSE;
1271 if (extension_loaded('suhosin')) {
1272 $suhosinLoaded = TRUE;
1273 }
1274 return $suhosinLoaded;
1275 }
1276
1277 /**
1278 * Helper method to explode a string by delimeter and throw away empty values.
1279 * Removes empty values from result array.
1280 *
1281 * @param string $delimiter Delimiter string to explode with
1282 * @param string $string The string to explode
1283 * @return array Exploded values
1284 */
1285 protected function trimExplode($delimiter, $string) {
1286 $explodedValues = explode($delimiter, $string);
1287 $resultWithPossibleEmptyValues = array_map('trim', $explodedValues);
1288 $result = array();
1289 foreach ($resultWithPossibleEmptyValues as $value) {
1290 if ($value !== '') {
1291 $result[] = $value;
1292 }
1293 }
1294 return $result;
1295 }
1296
1297 /**
1298 * Helper method to get the bytes value from a measurement string like "100k".
1299 *
1300 * @param string $measurement The measurement (e.g. "100k")
1301 * @return integer The bytes value (e.g. 102400)
1302 */
1303 protected function getBytesFromSizeMeasurement($measurement) {
1304 $bytes = doubleval($measurement);
1305 if (stripos($measurement, 'G')) {
1306 $bytes *= 1024 * 1024 * 1024;
1307 } elseif (stripos($measurement, 'M')) {
1308 $bytes *= 1024 * 1024;
1309 } elseif (stripos($measurement, 'K')) {
1310 $bytes *= 1024;
1311 }
1312 return $bytes;
1313 }
1314 }