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