c06b092d094d9977949cc54856857be2fb9aec8b
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Http / BackendModuleRequestHandler.php
1 <?php
2 namespace TYPO3\CMS\Backend\Http;
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\Core\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Core\Bootstrap;
19 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
20 use TYPO3\CMS\Core\Exception;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Extbase\Object\ObjectManager;
23
24 /**
25 * Handles the request for backend modules and wizards
26 */
27 class BackendModuleRequestHandler implements \TYPO3\CMS\Core\Core\RequestHandlerInterface {
28
29 /**
30 * @var Bootstrap
31 */
32 protected $bootstrap;
33
34 /**
35 * @var array
36 */
37 protected $moduleRegistry = array();
38
39 /**
40 * @var BackendUserAuthentication
41 */
42 protected $backendUserAuthentication;
43
44 /**
45 * @param Bootstrap $bootstrap The TYPO3 core bootstrap
46 */
47 public function __construct(Bootstrap $bootstrap) {
48 $this->bootstrap = $bootstrap;
49 }
50
51 /**
52 * Handles the request, evaluating the configuration and executes the module accordingly
53 *
54 * @throws Exception
55 */
56 public function handleRequest() {
57 $this->boot();
58
59 $this->moduleRegistry = $GLOBALS['TBE_MODULES'];
60
61 if (!$this->isValidModuleRequest()) {
62 throw new Exception('The CSRF protection token for the requested module is missing or invalid', 1417988921);
63 }
64
65 // Set to empty as it is not needed / always coming from typo3/mod.php
66 $GLOBALS['BACK_PATH'] = '';
67
68 $this->backendUserAuthentication = $GLOBALS['BE_USER'];
69
70 $moduleName = (string)GeneralUtility::_GET('M');
71 if ($this->isDispatchedModule($moduleName)) {
72 $isDispatched = $this->dispatchModule($moduleName);
73 } else {
74 $isDispatched = $this->callTraditionalModule($moduleName);
75 }
76 if ($isDispatched === FALSE) {
77 throw new Exception('No module "' . $moduleName . '" could be found.', 1294585070);
78 }
79 }
80
81 /**
82 * Execute TYPO3 bootstrap
83 */
84 protected function boot() {
85 // Evaluate the constant for skipping the BE user check for the bootstrap, will be done without the constant at a later point
86 if (defined('TYPO3_PROCEED_IF_NO_USER') && TYPO3_PROCEED_IF_NO_USER) {
87 $proceedIfNoUserIsLoggedIn = TRUE;
88 } else {
89 $proceedIfNoUserIsLoggedIn = FALSE;
90 }
91
92 $this->bootstrap->checkLockedBackendAndRedirectOrDie()
93 ->checkBackendIpOrDie()
94 ->checkSslBackendAndRedirectIfNeeded()
95 ->checkValidBrowserOrDie()
96 ->loadExtensionTables(TRUE)
97 ->initializeSpriteManager()
98 ->initializeBackendUser()
99 ->initializeBackendAuthentication($proceedIfNoUserIsLoggedIn)
100 ->initializeLanguageObject()
101 ->initializeBackendTemplate()
102 ->endOutputBufferingAndCleanPreviousOutput()
103 ->initializeOutputCompression()
104 ->sendHttpHeaders();
105 }
106
107 /**
108 * This request handler can handle any backend request coming from mod.php
109 *
110 * @return bool
111 */
112 public function canHandleRequest() {
113 return (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) && !empty((string)GeneralUtility::_GET('M'));
114 }
115
116 /**
117 * Checks if all parameters are met.
118 *
119 * @return bool
120 */
121 protected function isValidModuleRequest() {
122 return $this->getFormProtection()->validateToken((string)GeneralUtility::_GP('moduleToken'), 'moduleCall', (string)GeneralUtility::_GET('M'));
123 }
124
125 /**
126 * A dispatched module, currently only Extbase modules are dispatched,
127 * traditional modules have a module path set.
128 *
129 * @param string $moduleName
130 * @return bool
131 */
132 protected function isDispatchedModule($moduleName) {
133 return empty($this->moduleRegistry['_PATHS'][$moduleName]);
134 }
135
136 /**
137 * Executes the module dispatcher which calls the module appropriately.
138 * Currently only used by Extbase
139 *
140 * @param string $moduleName
141 * @return bool
142 */
143 protected function dispatchModule($moduleName) {
144 if (is_array($this->moduleRegistry['_dispatcher'])) {
145 foreach ($this->moduleRegistry['_dispatcher'] as $dispatcherClassName) {
146 $dispatcher = GeneralUtility::makeInstance(ObjectManager::class)->get($dispatcherClassName);
147 if ($dispatcher->callModule($moduleName) === TRUE) {
148 return TRUE;
149 break;
150 }
151 }
152 }
153 return FALSE;
154 }
155
156 /**
157 * Calls traditional modules which are identified by having a index.php in their directory
158 * and were previously located within the global scope.
159 *
160 * @param string $moduleName
161 * @return bool
162 */
163 protected function callTraditionalModule($moduleName) {
164 $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
165 $GLOBALS['MCONF'] = $moduleConfiguration = $this->getModuleConfiguration($moduleName);
166 if (!empty($moduleConfiguration['access'])) {
167 $this->backendUserAuthentication->modAccess($moduleConfiguration, TRUE);
168 }
169 if (file_exists($moduleBasePath . 'index.php')) {
170 global $SOBE;
171 require $moduleBasePath . 'index.php';
172 return TRUE;
173 }
174 return FALSE;
175 }
176
177 /**
178 * Returns the module configuration which is either provided in a conf.php file
179 * or during module registration
180 *
181 * @param string $moduleName
182 * @return array
183 */
184 protected function getModuleConfiguration($moduleName) {
185 $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
186 if (file_exists($moduleBasePath . 'conf.php')) {
187 // Some modules still rely on this global configuration array in a conf.php file
188 require $moduleBasePath . 'conf.php';
189 $moduleConfiguration = $MCONF;
190 } else {
191 $moduleConfiguration = $this->moduleRegistry['_configuration'][$moduleName];
192 }
193 return $moduleConfiguration;
194 }
195
196
197 /**
198 * Returns the priority - how eager the handler is to actually handle the request.
199 *
200 * @return int The priority of the request handler.
201 */
202 public function getPriority() {
203 return 90;
204 }
205
206 /**
207 * Wrapper method for static form protection utility
208 *
209 * @return \TYPO3\CMS\Core\FormProtection\AbstractFormProtection
210 */
211 protected function getFormProtection() {
212 return FormProtectionFactory::get();
213 }
214
215 }