‪TYPO3CMS  9.5
AbstractExceptionHandler.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 
17 use Psr\Log\LoggerAwareInterface;
18 use Psr\Log\LoggerAwareTrait;
23 
29 abstract class ‪AbstractExceptionHandler implements ‪ExceptionHandlerInterface, ‪SingletonInterface, LoggerAwareInterface
30 {
31  use LoggerAwareTrait;
32 
33  const ‪CONTEXT_WEB = 'WEB';
34  const ‪CONTEXT_CLI = 'CLI';
35 
36  private const ‪IGNORED_EXCEPTION_CODES = [
37  1396795884, // Current host header value does not match the configured trusted hosts pattern
38  1581862822, // Failed HMAC validation due to modified __trustedProperties in extbase property mapping
39  1581862823 // Failed HMAC validation due to modified form state in ext:forms
40  ];
41 
49  public function ‪handleException(\Throwable $exception)
50  {
51  switch (PHP_SAPI) {
52  case 'cli':
53  $this->‪echoExceptionCLI($exception);
54  break;
55  default:
56  $this->‪echoExceptionWeb($exception);
57  }
58  }
59 
66  protected function ‪writeLogEntries(\Throwable $exception, $context)
67  {
68  // Do not write any logs for some messages to avoid filling up tables or files with illegal requests
69  if (in_array($exception->getCode(), self::IGNORED_EXCEPTION_CODES, true)) {
70  return;
71  }
72  $filePathAndName = $exception->getFile();
73  $exceptionCodeNumber = $exception->getCode() > 0 ? '#' . $exception->getCode() . ': ' : '';
74  $logTitle = 'Core: Exception handler (' . $context . ')';
75  $logMessage = 'Uncaught TYPO3 Exception: ' . $exceptionCodeNumber . $exception->getMessage() . ' | '
76  . get_class($exception) . ' thrown in file ' . $filePathAndName . ' in line ' . $exception->getLine();
77  if ($context === 'WEB') {
78  $logMessage .= '. Requested URL: ' . $this->‪anonymizeToken(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'));
79  }
80  // When database credentials are wrong, the exception is probably
81  // caused by this. Therefor we cannot do any database operation,
82  // otherwise this will lead into recurring exceptions.
83  try {
84  if ($this->logger) {
85  $this->logger->critical($logTitle . ': ' . $logMessage, [
86  'TYPO3_MODE' => TYPO3_MODE,
87  'exception' => $exception
88  ]);
89  }
90  // Write error message to sys_log table
91  $this->‪writeLog($logTitle . ': ' . $logMessage);
92  } catch (\‪Exception $exception) {
93  }
94  }
95 
101  protected function ‪writeLog($logMessage)
102  {
103  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
104  ->getConnectionForTable('sys_log');
105 
106  if (!$connection->isConnected()) {
107  return;
108  }
109  $userId = 0;
110  $workspace = 0;
111  $data = [];
112  $backendUser = $this->‪getBackendUser();
113  if (is_object($backendUser)) {
114  if (isset($backendUser->user['uid'])) {
115  $userId = $backendUser->user['uid'];
116  }
117  if (isset($backendUser->workspace)) {
118  $workspace = $backendUser->workspace;
119  }
120  if (!empty($backendUser->user['ses_backuserid'])) {
121  $data['originalUser'] = $backendUser->user['ses_backuserid'];
122  }
123  }
124 
125  $connection->insert(
126  'sys_log',
127  [
128  'userid' => $userId,
129  'type' => 5,
130  'action' => 0,
131  'error' => 2,
132  'details_nr' => 0,
133  'details' => str_replace('%', '%%', $logMessage),
134  'log_data' => empty($data) ? '' : serialize($data),
135  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
136  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
137  'workspace' => $workspace
138  ]
139  );
140  }
141 
148  protected function ‪sendStatusHeaders(\Throwable $exception)
149  {
150  if (method_exists($exception, 'getStatusHeaders')) {
151  $headers = $exception->getStatusHeaders();
152  } else {
153  $headers = [‪HttpUtility::HTTP_STATUS_500];
154  }
155  if (!headers_sent()) {
156  foreach ($headers as $header) {
157  header($header);
158  }
159  }
160  }
161 
165  protected function ‪getBackendUser()
166  {
167  return ‪$GLOBALS['BE_USER'];
168  }
169 
176  protected function ‪anonymizeToken(string $requestedUrl): string
177  {
178  $pattern = '/(?<=[tT]oken=)[0-9a-fA-F]{40}/';
179  return preg_replace($pattern, '--AnonymizedToken--', $requestedUrl);
180  }
181 }
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\writeLog
‪writeLog($logMessage)
Definition: AbstractExceptionHandler.php:101
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\CONTEXT_WEB
‪const CONTEXT_WEB
Definition: AbstractExceptionHandler.php:33
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler
Definition: AbstractExceptionHandler.php:30
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\sendStatusHeaders
‪sendStatusHeaders(\Throwable $exception)
Definition: AbstractExceptionHandler.php:148
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\getBackendUser
‪TYPO3 CMS Core Authentication BackendUserAuthentication getBackendUser()
Definition: AbstractExceptionHandler.php:165
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\CONTEXT_CLI
‪const CONTEXT_CLI
Definition: AbstractExceptionHandler.php:34
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\handleException
‪handleException(\Throwable $exception)
Definition: AbstractExceptionHandler.php:49
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface
Definition: ExceptionHandlerInterface.php:23
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\IGNORED_EXCEPTION_CODES
‪const IGNORED_EXCEPTION_CODES
Definition: AbstractExceptionHandler.php:36
‪TYPO3\CMS\Core\Error
Definition: AbstractExceptionHandler.php:2
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface\echoExceptionWeb
‪echoExceptionWeb(\Throwable $exception)
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\anonymizeToken
‪string anonymizeToken(string $requestedUrl)
Definition: AbstractExceptionHandler.php:176
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Utility\HttpUtility\HTTP_STATUS_500
‪const HTTP_STATUS_500
Definition: HttpUtility.php:79
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface\echoExceptionCLI
‪echoExceptionCLI(\Throwable $exception)
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\writeLogEntries
‪writeLogEntries(\Throwable $exception, $context)
Definition: AbstractExceptionHandler.php:66