diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/EnvironmentStatus.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/EnvironmentStatus.php index 98484587c09f98228e571338243239a28216b98c..cac98efbe9f8764ca425d064cfe3e3ccbdc5b48a 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Ajax/EnvironmentStatus.php +++ b/typo3/sysext/install/Classes/Controller/Action/Ajax/EnvironmentStatus.php @@ -15,6 +15,10 @@ namespace TYPO3\CMS\Install\Controller\Action\Ajax; */ use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Status\StatusUtility; +use TYPO3\CMS\Install\SystemEnvironment\Check; +use TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck; +use TYPO3\CMS\Install\SystemEnvironment\SetupCheck; /** * Environment status check for errors @@ -28,17 +32,16 @@ class EnvironmentStatus extends AbstractAjaxAction */ protected function executeAction() { + // Count of failed checks to be displayed in the left navigation menu + $statusObjects = array_merge( + GeneralUtility::makeInstance(Check::class)->getStatus(), + GeneralUtility::makeInstance(SetupCheck::class)->getStatus(), + GeneralUtility::makeInstance(DatabaseCheck::class)->getStatus() + ); /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */ - $statusUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\StatusUtility::class); + $statusUtility = GeneralUtility::makeInstance(StatusUtility::class); + $errors = $statusUtility->filterBySeverity($statusObjects, 'error'); - // Count of failed environment checks to be displayed in the left navigation menu - $environmentStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\Check::class)->getStatus(); - $environmentErrors = $statusUtility->filterBySeverity($environmentStatus, 'error'); - - // Count of failed database checks to be displayed in the left navigation menu - $databaseStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck::class)->getStatus(); - $databaseErrors = $statusUtility->filterBySeverity($databaseStatus, 'error'); - - return count($environmentErrors) + count($databaseErrors); + return count($errors); } } diff --git a/typo3/sysext/install/Classes/Controller/Action/Common/InstallToolDisabledAction.php b/typo3/sysext/install/Classes/Controller/Action/Common/InstallToolDisabledAction.php index 6590b1513cba29a5b1457eff64281cafcad55cf2..3752f684eae8b4d3142a95d973d81fadf95a55a6 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Common/InstallToolDisabledAction.php +++ b/typo3/sysext/install/Classes/Controller/Action/Common/InstallToolDisabledAction.php @@ -16,6 +16,9 @@ namespace TYPO3\CMS\Install\Controller\Action\Common; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Controller\Action; +use TYPO3\CMS\Install\Status\StatusUtility; +use TYPO3\CMS\Install\SystemEnvironment\Check; +use TYPO3\CMS\Install\SystemEnvironment\SetupCheck; /** * Welcome page @@ -29,13 +32,15 @@ class InstallToolDisabledAction extends Action\AbstractAction */ protected function executeAction() { - /** @var \TYPO3\CMS\Install\SystemEnvironment\Check $statusCheck */ - $statusCheck = GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\Check::class); - $statusObjects = $statusCheck->getStatus(); + $statusObjects = array_merge( + GeneralUtility::makeInstance(Check::class)->getStatus(), + GeneralUtility::makeInstance(SetupCheck::class)->getStatus() + ); /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */ - $statusUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\StatusUtility::class); + $statusUtility = GeneralUtility::makeInstance(StatusUtility::class); $alerts = $statusUtility->filterBySeverity($statusObjects, 'alert'); $this->view->assign('alerts', $alerts); + return $this->view->render(); } } diff --git a/typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php b/typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php index 4c7daec3bde78630e389d0a63644c7a142b9cb92..46df25c9a123fb2052274e7ccf0d24a60ae5a367 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php +++ b/typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php @@ -15,6 +15,9 @@ namespace TYPO3\CMS\Install\Controller\Action\Step; */ use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Status\StatusUtility; +use TYPO3\CMS\Install\SystemEnvironment\Check; +use TYPO3\CMS\Install\SystemEnvironment\SetupCheck; /** * Very first install step: @@ -40,7 +43,7 @@ class EnvironmentAndFolders extends AbstractStepAction $structureFacade = $folderStructureFactory->getStructure(); $structureFixMessages = $structureFacade->fix(); /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */ - $statusUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\StatusUtility::class); + $statusUtility = GeneralUtility::makeInstance(StatusUtility::class); $errorsFromStructure = $statusUtility->filterBySeverity($structureFixMessages, 'error'); if (@is_dir(PATH_typo3conf)) { @@ -95,11 +98,12 @@ class EnvironmentAndFolders extends AbstractStepAction */ protected function executeAction() { - /** @var \TYPO3\CMS\Install\SystemEnvironment\Check $statusCheck */ - $statusCheck = GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\Check::class); - $statusObjects = $statusCheck->getStatus(); + $statusObjects = array_merge( + GeneralUtility::makeInstance(Check::class)->getStatus(), + GeneralUtility::makeInstance(SetupCheck::class)->getStatus() + ); /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */ - $statusUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\StatusUtility::class); + $statusUtility = GeneralUtility::makeInstance(StatusUtility::class); $environmentStatus = $statusUtility->sortBySeverity($statusObjects); $alerts = $statusUtility->filterBySeverity($statusObjects, 'alert'); $this->view->assign('alerts', $alerts); diff --git a/typo3/sysext/install/Classes/Controller/Action/Tool/SystemEnvironment.php b/typo3/sysext/install/Classes/Controller/Action/Tool/SystemEnvironment.php index 528af162194551c9cd85afbc640aa8e354ae30c0..8d55ac3d0f5379a75cd2393234b60aca61eec545 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Tool/SystemEnvironment.php +++ b/typo3/sysext/install/Classes/Controller/Action/Tool/SystemEnvironment.php @@ -19,6 +19,7 @@ use TYPO3\CMS\Install\Controller\Action; use TYPO3\CMS\Install\Status\StatusUtility; use TYPO3\CMS\Install\SystemEnvironment\Check; use TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck; +use TYPO3\CMS\Install\SystemEnvironment\SetupCheck; /** * Show system environment check results @@ -32,13 +33,11 @@ class SystemEnvironment extends Action\AbstractAction */ protected function executeAction() { - /** @var $statusCheck Check */ - $statusCheck = GeneralUtility::makeInstance(Check::class); - $statusObjects = $statusCheck->getStatus(); - - /** @var $statusCheck DatabaseCheck */ - $databaseStatusCheck = GeneralUtility::makeInstance(DatabaseCheck::class); - $statusObjects = array_merge($statusObjects, $databaseStatusCheck->getStatus()); + $statusObjects = array_merge( + GeneralUtility::makeInstance(Check::class)->getStatus(), + GeneralUtility::makeInstance(SetupCheck::class)->getStatus(), + GeneralUtility::makeInstance(DatabaseCheck::class)->getStatus() + ); /** @var $statusUtility StatusUtility */ $statusUtility = GeneralUtility::makeInstance(StatusUtility::class); diff --git a/typo3/sysext/install/Classes/Report/EnvironmentStatusReport.php b/typo3/sysext/install/Classes/Report/EnvironmentStatusReport.php index 04c72d43dfa7aa3bd0dedbe427cd877dd284b1a2..5296e539955641c9e859e2ef556cdb723a5f6078 100644 --- a/typo3/sysext/install/Classes/Report/EnvironmentStatusReport.php +++ b/typo3/sysext/install/Classes/Report/EnvironmentStatusReport.php @@ -14,6 +14,7 @@ namespace TYPO3\CMS\Install\Report; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Reports\ExtendedStatusProviderInterface; use TYPO3\CMS\Reports\StatusProviderInterface; @@ -49,14 +50,11 @@ class EnvironmentStatusReport implements StatusProviderInterface, ExtendedStatus */ protected function getStatusInternal($verbose) { - /** @var $statusCheck \TYPO3\CMS\Install\SystemEnvironment\Check */ - $statusCheck = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\Check::class); - $statusObjects = $statusCheck->getStatus(); - - /** @var $statusCheck \TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck */ - $databaseStatusCheck = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck::class); - $statusObjects = array_merge($statusObjects, $databaseStatusCheck->getStatus()); - + $statusObjects = array_merge( + GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\Check::class)->getStatus(), + GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\SetupCheck::class)->getStatus(), + GeneralUtility::makeInstance(\TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck::class)->getStatus() + ); $reportStatusTypes = array( 'error' => array(), 'warning' => array(), @@ -94,7 +92,7 @@ class EnvironmentStatusReport implements StatusProviderInterface, ExtendedStatus $message = $GLOBALS['LANG']->sL($pathToXliff . ':environment.status.message.' . $type); } $severity = constant('\TYPO3\CMS\Reports\Status::' . strtoupper($type)); - $statusArray[] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( + $statusArray[] = GeneralUtility::makeInstance( \TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->sL($pathToXliff . ':environment.status.title'), sprintf($GLOBALS['LANG']->sL($pathToXliff . ':environment.status.value'), $value), diff --git a/typo3/sysext/install/Classes/SystemEnvironment/Check.php b/typo3/sysext/install/Classes/SystemEnvironment/Check.php index a7876b048d30534cab25ef996c53905eea8fc385..84599e7d88531fc3c370d64ea4087fc722eed1a5 100644 --- a/typo3/sysext/install/Classes/SystemEnvironment/Check.php +++ b/typo3/sysext/install/Classes/SystemEnvironment/Check.php @@ -14,8 +14,6 @@ namespace TYPO3\CMS\Install\SystemEnvironment; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Core\Service\OpcodeCacheService; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Status; /** @@ -74,51 +72,49 @@ class Check */ public function getStatus() { - $statusArray = array(); - $statusArray[] = $this->checkCurrentDirectoryIsInIncludePath(); - $statusArray[] = $this->checkTrustedHostPattern(); - $statusArray[] = $this->checkFileUploadEnabled(); - $statusArray[] = $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize(); - $statusArray[] = $this->checkMemorySettings(); - $statusArray[] = $this->checkPhpVersion(); - $statusArray[] = $this->checkMaxExecutionTime(); - $statusArray[] = $this->checkDisableFunctions(); - $statusArray[] = $this->checkDownloadsPossible(); - $statusArray[] = $this->checkMysqliReconnectSetting(); - $statusArray[] = $this->checkDocRoot(); - $statusArray[] = $this->checkOpenBaseDir(); - $statusArray[] = $this->checkXdebugMaxNestingLevel(); - $statusArray[] = $this->checkOpenSslInstalled(); + $status = array(); + $status[] = $this->checkCurrentDirectoryIsInIncludePath(); + $status[] = $this->checkFileUploadEnabled(); + $status[] = $this->checkPostUploadSizeIsHigherOrEqualMaximumFileUploadSize(); + $status[] = $this->checkMemorySettings(); + $status[] = $this->checkPhpVersion(); + $status[] = $this->checkMaxExecutionTime(); + $status[] = $this->checkDisableFunctions(); + $status[] = $this->checkMysqliReconnectSetting(); + $status[] = $this->checkDocRoot(); + $status[] = $this->checkOpenBaseDir(); + $status[] = $this->checkXdebugMaxNestingLevel(); + $status[] = $this->checkOpenSslInstalled(); + if ($this->isSuhosinLoadedAndActive()) { - $statusArray[] = $this->getSuhosinLoadedStatus(); - $statusArray[] = $this->checkSuhosinRequestMaxVars(); - $statusArray[] = $this->checkSuhosinRequestMaxVarnameLength(); - $statusArray[] = $this->checkSuhosinPostMaxNameLength(); - $statusArray[] = $this->checkSuhosinPostMaxVars(); - $statusArray[] = $this->checkSuhosinGetMaxNameLength(); - $statusArray[] = $this->checkSuhosinGetMaxValueLength(); - $statusArray[] = $this->checkSuhosinExecutorIncludeWhiteListContainsPhar(); - $statusArray[] = $this->checkSuhosinExecutorIncludeWhiteListContainsVfs(); + $status[] = $this->getSuhosinLoadedStatus(); + $status[] = $this->checkSuhosinRequestMaxVars(); + $status[] = $this->checkSuhosinRequestMaxVarnameLength(); + $status[] = $this->checkSuhosinPostMaxNameLength(); + $status[] = $this->checkSuhosinPostMaxVars(); + $status[] = $this->checkSuhosinGetMaxNameLength(); + $status[] = $this->checkSuhosinGetMaxValueLength(); + $status[] = $this->checkSuhosinExecutorIncludeWhiteListContainsPhar(); + $status[] = $this->checkSuhosinExecutorIncludeWhiteListContainsVfs(); } - $statusArray[] = $this->checkMaxInputVars(); - $statusArray[] = $this->checkSomePhpOpcodeCacheIsLoaded(); - $statusArray[] = $this->checkReflectionDocComment(); - $statusArray[] = $this->checkSystemLocale(); - $statusArray[] = $this->checkLocaleWithUTF8filesystem(); - $statusArray[] = $this->checkWindowsApacheThreadStackSize(); + + $status[] = $this->checkMaxInputVars(); + $status[] = $this->checkReflectionDocComment(); + $status[] = $this->checkWindowsApacheThreadStackSize(); + foreach ($this->requiredPhpExtensions as $extension) { - $statusArray[] = $this->checkRequiredPhpExtension($extension); + $status[] = $this->checkRequiredPhpExtension($extension); } - $statusArray[] = $this->checkPcreVersion(); - $statusArray[] = $this->checkGdLibTrueColorSupport(); - $statusArray[] = $this->checkGdLibGifSupport(); - $statusArray[] = $this->checkGdLibJpgSupport(); - $statusArray[] = $this->checkGdLibPngSupport(); - $statusArray[] = $this->checkGdLibFreeTypeSupport(); - $statusArray[] = $this->checkRegisterGlobals(); - $statusArray[] = $this->checkLibXmlBug(); - $statusArray[] = $this->isTrueTypeFontWorking(); - return $statusArray; + + $status[] = $this->checkPcreVersion(); + $status[] = $this->checkGdLibTrueColorSupport(); + $status[] = $this->checkGdLibGifSupport(); + $status[] = $this->checkGdLibJpgSupport(); + $status[] = $this->checkGdLibPngSupport(); + $status[] = $this->checkGdLibFreeTypeSupport(); + $status[] = $this->checkRegisterGlobals(); + + return $status; } /** @@ -148,31 +144,6 @@ class Check return $status; } - /** - * Checks the status of the trusted hosts pattern check - * - * @return Status\StatusInterface - */ - protected function checkTrustedHostPattern() - { - if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) { - $status = new Status\WarningStatus(); - $status->setTitle('Trusted hosts pattern is insecure'); - $status->setMessage('Trusted hosts pattern is configured to allow all header values. Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).'); - } else { - if (GeneralUtility::hostHeaderValueMatchesTrustedHostsPattern($_SERVER['HTTP_HOST'])) { - $status = new Status\OkStatus(); - $status->setTitle('Trusted hosts pattern is configured to allow current host value.'); - } else { - $status = new Status\ErrorStatus(); - $status->setTitle('Trusted hosts pattern mismatch'); - $status->setMessage('The trusted hosts pattern will be configured to allow all header values. This is because your $SERVER_NAME is "' . htmlspecialchars($_SERVER['SERVER_NAME']) . '" while your HTTP_HOST is "' . htmlspecialchars($_SERVER['HTTP_HOST']) . '". Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).'); - } - } - - return $status; - } - /** * Check if file uploads are enabled in PHP * @@ -434,29 +405,6 @@ class Check return $status; } - /** - * Check if it is possible to download external data (e.g. TER) - * Either allow_url_fopen must be enabled or curl must be used - * - * @return Status\OkStatus|Status\WarningStatus - */ - protected function checkDownloadsPossible() - { - $allowUrlFopen = (bool)ini_get('allow_url_fopen'); - $curlEnabled = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse']); - if ($allowUrlFopen || $curlEnabled) { - $status = new Status\OkStatus(); - $status->setTitle('Fetching external URLs is allowed'); - } else { - $status = new Status\WarningStatus(); - $status->setTitle('Fetching external URLs is not allowed'); - $status->setMessage( - 'Either enable PHP runtime setting "allow_url_fopen"' . LF . 'or enable curl by setting [SYS][curlUse] accordingly.' - ); - } - return $status; - } - /** * Verify that mysqli.reconnect is set to 0 in order to avoid improper reconnects * @@ -950,74 +898,6 @@ class Check return $status; } - /** - * Check if some opcode cache is loaded - * - * @return Status\StatusInterface - */ - protected function checkSomePhpOpcodeCacheIsLoaded() - { - // Link to our wiki page, so we can update opcode cache issue information independent of TYPO3 CMS releases. - $wikiLink = 'For more information take a look in our wiki ' . TYPO3_URL_WIKI_OPCODECACHE . '.'; - $opcodeCaches = GeneralUtility::makeInstance(OpcodeCacheService::class)->getAllActive(); - if (empty($opcodeCaches)) { - // Set status to notice. It needs to be notice so email won't be triggered. - $status = new Status\NoticeStatus(); - $status->setTitle('No PHP opcode cache loaded'); - $status->setMessage( - 'PHP opcode caches hold a compiled version of executed PHP scripts in' . - ' memory and do not require to recompile a script each time it is accessed.' . - ' This can be a massive performance improvement and can reduce the load on a' . - ' server in general. A parse time reduction by factor three for fully cached' . - ' pages can be achieved easily if using an opcode cache.' . - LF . $wikiLink - ); - } else { - $status = new Status\OkStatus(); - $message = ''; - - foreach ($opcodeCaches as $opcodeCache => $properties) { - $message .= 'Name: ' . $opcodeCache . ' Version: ' . $properties['version']; - $message .= LF; - - if ($properties['error']) { - // Set status to error if not already set - if ($status->getSeverity() !== 'error') { - $status = new Status\ErrorStatus(); - } - $message .= ' This opcode cache is marked as malfunctioning by the TYPO3 CMS Team.'; - } elseif ($properties['canInvalidate']) { - $message .= ' This opcode cache should work correctly and has good performance.'; - } else { - // Set status to notice if not already error set. It needs to be notice so email won't be triggered. - if ($status->getSeverity() !== 'error' || $status->getSeverity() !== 'warning') { - $status = new Status\NoticeStatus(); - } - $message .= ' This opcode cache may work correctly but has medium performance.'; - } - $message .= LF; - } - - $message .= $wikiLink; - - // Set title of status depending on serverity - switch ($status->getSeverity()) { - case 'error': - $status->setTitle('A possibly malfunctioning PHP opcode cache is loaded'); - break; - case 'warning': - $status->setTitle('A PHP opcode cache is loaded which may cause problems'); - break; - case 'ok': - default: - $status->setTitle('A PHP opcode cache is loaded'); - break; - } - $status->setMessage($message); - } - return $status; - } - /** * Check doc comments can be fetched by reflection * @@ -1053,84 +933,6 @@ class Check return $status; } - /** - * Check if systemLocale setting is correct (locale exists in the OS) - * - * @return Status\StatusInterface - */ - protected function checkSystemLocale() - { - $currentLocale = setlocale(LC_CTYPE, 0); - - // On Windows an empty locale value uses the regional settings from the Control Panel - if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') { - $status = new Status\InfoStatus(); - $status->setTitle('Empty systemLocale setting'); - $status->setMessage( - '$GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is not set. This is fine as long as no UTF-8' . - ' file system is used.' - ); - } elseif (setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']) === false) { - $status = new Status\ErrorStatus(); - $status->setTitle('Incorrect systemLocale setting'); - $status->setMessage( - 'Current value of the $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is incorrect. A locale with' . - ' this name doesn\'t exist in the operating system.' - ); - setlocale(LC_CTYPE, $currentLocale); - } else { - $status = new Status\OkStatus(); - $status->setTitle('System locale is correct'); - } - - return $status; - } - - /** - * Checks whether we can use file names with UTF-8 characters. - * Configured system locale must support UTF-8 when UTF8filesystem is set - * - * @return Status\StatusInterface - */ - protected function checkLocaleWithUTF8filesystem() - { - if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) { - // On Windows an empty local value uses the regional settings from the Control Panel - if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') { - $status = new Status\ErrorStatus(); - $status->setTitle('System locale not set on UTF-8 file system'); - $status->setMessage( - '$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.' - ); - } else { - $testString = 'ÖöĄĆŻĘĆćążąęó.jpg'; - $currentLocale = setlocale(LC_CTYPE, 0); - $quote = TYPO3_OS === 'WIN' ? '"' : '\''; - - setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']); - - if (escapeshellarg($testString) === $quote . $testString . $quote) { - $status = new Status\OkStatus(); - $status->setTitle('File names with UTF-8 characters can be used.'); - } else { - $status = new Status\ErrorStatus(); - $status->setTitle('System locale setting doesn\'t support UTF-8 file names.'); - $status->setMessage( - 'Please check your $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] setting.' - ); - } - - setlocale(LC_CTYPE, $currentLocale); - } - } else { - $status = new Status\OkStatus(); - $status->setTitle('Skipping test, as UTF8filesystem is not enabled.'); - } - - return $status; - } - /** * Checks thread stack size if on windows with apache * @@ -1225,7 +1027,8 @@ class Check && function_exists('imagegif') && (imagetypes() & IMG_GIF) ) { - $imageResource = @imagecreatefromgif(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.gif'); + // See http://stackoverflow.com/a/13139830 + $imageResource = @imagecreatefromgif('data://image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); if (is_resource($imageResource)) { imagedestroy($imageResource); $status = new Status\OkStatus(); @@ -1284,7 +1087,7 @@ class Check && function_exists('imagepng') && (imagetypes() & IMG_PNG) ) { - $imageResource = @imagecreatefrompng(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.png'); + $imageResource = @imagecreatefrompng('data://image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII'); if (is_resource($imageResource)) { imagedestroy($imageResource); $status = new Status\OkStatus(); @@ -1336,48 +1139,6 @@ class Check return $status; } - /** - * Create true type font test image - * - * @return Status\StatusInterface - */ - protected function isTrueTypeFontWorking() - { - if (function_exists('imageftbbox')) { - // 20 Pixels at 96 DPI - $fontSize = (20 / 96 * 72); - $textDimensions = @imageftbbox( - $fontSize, - 0, - __DIR__ . '/../../Resources/Private/Font/vera.ttf', - 'Testing true type support' - ); - $fontBoxWidth = $textDimensions[2] - $textDimensions[0]; - if ($fontBoxWidth < 300 && $fontBoxWidth > 200) { - $status = new Status\OkStatus(); - $status->setTitle('FreeType True Type Font DPI'); - $status->setMessage('Fonts are rendered by FreeType library. ' . - 'We need to ensure that the final dimensions are as expected. ' . - 'This server renderes fonts based on 96 DPI correctly'); - } else { - $status = new Status\NoticeStatus(); - $status->setTitle('FreeType True Type Font DPI'); - $status->setMessage('Fonts are rendered by FreeType library. ' . - 'This server does not render fonts as expected. ' . - 'Please check your FreeType 2 module.'); - } - } else { - $status = new Status\ErrorStatus(); - $status->setTitle('PHP GD library freetype2 support missing'); - $status->setMessage( - 'The core relies on GD library compiled into PHP with freetype2' . - ' support. This is missing on your system. Please install it.' - ); - } - - return $status; - } - /** * Check register globals * @@ -1407,34 +1168,6 @@ class Check return $status; } - /** - * Check for bug in libxml - * - * @return Status\StatusInterface - */ - protected function checkLibXmlBug() - { - $sampleArray = array('Test>><<Data'); - - $xmlContent = '<numIndex index="0">Test>><<Data</numIndex>' . LF; - - $xml = \TYPO3\CMS\Core\Utility\GeneralUtility::array2xml($sampleArray, '', -1); - - if ($xmlContent !== $xml) { - $status = new Status\ErrorStatus(); - $status->setTitle('PHP libxml bug present'); - $status->setMessage( - 'Some hosts have problems saving ">><<" in a flexform.' . - ' To fix this, enable [BE][flexformForceCDATA] in' . - ' All Configuration.' - ); - } else { - $status = new Status\OkStatus(); - $status->setTitle('PHP libxml bug not present'); - } - return $status; - } - /** * Helper methods */ diff --git a/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php new file mode 100644 index 0000000000000000000000000000000000000000..5f1daf4b637af1bd94dc79e6ec5b97f047599550 --- /dev/null +++ b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php @@ -0,0 +1,309 @@ +<?php +namespace TYPO3\CMS\Install\SystemEnvironment; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Service\OpcodeCacheService; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Status; + +/** + * Check TYPO3 setup status + * + * This class is a hardcoded requirement check for the TYPO3 setup. + * + * The status messages and title *must not* include HTML, use plain + * text only. The return values of this class are not bound to HTML + * and can be used in different scopes (eg. as json array). + */ +class SetupCheck +{ + /** + * Get all status information as array with status objects + * + * @return array<\TYPO3\CMS\Install\Status\StatusInterface> + */ + public function getStatus() + { + $status = []; + + $status[] = $this->checkTrustedHostPattern(); + $status[] = $this->checkDownloadsPossible(); + $status[] = $this->checkSystemLocale(); + $status[] = $this->checkLocaleWithUTF8filesystem(); + $status[] = $this->checkSomePhpOpcodeCacheIsLoaded(); + $status[] = $this->isTrueTypeFontWorking(); + $status[] = $this->checkLibXmlBug(); + + return $status; + } + + /** + * Checks the status of the trusted hosts pattern check + * + * @return Status\StatusInterface + */ + protected function checkTrustedHostPattern() + { + if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) { + $status = new Status\WarningStatus(); + $status->setTitle('Trusted hosts pattern is insecure'); + $status->setMessage('Trusted hosts pattern is configured to allow all header values. Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).'); + } else { + if (GeneralUtility::hostHeaderValueMatchesTrustedHostsPattern($_SERVER['HTTP_HOST'])) { + $status = new Status\OkStatus(); + $status->setTitle('Trusted hosts pattern is configured to allow current host value.'); + } else { + $status = new Status\ErrorStatus(); + $status->setTitle('Trusted hosts pattern mismatch'); + $status->setMessage('The trusted hosts pattern will be configured to allow all header values. This is because your $SERVER_NAME is "' . htmlspecialchars($_SERVER['SERVER_NAME']) . '" while your HTTP_HOST is "' . htmlspecialchars($_SERVER['HTTP_HOST']) . '". Check the pattern defined in Install Tool -> All configuration -> System -> trustedHostsPattern and adapt it to expected host value(s).'); + } + } + + return $status; + } + + /** + * Check if it is possible to download external data (e.g. TER) + * Either allow_url_fopen must be enabled or curl must be used + * + * @return Status\OkStatus|Status\WarningStatus + */ + protected function checkDownloadsPossible() + { + $allowUrlFopen = (bool)ini_get('allow_url_fopen'); + $curlEnabled = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse']); + if ($allowUrlFopen || $curlEnabled) { + $status = new Status\OkStatus(); + $status->setTitle('Fetching external URLs is allowed'); + } else { + $status = new Status\WarningStatus(); + $status->setTitle('Fetching external URLs is not allowed'); + $status->setMessage( + 'Either enable PHP runtime setting "allow_url_fopen"' . LF . 'or enable curl by setting [SYS][curlUse] accordingly.' + ); + } + + return $status; + } + + /** + * Check if systemLocale setting is correct (locale exists in the OS) + * + * @return Status\StatusInterface + */ + protected function checkSystemLocale() + { + $currentLocale = setlocale(LC_CTYPE, 0); + + // On Windows an empty locale value uses the regional settings from the Control Panel + if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') { + $status = new Status\InfoStatus(); + $status->setTitle('Empty systemLocale setting'); + $status->setMessage( + '$GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is not set. This is fine as long as no UTF-8' . + ' file system is used.' + ); + } elseif (setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']) === false) { + $status = new Status\ErrorStatus(); + $status->setTitle('Incorrect systemLocale setting'); + $status->setMessage( + 'Current value of the $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] is incorrect. A locale with' . + ' this name doesn\'t exist in the operating system.' + ); + setlocale(LC_CTYPE, $currentLocale); + } else { + $status = new Status\OkStatus(); + $status->setTitle('System locale is correct'); + } + + return $status; + } + + /** + * Checks whether we can use file names with UTF-8 characters. + * Configured system locale must support UTF-8 when UTF8filesystem is set + * + * @return Status\StatusInterface + */ + protected function checkLocaleWithUTF8filesystem() + { + if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) { + // On Windows an empty local value uses the regional settings from the Control Panel + if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale'] === '' && TYPO3_OS !== 'WIN') { + $status = new Status\ErrorStatus(); + $status->setTitle('System locale not set on UTF-8 file system'); + $status->setMessage( + '$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.' + ); + } else { + $testString = 'ÖöĄĆŻĘĆćążąęó.jpg'; + $currentLocale = setlocale(LC_CTYPE, 0); + $quote = TYPO3_OS === 'WIN' ? '"' : '\''; + setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']); + if (escapeshellarg($testString) === $quote . $testString . $quote) { + $status = new Status\OkStatus(); + $status->setTitle('File names with UTF-8 characters can be used.'); + } else { + $status = new Status\ErrorStatus(); + $status->setTitle('System locale setting doesn\'t support UTF-8 file names.'); + $status->setMessage( + 'Please check your $GLOBALS[TYPO3_CONF_VARS][SYS][systemLocale] setting.' + ); + } + setlocale(LC_CTYPE, $currentLocale); + } + } else { + $status = new Status\OkStatus(); + $status->setTitle('Skipping test, as UTF8filesystem is not enabled.'); + } + + return $status; + } + + /** + * Check if some opcode cache is loaded + * + * @return Status\StatusInterface + */ + protected function checkSomePhpOpcodeCacheIsLoaded() + { + // Link to our wiki page, so we can update opcode cache issue information independent of TYPO3 CMS releases. + $wikiLink = 'For more information take a look in our wiki ' . TYPO3_URL_WIKI_OPCODECACHE . '.'; + $opcodeCaches = GeneralUtility::makeInstance(OpcodeCacheService::class)->getAllActive(); + if (empty($opcodeCaches)) { + // Set status to notice. It needs to be notice so email won't be triggered. + $status = new Status\NoticeStatus(); + $status->setTitle('No PHP opcode cache loaded'); + $status->setMessage( + 'PHP opcode caches hold a compiled version of executed PHP scripts in' . + ' memory and do not require to recompile a script each time it is accessed.' . + ' This can be a massive performance improvement and can reduce the load on a' . + ' server in general. A parse time reduction by factor three for fully cached' . + ' pages can be achieved easily if using an opcode cache.' . + LF . $wikiLink + ); + } else { + $status = new Status\OkStatus(); + $message = ''; + foreach ($opcodeCaches as $opcodeCache => $properties) { + $message .= 'Name: ' . $opcodeCache . ' Version: ' . $properties['version']; + $message .= LF; + if ($properties['error']) { + // Set status to error if not already set + if ($status->getSeverity() !== 'error') { + $status = new Status\ErrorStatus(); + } + $message .= ' This opcode cache is marked as malfunctioning by the TYPO3 CMS Team.'; + } elseif ($properties['canInvalidate']) { + $message .= ' This opcode cache should work correctly and has good performance.'; + } else { + // Set status to notice if not already error set. It needs to be notice so email won't be triggered. + if ($status->getSeverity() !== 'error' || $status->getSeverity() !== 'warning') { + $status = new Status\NoticeStatus(); + } + $message .= ' This opcode cache may work correctly but has medium performance.'; + } + $message .= LF; + } + $message .= $wikiLink; + // Set title of status depending on serverity + switch ($status->getSeverity()) { + case 'error': + $status->setTitle('A possibly malfunctioning PHP opcode cache is loaded'); + break; + case 'warning': + $status->setTitle('A PHP opcode cache is loaded which may cause problems'); + break; + case 'ok': + default: + $status->setTitle('A PHP opcode cache is loaded'); + break; + } + $status->setMessage($message); + } + + return $status; + } + + /** + * Create true type font test image + * + * @return Status\StatusInterface + */ + protected function isTrueTypeFontWorking() + { + if (function_exists('imageftbbox')) { + // 20 Pixels at 96 DPI + $fontSize = (20 / 96 * 72); + $textDimensions = @imageftbbox( + $fontSize, + 0, + __DIR__ . '/../../Resources/Private/Font/vera.ttf', + 'Testing true type support' + ); + $fontBoxWidth = $textDimensions[2] - $textDimensions[0]; + if ($fontBoxWidth < 300 && $fontBoxWidth > 200) { + $status = new Status\OkStatus(); + $status->setTitle('FreeType True Type Font DPI'); + $status->setMessage('Fonts are rendered by FreeType library. ' . + 'We need to ensure that the final dimensions are as expected. ' . + 'This server renderes fonts based on 96 DPI correctly'); + } else { + $status = new Status\NoticeStatus(); + $status->setTitle('FreeType True Type Font DPI'); + $status->setMessage('Fonts are rendered by FreeType library. ' . + 'This server does not render fonts as expected. ' . + 'Please check your FreeType 2 module.'); + } + } else { + $status = new Status\ErrorStatus(); + $status->setTitle('PHP GD library freetype2 support missing'); + $status->setMessage( + 'The core relies on GD library compiled into PHP with freetype2' . + ' support. This is missing on your system. Please install it.' + ); + } + + return $status; + } + + /** + * Check for bug in libxml + * + * @return Status\StatusInterface + */ + protected function checkLibXmlBug() + { + $sampleArray = array('Test>><<Data'); + $xmlContent = '<numIndex index="0">Test>><<Data</numIndex>' . LF; + $xml = GeneralUtility::array2xml($sampleArray, '', -1); + + if ($xmlContent !== $xml) { + $status = new Status\ErrorStatus(); + $status->setTitle('PHP libxml bug present'); + $status->setMessage( + 'Some hosts have problems saving ">><<" in a flexform.' . + ' To fix this, enable [BE][flexformForceCDATA] in' . + ' All Configuration.' + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('PHP libxml bug not present'); + } + + return $status; + } +}