PageRenderTime 61ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/joomla/libraries/joomla/error/error.php

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