[BUGFIX] Display detected fatal in extension check
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Controller / ToolController.php
1 <?php
2 namespace TYPO3\CMS\Install\Controller;
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 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 /**
31 * Install tool controller, dispatcher class of the install tool.
32 *
33 * Handles install tool session, login and login form rendering,
34 * calls actions that need authentication and handles form tokens.
35 */
36 class ToolController extends AbstractController {
37
38 /**
39 * @var array List of valid action names that need authentication
40 */
41 protected $authenticationActions = array(
42 'welcome',
43 'importantActions',
44 'systemEnvironment',
45 'configuration',
46 'folderStructure',
47 'testSetup',
48 'updateWizard',
49 'allConfiguration',
50 'cleanUp',
51 'loadExtensions',
52 );
53
54 /**
55 * Main dispatch method
56 *
57 * @return void
58 */
59 public function execute() {
60 $this->loadBaseExtensions();
61 $this->initializeObjectManager();
62
63 // Warning: Order of these methods is security relevant and interferes with different access
64 // conditions (new/existing installation). See the single method comments for details.
65 $this->outputInstallToolNotEnabledMessageIfNeeded();
66 $this->outputInstallToolPasswordNotSetMessageIfNeeded();
67 $this->initializeSession();
68 $this->checkSessionToken();
69 $this->checkSessionLifetime();
70 $this->logoutIfRequested();
71 $this->loginIfRequested();
72 $this->outputLoginFormIfNotAuthorized();
73 $this->registerExtensionConfigurationErrorHandler();
74 $this->dispatchAuthenticationActions();
75 }
76
77 /**
78 * Logout user if requested
79 *
80 * @return void
81 */
82 protected function logoutIfRequested() {
83 $action = $this->getAction();
84 if ($action === 'logout') {
85 // @TODO: This and similar code in step action DefaultConfiguration should be moved to enable install file service
86 $enableInstallToolFile = PATH_typo3conf . 'ENABLE_INSTALL_TOOL';
87 if (is_file($enableInstallToolFile) && trim(file_get_contents($enableInstallToolFile)) !== 'KEEP_FILE') {
88 unlink($enableInstallToolFile);
89 }
90
91 /** @var $formProtection \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection */
92 $formProtection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get(
93 'TYPO3\\CMS\\Core\\FormProtection\\InstallToolFormProtection'
94 );
95 $formProtection->clean();
96 $this->session->destroySession();
97 $this->redirect();
98 }
99 }
100
101 /**
102 * This function registers a shutdown function, which is called even if a fatal error occurs.
103 * The request either gets redirected to an action where all extension configurations are checked for compatibility or
104 * an information with a link to that action.
105 *
106 * @return void
107 */
108 protected function registerExtensionConfigurationErrorHandler() {
109 register_shutdown_function(function() {
110 $error = error_get_last();
111 if ($error !== NULL) {
112 $errorType = $error["type"];
113
114 if ($errorType & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) {
115 $getPostValues = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('install');
116
117 $parameters = array();
118
119 // Add context parameter in case this script was called within backend scope
120 $context = 'install[context]=standalone';
121 if (isset($getPostValues['context']) && $getPostValues['context'] === 'backend') {
122 $context = 'install[context]=backend';
123 }
124 $parameters[] = $context;
125
126 // Add controller parameter
127 $parameters[] = 'install[controller]=tool';
128
129 // Add action if specified
130 $parameters[] = 'install[action]=loadExtensions';
131
132 // Add error to display a message what triggered the check
133 $errorEncoded = json_encode($error);
134 $parameters[] = 'install[lastError]=' . rawurlencode($errorEncoded);
135 // We do not use GeneralUtility here to be sure that hash generation works even if that class might not exist any more.
136 $parameters[] = 'install[lastErrorHash]=' . hash_hmac('sha1', $errorEncoded, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'InstallToolError');
137
138 $redirectLocation = 'Install.php?' . implode('&', $parameters);
139
140 if (!headers_sent()) {
141 \TYPO3\CMS\Core\Utility\HttpUtility::redirect(
142 $redirectLocation,
143 \TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_303
144 );
145 } else {
146 echo '
147 <p><strong>
148 The system detected a fatal error during script execution.
149 Please use the <a href="' . $redirectLocation . '">extension check tool</a> to find incompatible extensions.
150 </strong></p>';
151 }
152 }
153 }
154 });
155 }
156
157 /**
158 * Get last error values of install tool.
159 *
160 * @return array
161 */
162 protected function getLastError() {
163 $getVars = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('install');
164 $lastError = array();
165 if (isset($getVars['lastError']) && isset($getVars['lastErrorHash']) && !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
166 $calculatedHash = hash_hmac('sha1', $getVars['lastError'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'InstallToolError');
167 if ($calculatedHash === $getVars['lastErrorHash']) {
168 $lastError = json_decode($getVars['lastError'], TRUE);
169 }
170 }
171 return $lastError;
172 }
173
174 /**
175 * Call an action that needs authentication
176 *
177 * @throws Exception
178 * @return string Rendered content
179 */
180 protected function dispatchAuthenticationActions() {
181 $action = $this->getAction();
182 if ($action === '') {
183 $action = 'welcome';
184 }
185 $this->validateAuthenticationAction($action);
186 $actionClass = ucfirst($action);
187 /** @var \TYPO3\CMS\Install\Controller\Action\ActionInterface $toolAction */
188 $toolAction = $this->objectManager->get('TYPO3\\CMS\\Install\\Controller\\Action\\Tool\\' . $actionClass);
189 if (!($toolAction instanceof \TYPO3\CMS\Install\Controller\Action\ActionInterface)) {
190 throw new Exception(
191 $action . ' does not implement ActionInterface',
192 1369474308
193 );
194 }
195 $toolAction->setController('tool');
196 $toolAction->setAction($action);
197 $toolAction->setToken($this->generateTokenForAction($action));
198 $toolAction->setPostValues($this->getPostValues());
199 $toolAction->setLastError($this->getLastError());
200 $this->output($toolAction->handle());
201 }
202 }