MyErrorHandler.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. App::uses('ErrorHandler', 'Error');
  3. App::uses('CakeRequest', 'Network');
  4. App::uses('Router', 'Routing');
  5. App::uses('Utility', 'Tools.Utility');
  6. class MyErrorHandler extends ErrorHandler {
  7. /**
  8. * override core one with the following enhancements/fixes:
  9. * - 404s log to a different domain
  10. * - IP, Referer and Browser-Infos are added for better error debugging/tracing
  11. * 2011-12-21 ms
  12. */
  13. public static function handleException(Exception $exception) {
  14. $config = Configure::read('Exception');
  15. if (!empty($config['log'])) {
  16. $message = sprintf("[%s] %s\n%s\n%s",
  17. get_class($exception),
  18. $exception->getMessage(),
  19. $exception->getTraceAsString(),
  20. self::traceDetails()
  21. );
  22. $log = LOG_ERR;
  23. if (in_array(get_class($exception), array('MissingControllerException', 'MissingActionException', 'PrivateActionException', 'NotFoundException'))) {
  24. $log = '404';
  25. }
  26. CakeLog::write($log, $message);
  27. }
  28. $renderer = $config['renderer'];
  29. if ($renderer !== 'ExceptionRenderer') {
  30. list($plugin, $renderer) = pluginSplit($renderer, true);
  31. App::uses($renderer, $plugin . 'Error');
  32. }
  33. try {
  34. $error = new $renderer($exception);
  35. $error->render();
  36. } catch (Exception $e) {
  37. set_error_handler(Configure::read('Error.handler')); // Should be using configured ErrorHandler
  38. Configure::write('Error.trace', false); // trace is useless here since it's internal
  39. $message = sprintf("[%s] %s\n%s\n%s", // Keeping same message format
  40. get_class($e),
  41. $e->getMessage(),
  42. $e->getTraceAsString(),
  43. self::traceDetails()
  44. );
  45. trigger_error($message, E_USER_ERROR);
  46. }
  47. }
  48. /**
  49. * override core one with the following enhancements/fixes:
  50. * - 404s log to a different domain
  51. * - IP, Referer and Browser-Infos are added for better error debugging/tracing
  52. * 2011-12-21 ms
  53. */
  54. public static function handleError($code, $description, $file = null, $line = null, $context = null) {
  55. if (error_reporting() === 0) {
  56. return false;
  57. }
  58. $errorConfig = Configure::read('Error');
  59. list($error, $log) = self::mapErrorCode($code);
  60. if ($log === LOG_ERR) {
  61. return self::handleFatalError($code, $description, $file, $line);
  62. }
  63. $debug = Configure::read('debug');
  64. if ($debug) {
  65. $data = array(
  66. 'level' => $log,
  67. 'code' => $code,
  68. 'error' => $error,
  69. 'description' => $description,
  70. 'file' => $file,
  71. 'line' => $line,
  72. 'context' => $context,
  73. 'start' => 2,
  74. 'path' => Debugger::trimPath($file)
  75. );
  76. return Debugger::getInstance()->outputError($data);
  77. } else {
  78. $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
  79. if (!empty($errorConfig['trace'])) {
  80. $trace = Debugger::trace(array('start' => 1, 'format' => 'log'));
  81. $message .= "\nTrace:\n" . $trace . "\n";
  82. $message .= self::traceDetails();
  83. }
  84. return CakeLog::write($log, $message);
  85. }
  86. }
  87. /**
  88. * Generate an error page when some fatal error happens.
  89. *
  90. * @param integer $code Code of error
  91. * @param string $description Error description
  92. * @param string $file File on which error occurred
  93. * @param integer $line Line that triggered the error
  94. * @return boolean
  95. */
  96. public static function handleFatalError($code, $description, $file, $line) {
  97. $logMessage = 'Fatal Error (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
  98. CakeLog::write(LOG_ERR, $logMessage);
  99. $exceptionHandler = Configure::read('Exception.handler');
  100. if (!is_callable($exceptionHandler)) {
  101. return false;
  102. }
  103. if (Configure::read('debug')) {
  104. return false;
  105. }
  106. if (ob_get_level()) {
  107. ob_clean();
  108. }
  109. if (Configure::read('debug')) {
  110. call_user_func($exceptionHandler, new FatalErrorException($description, 500, $file, $line));
  111. } else {
  112. call_user_func($exceptionHandler, new InternalErrorException());
  113. }
  114. return false;
  115. }
  116. /**
  117. * append some more infos to better track down the error
  118. * @return string
  119. * 2011-12-21 ms
  120. */
  121. public static function traceDetails() {
  122. if (strpos($_SERVER['REQUEST_URI'], '/test.php?') === 0) {
  123. return null;
  124. }
  125. $currentUrl = Router::url(); //isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'n/a';
  126. $refererUrl = Utility::getReferer(); //Router::getRequest()->url().'
  127. App::uses('CakeSession', 'Model/Datasource');
  128. $uid = CakeSession::read('Auth.User.id');
  129. if (!isset($uid)) {
  130. $uid = (!empty($_SESSION) && !empty($_SESSION['Auth']['User']['id'])) ? $_SESSION['Auth']['User']['id'] : null;
  131. }
  132. $data = array(
  133. @CakeRequest::clientIp(),
  134. $currentUrl.(!empty($refererUrl) ? (' ('.$refererUrl.')') : ''),
  135. $uid,
  136. env('HTTP_USER_AGENT')
  137. );
  138. return implode(' - ', $data);
  139. }
  140. }