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