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