‪TYPO3CMS  10.4
AbstractExceptionHandler.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
23 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
24 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
27 
33 abstract class ‪AbstractExceptionHandler implements ‪ExceptionHandlerInterface, ‪SingletonInterface, LoggerAwareInterface
34 {
35  use LoggerAwareTrait;
36 
37  const ‪CONTEXT_WEB = 'WEB';
38  const ‪CONTEXT_CLI = 'CLI';
39 
40  protected ‪$logExceptionStackTrace = false;
41 
42  private const ‪IGNORED_EXCEPTION_CODES = [
43  1396795884, // Current host header value does not match the configured trusted hosts pattern
44  1581862822, // Failed HMAC validation due to modified __trustedProperties in extbase property mapping
45  1581862823 // Failed HMAC validation due to modified form state in ext:forms
46  ];
47 
55  public function ‪handleException(\Throwable $exception)
56  {
57  switch (PHP_SAPI) {
58  case 'cli':
59  $this->‪echoExceptionCLI($exception);
60  break;
61  default:
62  $this->‪echoExceptionWeb($exception);
63  }
64  }
65 
72  protected function ‪writeLogEntries(\Throwable $exception, $context)
73  {
74  // Do not write any logs for some messages to avoid filling up tables or files with illegal requests
75  if (in_array($exception->getCode(), self::IGNORED_EXCEPTION_CODES, true)) {
76  return;
77  }
78  $filePathAndName = $exception->getFile();
79  $exceptionCodeNumber = $exception->getCode() > 0 ? '#' . $exception->getCode() . ': ' : '';
80  $logTitle = 'Core: Exception handler (' . $context . ')';
81  $logMessage = 'Uncaught TYPO3 Exception: ' . $exceptionCodeNumber . $exception->getMessage() . ' | '
82  . get_class($exception) . ' thrown in file ' . $filePathAndName . ' in line ' . $exception->getLine();
83  if ($context === 'WEB') {
84  $logMessage .= '. Requested URL: ' . $this->‪anonymizeToken(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'));
85  }
86  // When database credentials are wrong, the exception is probably
87  // caused by this. Therefor we cannot do any database operation,
88  // otherwise this will lead into recurring exceptions.
89  try {
90  if ($this->logger) {
91  $this->logger->critical($logTitle . ': ' . $logMessage, [
92  'TYPO3_MODE' => TYPO3_MODE,
93  'exception' => $this->logExceptionStackTrace ? $exception : null
94  ]);
95  }
96  // Write error message to sys_log table
97  $this->‪writeLog($logTitle . ': ' . $logMessage);
98  } catch (\‪Exception $exception) {
99  }
100  }
101 
107  protected function ‪writeLog($logMessage)
108  {
109  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
110  ->getConnectionForTable('sys_log');
111 
112  if (!$connection->isConnected()) {
113  return;
114  }
115  $userId = 0;
116  $workspace = 0;
117  $data = [];
118  $backendUser = $this->‪getBackendUser();
119  if (is_object($backendUser)) {
120  if (isset($backendUser->user['uid'])) {
121  $userId = $backendUser->user['uid'];
122  }
123  if (isset($backendUser->workspace)) {
124  $workspace = $backendUser->workspace;
125  }
126  if (!empty($backendUser->user['ses_backuserid'])) {
127  $data['originalUser'] = $backendUser->user['ses_backuserid'];
128  }
129  }
130 
131  $connection->insert(
132  'sys_log',
133  [
134  'userid' => $userId,
135  'type' => SystemLogType::ERROR,
136  'action' => SystemLogGenericAction::UNDEFINED,
137  'error' => SystemLogErrorClassification::SYSTEM_ERROR,
138  'details_nr' => 0,
139  'details' => str_replace('%', '%%', $logMessage),
140  'log_data' => empty($data) ? '' : serialize($data),
141  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
142  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
143  'workspace' => $workspace
144  ]
145  );
146  }
147 
154  protected function ‪sendStatusHeaders(\Throwable $exception)
155  {
156  if (method_exists($exception, 'getStatusHeaders')) {
157  $headers = $exception->getStatusHeaders();
158  } else {
159  $headers = [‪HttpUtility::HTTP_STATUS_500];
160  }
161  if (!headers_sent()) {
162  foreach ($headers as $header) {
163  header($header);
164  }
165  }
166  }
167 
171  protected function ‪getBackendUser()
172  {
173  return ‪$GLOBALS['BE_USER'];
174  }
175 
182  protected function ‪anonymizeToken(string $requestedUrl): string
183  {
184  $pattern = '/(?<=[tT]oken=)[0-9a-fA-F]{40}/';
185  return preg_replace($pattern, '--AnonymizedToken--', $requestedUrl);
186  }
187 }
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\writeLog
‪writeLog($logMessage)
Definition: AbstractExceptionHandler.php:107
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\$logExceptionStackTrace
‪$logExceptionStackTrace
Definition: AbstractExceptionHandler.php:40
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\CONTEXT_WEB
‪const CONTEXT_WEB
Definition: AbstractExceptionHandler.php:37
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler
Definition: AbstractExceptionHandler.php:34
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\sendStatusHeaders
‪sendStatusHeaders(\Throwable $exception)
Definition: AbstractExceptionHandler.php:154
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\getBackendUser
‪TYPO3 CMS Core Authentication BackendUserAuthentication getBackendUser()
Definition: AbstractExceptionHandler.php:171
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\CONTEXT_CLI
‪const CONTEXT_CLI
Definition: AbstractExceptionHandler.php:38
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\handleException
‪handleException(\Throwable $exception)
Definition: AbstractExceptionHandler.php:55
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface
Definition: ExceptionHandlerInterface.php:24
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪$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:42
‪TYPO3\CMS\Core\Error
Definition: AbstractExceptionHandler.php:16
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface\echoExceptionWeb
‪echoExceptionWeb(\Throwable $exception)
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\anonymizeToken
‪string anonymizeToken(string $requestedUrl)
Definition: AbstractExceptionHandler.php:182
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\HttpUtility\HTTP_STATUS_500
‪const HTTP_STATUS_500
Definition: HttpUtility.php:82
‪TYPO3\CMS\Core\SysLog\Type
Definition: Type.php:24
‪TYPO3\CMS\Core\Error\ExceptionHandlerInterface\echoExceptionCLI
‪echoExceptionCLI(\Throwable $exception)
‪TYPO3\CMS\Core\Error\AbstractExceptionHandler\writeLogEntries
‪writeLogEntries(\Throwable $exception, $context)
Definition: AbstractExceptionHandler.php:72