1: <?php
2:
3: /**
4: * Smarty error handler
5: *
6: * @package Smarty
7: * @subpackage PluginsInternal
8: * @author Uwe Tews
9: *
10: * @deprecated
11: Smarty does no longer use @filemtime()
12: */
13: class Smarty_Internal_ErrorHandler
14: {
15: /**
16: * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
17: */
18: public static $mutedDirectories = array();
19:
20: /**
21: * error handler returned by set_error_handler() in self::muteExpectedErrors()
22: */
23: private static $previousErrorHandler = null;
24:
25: /**
26: * Enable error handler to mute expected messages
27: *
28: */
29: public static function muteExpectedErrors()
30: {
31: /*
32: error muting is done because some people implemented custom error_handlers using
33: http://php.net/set_error_handler and for some reason did not understand the following paragraph:
34:
35: It is important to remember that the standard PHP error handler is completely bypassed for the
36: error types specified by error_types unless the callback function returns FALSE.
37: error_reporting() settings will have no effect and your error handler will be called regardless -
38: however you are still able to read the current value of error_reporting and act appropriately.
39: Of particular note is that this value will be 0 if the statement that caused the error was
40: prepended by the @ error-control operator.
41:
42: Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
43: - @filemtime() is almost twice as fast as using an additional file_exists()
44: - between file_exists() and filemtime() a possible race condition is opened,
45: which does not exist using the simple @filemtime() approach.
46: */
47: $error_handler = array('Smarty_Internal_ErrorHandler', 'mutingErrorHandler');
48: $previous = set_error_handler($error_handler);
49: // avoid dead loops
50: if ($previous !== $error_handler) {
51: self::$previousErrorHandler = $previous;
52: }
53: }
54:
55: /**
56: * Error Handler to mute expected messages
57: *
58: * @link http://php.net/set_error_handler
59: *
60: * @param integer $errno Error level
61: * @param $errstr
62: * @param $errfile
63: * @param $errline
64: * @param $errcontext
65: *
66: * @return bool
67: */
68: public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext = array())
69: {
70: $_is_muted_directory = false;
71: // add the SMARTY_DIR to the list of muted directories
72: if (!isset(self::$mutedDirectories[ SMARTY_DIR ])) {
73: $smarty_dir = realpath(SMARTY_DIR);
74: if ($smarty_dir !== false) {
75: self::$mutedDirectories[ SMARTY_DIR ] =
76: array('file' => $smarty_dir, 'length' => strlen($smarty_dir),);
77: }
78: }
79: // walk the muted directories and test against $errfile
80: foreach (self::$mutedDirectories as $key => &$dir) {
81: if (!$dir) {
82: // resolve directory and length for speedy comparisons
83: $file = realpath($key);
84: if ($file === false) {
85: // this directory does not exist, remove and skip it
86: unset(self::$mutedDirectories[ $key ]);
87: continue;
88: }
89: $dir = array('file' => $file, 'length' => strlen($file),);
90: }
91: if (!strncmp($errfile, $dir[ 'file' ], $dir[ 'length' ])) {
92: $_is_muted_directory = true;
93: break;
94: }
95: }
96: // pass to next error handler if this error did not occur inside SMARTY_DIR
97: // or the error was within smarty but masked to be ignored
98: if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
99: if (self::$previousErrorHandler) {
100: return call_user_func(
101: self::$previousErrorHandler,
102: $errno,
103: $errstr,
104: $errfile,
105: $errline,
106: $errcontext
107: );
108: } else {
109: return false;
110: }
111: }
112: }
113: }
114: