PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/error/error.php

https://bitbucket.org/pasamio/jhttprequest
PHP | 643 lines | 295 code | 74 blank | 274 comment | 42 complexity | 417ff3b6ab6e6856a4a5ef919fad7c50 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  4. * @license GNU General Public License version 2 or later; see LICENSE
  5. * @package Joomla.Platform
  6. * @subpackage Error
  7. */
  8. defined('JPATH_PLATFORM') or die;
  9. // Error Definition: Illegal Options
  10. define('JERROR_ILLEGAL_OPTIONS', 1);
  11. // Error Definition: Callback does not exist
  12. define('JERROR_CALLBACK_NOT_CALLABLE', 2);
  13. // Error Definition: Illegal Handler
  14. define('JERROR_ILLEGAL_MODE', 3);
  15. /**
  16. * Error Handling Class
  17. *
  18. * This class is inspired in design and concept by patErrorManager <http://www.php-tools.net>
  19. *
  20. * patErrorManager contributors include:
  21. * - gERD Schaufelberger <gerd@php-tools.net>
  22. * - Sebastian Mordziol <argh@php-tools.net>
  23. * - Stephan Schmidt <scst@php-tools.net>
  24. *
  25. * @package Joomla.Platform
  26. * @subpackage Error
  27. * @since 11.1
  28. */
  29. abstract class JError
  30. {
  31. protected static $levels = array(
  32. E_NOTICE => 'Notice',
  33. E_WARNING => 'Warning',
  34. E_ERROR => 'Error'
  35. );
  36. protected static $handlers = array(
  37. E_NOTICE => array('mode' => 'message'),
  38. E_WARNING => array('mode' => 'message'),
  39. E_ERROR => array('mode' => 'callback', 'options' => array('JError','customErrorPage'))
  40. );
  41. protected static $stack = array();
  42. /**
  43. * Method to determine if a value is an exception object. This check supports both JException and PHP5 Exception objects
  44. *
  45. * @param mixed &$object Object to check
  46. * @return boolean True if argument is an exception, false otherwise.
  47. * @since 11.1
  48. w
  49. */
  50. public static function isError(& $object)
  51. {
  52. // supports PHP 5 exception handling
  53. return $object instanceof Exception;
  54. }
  55. /**
  56. * Method for retrieving the last exception object in the error stack
  57. *
  58. * @return mixed Last exception object in the error stack or boolean false if none exist
  59. * @since 11.1
  60. */
  61. public static function getError($unset = false)
  62. {
  63. if (!isset(JError::$stack[0])) {
  64. return false;
  65. }
  66. if ($unset) {
  67. $error = array_shift(JError::$stack);
  68. }
  69. else {
  70. $error = &JError::$stack[0];
  71. }
  72. return $error;
  73. }
  74. /**
  75. * Method for retrieving the exception stack
  76. *
  77. * @return array Chronological array of errors that have been stored during script execution
  78. * @since 11.1
  79. */
  80. public static function getErrors()
  81. {
  82. return JError::$stack;
  83. }
  84. /**
  85. * Method to add non-JError thrown JExceptions to the JError stack for debugging purposes
  86. *
  87. * @access public
  88. * @param object JException
  89. * @return void
  90. * @since 11.1
  91. */
  92. public static function addToStack(JException &$e) {
  93. JError::$stack[] = &$e;
  94. }
  95. /**
  96. * Create a new JException object given the passed arguments
  97. *
  98. * @param int $level The error level - use any of PHP's own error levels for this: E_ERROR, E_WARNING, E_NOTICE, E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE.
  99. * @param string $code The application-internal error code for this error
  100. * @param string $msg The error message, which may also be shown the user if need be.
  101. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN).
  102. *
  103. * @return mixed The JException object
  104. * @since 11.1
  105. *
  106. * @see JException
  107. */
  108. public static function raise($level, $code, $msg, $info = null, $backtrace = false)
  109. {
  110. jimport('joomla.error.exception');
  111. // build error object
  112. $exception = new JException($msg, $code, $level, $info, $backtrace);
  113. return JError::throwError($exception);
  114. }
  115. public static function throwError(&$exception)
  116. {
  117. static $thrown = false;
  118. // If thrown is hit again, we've come back to JError in the middle of throwing another JError, so die!
  119. if ($thrown) {
  120. //echo debug_print_backtrace();
  121. jexit(JText::_('JLIB_ERROR_INFINITE_LOOP'));
  122. }
  123. $thrown = true;
  124. $level = $exception->get('level');
  125. // see what to do with this kind of error
  126. $handler = JError::getErrorHandling($level);
  127. $function = 'handle'.ucfirst($handler['mode']);
  128. if (is_callable(array('JError', $function))) {
  129. $reference = call_user_func_array(array('JError',$function), array(&$exception, (isset($handler['options'])) ? $handler['options'] : array()));
  130. }
  131. else {
  132. // This is required to prevent a very unhelpful white-screen-of-death
  133. jexit(
  134. 'JError::raise -> Static method JError::' . $function . ' does not exist.' .
  135. ' Contact a developer to debug' .
  136. '<br /><strong>Error was</strong> ' .
  137. '<br />' . $exception->getMessage()
  138. );
  139. }
  140. //we don't need to store the error, since JException already does that for us!
  141. //remove loop check
  142. $thrown = false;
  143. return $reference;
  144. }
  145. /**
  146. * Wrapper method for the {@link raise()} method with predefined error level of E_ERROR and backtrace set to true.
  147. *
  148. * @param string $code The application-internal error code for this error
  149. * @param string $msg The error message, which may also be shown the user if need be.
  150. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN).
  151. *
  152. * @return object $error The configured JError object
  153. * @since 11.1
  154. */
  155. public static function raiseError($code, $msg, $info = null)
  156. {
  157. return JError::raise(E_ERROR, $code, $msg, $info, true);
  158. }
  159. /**
  160. * Wrapper method for the {@link raise()} method with predefined error level of E_WARNING and backtrace set to false.
  161. *
  162. * @param string $code The application-internal error code for this error
  163. * @param string $msg The error message, which may also be shown the user if need be.
  164. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN).
  165. *
  166. * @return object $error The configured JError object
  167. * @since 11.1
  168. */
  169. public static function raiseWarning($code, $msg, $info = null)
  170. {
  171. return JError::raise(E_WARNING, $code, $msg, $info);
  172. }
  173. /**
  174. * Wrapper method for the {@link raise()} method with predefined error level of E_NOTICE and backtrace set to false.
  175. *
  176. * @param string $code The application-internal error code for this error
  177. * @param string $msg The error message, which may also be shown the user if need be.
  178. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN).
  179. *
  180. * @return object $error The configured JError object
  181. * @since 11.1
  182. */
  183. public static function raiseNotice($code, $msg, $info = null)
  184. {
  185. return JError::raise(E_NOTICE, $code, $msg, $info);
  186. }
  187. /**
  188. * Method to get the current error handler settings for a specified error level.
  189. *
  190. * @param int $level The error level to retrieve. This can be any of PHP's own error levels, e.g. E_ALL, E_NOTICE...
  191. *
  192. * @return array All error handling details
  193. * @since 11.1
  194. */
  195. public static function getErrorHandling($level)
  196. {
  197. return JError::$handlers[$level];
  198. }
  199. /**
  200. * Method to set the way the JError will handle different error levels. Use this if you want to override the default settings.
  201. *
  202. * Error handling modes:
  203. * - ignore
  204. * - echo
  205. * - verbose
  206. * - die
  207. * - message
  208. * - log
  209. * - callback
  210. *
  211. * You may also set the error handling for several modes at once using PHP's bit operations.
  212. * Examples:
  213. * - E_ALL = Set the handling for all levels
  214. * - E_ERROR | E_WARNING = Set the handling for errors and warnings
  215. * - E_ALL ^ E_ERROR = Set the handling for all levels except errors
  216. *
  217. * @param int $level The error level for which to set the error handling
  218. * @param string $mode The mode to use for the error handling.
  219. * @param mixed $options Optional: Any options needed for the given mode.
  220. *
  221. * @return mixed True on success, or a JException object if failed.
  222. * @since 11.1
  223. */
  224. public static function setErrorHandling($level, $mode, $options = null)
  225. {
  226. $levels = JError::$levels;
  227. $function = 'handle'.ucfirst($mode);
  228. if (!is_callable(array ('JError',$function))) {
  229. return JError::raiseError(E_ERROR, 'JError:'.JERROR_ILLEGAL_MODE, 'Error Handling mode is not known', 'Mode: '.$mode.' is not implemented.');
  230. }
  231. foreach ($levels as $eLevel => $eTitle)
  232. {
  233. if (($level & $eLevel) != $eLevel) {
  234. continue;
  235. }
  236. // set callback options
  237. if ($mode == 'callback') {
  238. if (!is_array($options)) {
  239. return JError::raiseError(E_ERROR, 'JError:'.JERROR_ILLEGAL_OPTIONS, 'Options for callback not valid');
  240. }
  241. if (!is_callable($options)) {
  242. $tmp = array ('GLOBAL');
  243. if (is_array($options)) {
  244. $tmp[0] = $options[0];
  245. $tmp[1] = $options[1];
  246. }
  247. else {
  248. $tmp[1] = $options;
  249. }
  250. return JError::raiseError(E_ERROR, 'JError:'.JERROR_CALLBACK_NOT_CALLABLE, 'Function is not callable', 'Function:'.$tmp[1].' scope '.$tmp[0].'.');
  251. }
  252. }
  253. // save settings
  254. JError::$handlers[$eLevel] = array ('mode' => $mode);
  255. if ($options != null) {
  256. JError::$handlers[$eLevel]['options'] = $options;
  257. }
  258. }
  259. return true;
  260. }
  261. /**
  262. * Method that attaches the error handler to JError
  263. *
  264. * @access public
  265. * @see set_error_handler
  266. */
  267. public static function attachHandler()
  268. {
  269. set_error_handler(array('JError', 'customErrorHandler'));
  270. }
  271. /**
  272. * Method that dettaches the error handler from JError
  273. *
  274. * @access public
  275. * @see restore_error_handler
  276. */
  277. public static function detachHandler()
  278. {
  279. restore_error_handler();
  280. }
  281. /**
  282. * Method to register a new error level for handling errors
  283. *
  284. * This allows you to add custom error levels to the built-in
  285. * - E_NOTICE
  286. * - E_WARNING
  287. * - E_NOTICE
  288. *
  289. * @param int $level Error level to register
  290. * @param string $name Human readable name for the error level
  291. * @param string $handler Error handler to set for the new error level [optional]
  292. *
  293. * @return boolean True on success; false if the level already has been registered
  294. * @since 11.1
  295. */
  296. public static function registerErrorLevel($level, $name, $handler = 'ignore')
  297. {
  298. if (isset(JError::$levels[$level])) {
  299. return false;
  300. }
  301. JError::$levels[$level] = $name;
  302. JError::setErrorHandling($level, $handler);
  303. return true;
  304. }
  305. /**
  306. * Translate an error level integer to a human readable string
  307. * e.g. E_ERROR will be translated to 'Error'
  308. *
  309. * @param int $level Error level to translate
  310. *
  311. * @return mixed Human readable error level name or boolean false if it doesn't exist
  312. * @since 11.1
  313. */
  314. public static function translateErrorLevel($level)
  315. {
  316. if (isset(JError::$levels[$level])) {
  317. return JError::$levels[$level];
  318. }
  319. return false;
  320. }
  321. /**
  322. * Ignore error handler
  323. * - Ignores the error
  324. *
  325. * @param object $error Exception object to handle
  326. * @param array $options Handler options
  327. *
  328. * @return object The exception object
  329. * @since 11.1
  330. *
  331. * @see raise()
  332. */
  333. public static function handleIgnore(&$error, $options)
  334. {
  335. return $error;
  336. }
  337. /**
  338. * Echo error handler
  339. * - Echos the error message to output
  340. *
  341. * @param object $error Exception object to handle
  342. * @param array $options Handler options
  343. *
  344. * @return object The exception object
  345. * @since 11.1
  346. *
  347. * @see raise()
  348. */
  349. public static function handleEcho(&$error, $options)
  350. {
  351. $level_human = JError::translateErrorLevel($error->get('level'));
  352. if (isset ($_SERVER['HTTP_HOST'])) {
  353. // output as html
  354. echo "<br /><b>jos-$level_human</b>: ".$error->get('message')."<br />\n";
  355. }
  356. else {
  357. // output as simple text
  358. if (defined('STDERR')) {
  359. fwrite(STDERR, "J$level_human: ".$error->get('message')."\n");
  360. }
  361. else {
  362. echo "J$level_human: ".$error->get('message')."\n";
  363. }
  364. }
  365. return $error;
  366. }
  367. /**
  368. * Verbose error handler
  369. * - Echos the error message to output as well as related info
  370. *
  371. * @param object $error Exception object to handle
  372. * @param array $options Handler options
  373. *
  374. * @return object The exception object
  375. * @since 11.1
  376. *
  377. * @see raise()
  378. */
  379. public static function handleVerbose(& $error, $options)
  380. {
  381. $level_human = JError::translateErrorLevel($error->get('level'));
  382. $info = $error->get('info');
  383. if (isset ($_SERVER['HTTP_HOST'])) {
  384. // output as html
  385. echo "<br /><b>J$level_human</b>: ".$error->get('message')."<br />\n";
  386. if ($info != null) {
  387. echo "&#160;&#160;&#160;".$info."<br />\n";
  388. }
  389. echo $error->getBacktrace(true);
  390. }
  391. else {
  392. // output as simple text
  393. echo "J$level_human: ".$error->get('message')."\n";
  394. if ($info != null) {
  395. echo "\t".$info."\n";
  396. }
  397. }
  398. return $error;
  399. }
  400. /**
  401. * Die error handler
  402. * - Echos the error message to output and then dies
  403. *
  404. * @param object $error Exception object to handle
  405. * @param array $options Handler options
  406. *
  407. * @return object The exception object
  408. * @since 11.1
  409. *
  410. * @see raise()
  411. */
  412. public static function handleDie(& $error, $options)
  413. {
  414. $level_human = JError::translateErrorLevel($error->get('level'));
  415. if (isset ($_SERVER['HTTP_HOST'])) {
  416. // output as html
  417. jexit("<br /><b>J$level_human</b>: ".$error->get('message')."<br />\n");
  418. }
  419. else {
  420. // output as simple text
  421. if (defined('STDERR')) {
  422. fwrite(STDERR, "J$level_human: ".$error->get('message')."\n");
  423. jexit();
  424. }
  425. else {
  426. jexit("J$level_human: ".$error->get('message')."\n");
  427. }
  428. }
  429. return $error;
  430. }
  431. /**
  432. * Message error handler
  433. * - Enqueues the error message into the system queue
  434. *
  435. * @param object $error Exception object to handle
  436. * @param array $options Handler options
  437. *
  438. * @return object The exception object
  439. * @since 11.1
  440. *
  441. * @see raise()
  442. */
  443. public static function handleMessage(& $error, $options)
  444. {
  445. $appl = JFactory::getApplication();
  446. $type = ($error->get('level') == E_NOTICE) ? 'notice' : 'error';
  447. $appl->enqueueMessage($error->get('message'), $type);
  448. return $error;
  449. }
  450. /**
  451. * Log error handler
  452. * - Logs the error message to a system log file
  453. *
  454. * @param object $error Exception object to handle
  455. * @param array $options Handler options
  456. *
  457. * @return object The exception object
  458. * @since 11.1
  459. *
  460. * @see raise()
  461. */
  462. public static function handleLog(& $error, $options)
  463. {
  464. static $log;
  465. if ($log == null) {
  466. jimport('joomla.error.log');
  467. $fileName = date('Y-m-d').'.error.log';
  468. $options['format'] = "{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}";
  469. $log = JLog::getInstance($fileName, $options);
  470. }
  471. $entry['level'] = $error->get('level');
  472. $entry['code'] = $error->get('code');
  473. $entry['message'] = str_replace(array ("\r","\n"), array ('','\\n'), $error->get('message'));
  474. $log->addEntry($entry);
  475. return $error;
  476. }
  477. /**
  478. * Callback error handler
  479. * - Send the error object to a callback method for error handling
  480. *
  481. * @param object $error Exception object to handle
  482. * @param array $options Handler options
  483. *
  484. * @return object The exception object
  485. * @since 11.1
  486. *
  487. * @see raise()
  488. */
  489. public static function handleCallback(&$error, $options)
  490. {
  491. return call_user_func($options, $error);
  492. }
  493. /**
  494. * Display a custom error page and exit gracefully
  495. *
  496. * @param object $error Exception object
  497. * @return void
  498. * @since 11.1
  499. */
  500. public static function customErrorPage(& $error)
  501. {
  502. // Initialise variables.
  503. jimport('joomla.document.document');
  504. $app = JFactory::getApplication();
  505. $document = JDocument::getInstance('error');
  506. $config = JFactory::getConfig();
  507. // Get the current template from the application
  508. $template = $app->getTemplate();
  509. // Push the error object into the document
  510. $document->setError($error);
  511. @ob_end_clean();
  512. $document->setTitle(JText::_('Error').': '.$error->get('code'));
  513. $data = $document->render(false, array (
  514. 'template' => $template,
  515. 'directory' => JPATH_THEMES,
  516. 'debug' => $config->get('debug')
  517. ));
  518. // Do not allow cache
  519. JResponse::allowCache(false);
  520. JResponse::setBody($data);
  521. echo JResponse::toString();
  522. $app->close(0);
  523. }
  524. public static function customErrorHandler($level, $msg)
  525. {
  526. JError::raise($level, '', $msg);
  527. }
  528. public static function renderBacktrace($error)
  529. {
  530. $contents = null;
  531. $backtrace = $error->getTrace();
  532. if (is_array($backtrace)) {
  533. ob_start();
  534. $j = 1;
  535. echo '<table border="0" cellpadding="0" cellspacing="0" class="Table">';
  536. echo ' <tr>';
  537. echo ' <td colspan="3" class="TD"><strong>Call stack</strong></td>';
  538. echo ' </tr>';
  539. echo ' <tr>';
  540. echo ' <td class="TD"><strong>#</strong></td>';
  541. echo ' <td class="TD"><strong>Function</strong></td>';
  542. echo ' <td class="TD"><strong>Location</strong></td>';
  543. echo ' </tr>';
  544. for ($i = count($backtrace)-1; $i >= 0 ; $i--)
  545. {
  546. echo ' <tr>';
  547. echo ' <td class="TD">'.$j.'</td>';
  548. if (isset($backtrace[$i]['class'])) {
  549. echo ' <td class="TD">'.$backtrace[$i]['class'].$backtrace[$i]['type'].$backtrace[$i]['function'].'()</td>';
  550. }
  551. else {
  552. echo ' <td class="TD">'.$backtrace[$i]['function'].'()</td>';
  553. }
  554. if (isset($backtrace[$i]['file'])) {
  555. echo ' <td class="TD">'.$backtrace[$i]['file'].':'.$backtrace[$i]['line'].'</td>';
  556. }
  557. else {
  558. echo ' <td class="TD">&#160;</td>';
  559. }
  560. echo ' </tr>';
  561. $j++;
  562. }
  563. echo '</table>';
  564. $contents = ob_get_contents();
  565. ob_end_clean();
  566. }
  567. return $contents;
  568. }
  569. }