TYPO3  7.6
backend/Classes/Http/AjaxRequestHandler.php
Go to the documentation of this file.
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 
27 
41 {
46  protected $bootstrap;
47 
52  protected $publicAjaxIds = array(
53  '/ajax/login',
54  '/ajax/logout',
55  '/ajax/login/refresh',
56  '/ajax/login/timedout',
57  '/ajax/rsa/publickey'
58  );
59 
65  public function __construct(Bootstrap $bootstrap)
66  {
67  $this->bootstrap = $bootstrap;
68  }
69 
76  public function handleRequest(ServerRequestInterface $request)
77  {
78  // First get the ajaxID
79  $ajaxID = isset($request->getParsedBody()['ajaxID']) ? $request->getParsedBody()['ajaxID'] : $request->getQueryParams()['ajaxID'];
80 
81  // used for backwards-compatibility
82  $GLOBALS['ajaxID'] = $ajaxID;
83  $request = $request->withAttribute('routePath', $ajaxID);
84  $proceedIfNoUserIsLoggedIn = $this->isLoggedInBackendUserRequired($ajaxID);
85  $this->boot($proceedIfNoUserIsLoggedIn);
86 
87  try {
88  // Backend Routing - check if a valid route is there, and dispatch
89  return $this->dispatch($request);
90  } catch (ResourceNotFoundException $e) {
91  // no Route found, fallback to the traditional AJAX request
92  }
93  return $this->dispatchTraditionalAjaxRequest($request);
94  }
95 
103  public function canHandleRequest(ServerRequestInterface $request)
104  {
105  return $request->getAttribute('isAjaxRequest', false);
106  }
107 
113  public function getPriority()
114  {
115  return 80;
116  }
117 
125  protected function isLoggedInBackendUserRequired($ajaxId)
126  {
127  return in_array($ajaxId, $this->publicAjaxIds, true);
128  }
129 
135  protected function boot($proceedIfNoUserIsLoggedIn)
136  {
137  $this->bootstrap
138  ->checkLockedBackendAndRedirectOrDie($proceedIfNoUserIsLoggedIn)
139  ->checkBackendIpOrDie()
140  ->checkSslBackendAndRedirectIfNeeded()
141  ->initializeBackendRouter()
142  ->loadExtensionTables(true)
143  ->initializeSpriteManager()
144  ->initializeBackendUser()
145  ->initializeBackendAuthentication($proceedIfNoUserIsLoggedIn)
146  ->initializeLanguageObject()
147  ->initializeBackendTemplate()
148  ->endOutputBufferingAndCleanPreviousOutput()
149  ->initializeOutputCompression()
150  ->sendHttpHeaders();
151  }
152 
161  protected function dispatch(ServerRequestInterface $request)
162  {
164  $response = GeneralUtility::makeInstance(Response::class, 'php://temp', 200, [
165  'Content-type' => 'application/json; charset=utf-8',
166  'X-JSON' => 'true'
167  ]);
168 
170  $dispatcher = GeneralUtility::makeInstance(RouteDispatcher::class);
171  return $dispatcher->dispatch($request, $response);
172  }
173 
180  protected function dispatchTraditionalAjaxRequest($request)
181  {
182  $ajaxID = $request->getAttribute('routePath');
183  // Finding the script path from the registry
184  $ajaxRegistryEntry = isset($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID]) ? $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID] : null;
185  $ajaxScript = null;
186  $csrfTokenCheck = false;
187  if ($ajaxRegistryEntry !== null && is_array($ajaxRegistryEntry) && isset($ajaxRegistryEntry['callbackMethod'])) {
188  $ajaxScript = $ajaxRegistryEntry['callbackMethod'];
189  $csrfTokenCheck = $ajaxRegistryEntry['csrfTokenCheck'];
190  }
191 
192  // Instantiating the AJAX object
194  $ajaxObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\AjaxRequestHandler::class, $ajaxID);
195  $ajaxParams = array('request' => $request);
196 
197  // Evaluating the arguments and calling the AJAX method/function
198  if (empty($ajaxID)) {
199  $ajaxObj->setError('No valid ajaxID parameter given.');
200  } elseif (empty($ajaxScript)) {
201  $ajaxObj->setError('No backend function registered for ajaxID "' . $ajaxID . '".');
202  } elseif ($csrfTokenCheck && !$this->isValidRequest($request)) {
203  $ajaxObj->setError('Invalid CSRF token detected for ajaxID "' . $ajaxID . '"!');
204  } else {
205  $success = GeneralUtility::callUserFunction($ajaxScript, $ajaxParams, $ajaxObj, false, true);
206  if ($success === false) {
207  $ajaxObj->setError('Registered backend function for ajaxID "' . $ajaxID . '" was not found.');
208  }
209  }
210 
211  // Outputting the content (and setting the X-JSON-Header)
212  return $ajaxObj->render();
213  }
214 
220  protected function getFormProtection()
221  {
223  }
224 
234  protected function isValidRequest(ServerRequestInterface $request)
235  {
236  $token = (string)(isset($request->getParsedBody()['ajaxToken']) ? $request->getParsedBody()['ajaxToken'] : $request->getQueryParams()['ajaxToken']);
237  return $this->getFormProtection()->validateToken($token, 'ajaxCall', $request->getAttribute('routePath'));
238  }
239 }