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