1<?php 2namespace TYPO3\CMS\Core\Error; 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 */ 16use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; 17use TYPO3\CMS\Core\Controller\ErrorPageController; 18use TYPO3\CMS\Core\Messaging\AbstractMessage; 19use TYPO3\CMS\Core\Utility\GeneralUtility; 20 21/** 22 * An exception handler which catches any exception and 23 * renders an error page without backtrace (Web) or a slim 24 * message on CLI. 25 */ 26class ProductionExceptionHandler extends AbstractExceptionHandler 27{ 28 /** 29 * Default title for error messages 30 * 31 * @var string 32 */ 33 protected $defaultTitle = 'Oops, an error occurred!'; 34 35 /** 36 * Default message for error messages 37 * 38 * @var string 39 */ 40 protected $defaultMessage = ''; 41 42 /** 43 * Constructs this exception handler - registers itself as the default exception handler. 44 */ 45 public function __construct() 46 { 47 set_exception_handler([$this, 'handleException']); 48 } 49 50 /** 51 * Echoes an exception for the web. 52 * 53 * @param \Throwable $exception The throwable object. 54 */ 55 public function echoExceptionWeb(\Throwable $exception) 56 { 57 $this->sendStatusHeaders($exception); 58 $this->writeLogEntries($exception, self::CONTEXT_WEB); 59 echo GeneralUtility::makeInstance(ErrorPageController::class)->errorAction( 60 $this->getTitle($exception), 61 $this->getMessage($exception), 62 AbstractMessage::ERROR, 63 $this->discloseExceptionInformation($exception) ? $exception->getCode() : 0 64 ); 65 } 66 67 /** 68 * Echoes an exception for the command line. 69 * 70 * @param \Throwable $exception The throwable object. 71 */ 72 public function echoExceptionCLI(\Throwable $exception) 73 { 74 $filePathAndName = $exception->getFile(); 75 $exceptionCodeNumber = $exception->getCode() > 0 ? '#' . $exception->getCode() . ': ' : ''; 76 $this->writeLogEntries($exception, self::CONTEXT_CLI); 77 echo LF . 'Uncaught TYPO3 Exception ' . $exceptionCodeNumber . $exception->getMessage() . LF; 78 echo 'thrown in file ' . $filePathAndName . LF; 79 echo 'in line ' . $exception->getLine() . LF . LF; 80 die(1); 81 } 82 83 /** 84 * Determines, whether Exception details should be outputted 85 * 86 * @param \Throwable $exception The throwable object. 87 * @return bool 88 */ 89 protected function discloseExceptionInformation(\Throwable $exception) 90 { 91 // Allow message to be shown in production mode if the exception is about 92 // trusted host configuration. By doing so we do not disclose 93 // any valuable information to an attacker but avoid confusions among TYPO3 admins 94 // in production context. 95 if ($exception->getCode() === 1396795884) { 96 return true; 97 } 98 // Show client error messages 40x in every case 99 if ($exception instanceof Http\AbstractClientErrorException) { 100 return true; 101 } 102 // Only show errors if a BE user is authenticated 103 if ($GLOBALS['BE_USER'] instanceof BackendUserAuthentication) { 104 return $GLOBALS['BE_USER']->user['uid'] > 0; 105 } 106 return false; 107 } 108 109 /** 110 * Returns the title for the error message 111 * 112 * @param \Throwable $exception The throwable object. 113 * @return string 114 */ 115 protected function getTitle(\Throwable $exception) 116 { 117 if ($this->discloseExceptionInformation($exception) && method_exists($exception, 'getTitle') && $exception->getTitle() !== '') { 118 return $exception->getTitle(); 119 } 120 return $this->defaultTitle; 121 } 122 123 /** 124 * Returns the message for the error message 125 * 126 * @param \Throwable $exception The throwable object. 127 * @return string 128 */ 129 protected function getMessage(\Throwable $exception) 130 { 131 if ($this->discloseExceptionInformation($exception)) { 132 return $exception->getMessage(); 133 } 134 return $this->defaultMessage; 135 } 136} 137