1: <?php
2: /**
3: * @package Kolab_Filter
4: */
5:
6: /* Some output constants */
7: define('OUT_STDOUT', 128);
8: define('OUT_LOG', 256);
9:
10: /* Failure constants from postfix src/global/sys_exits.h */
11: define('EX_USAGE', 64); /* command line usage error */
12: define('EX_DATAERR', 65); /* data format error */
13: define('EX_NOINPUT', 66); /* cannot open input */
14: define('EX_NOUSER', 67); /* user unknown */
15: define('EX_NOHOST', 68); /* host name unknown */
16: define('EX_UNAVAILABLE', 69); /* service unavailable */
17: define('EX_SOFTWARE', 70); /* internal software error */
18: define('EX_OSERR', 71); /* system resource error */
19: define('EX_OSFILE', 72); /* critical OS file missing */
20: define('EX_CANTCREAT', 73); /* can't create user output file */
21: define('EX_IOERR', 74); /* input/output error */
22: define('EX_TEMPFAIL', 75); /* temporary failure */
23: define('EX_PROTOCOL', 76); /* remote error in protocol */
24: define('EX_NOPERM', 77); /* permission denied */
25: define('EX_CONFIG', 78); /* local configuration error */
26:
27: /**
28: * Provides error handling for the Kolab server filter scripts.
29: *
30: * Copyright 2004-2008 Klarälvdalens Datakonsult AB
31: *
32: * See the enclosed file COPYING for license information (LGPL). If you
33: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
34: *
35: * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
36: * @author Gunnar Wrobel <wrobel@pardus.de>
37: * @package Kolab_Filter
38: */
39: class Horde_Kolab_Filter_Response
40: {
41:
42: /**
43: * Constructor.
44: */
45: function Horde_Kolab_Filter_Response()
46: {
47: /* Set a custom PHP error handler to catch any coding errors */
48: set_error_handler(array($this, '_fatal'));
49: }
50:
51: /**
52: * Handle the results of the message transport.
53: *
54: * @param mixed $result The reponse of the transport.
55: */
56: function handle($result)
57: {
58: /* No error? Be happy and exit clean */
59: if (!is_a($result, 'PEAR_Error')) {
60: exit(0);
61: }
62:
63: $msg = $result->getMessage();
64: $code = $result->getCode();
65:
66: if ($code & OUT_STDOUT) {
67: fwrite(STDOUT, $msg);
68: }
69: if ($code & OUT_LOG || empty($code)) {
70: $this->_log($result);
71: }
72:
73: // FIXME: Add a userinfo handler in case there were multiple
74: // combined errors
75:
76: /* If we have an error code we want to return it to the
77: * calling application and exit here
78: */
79: if ($code) {
80: /* Return the first seven bits as error code to postfix */
81: exit($code & 127);
82: }
83: }
84:
85: /**
86: * An alternative PHP error handler so that we don't drop silent
87: * on fatal errors.
88: *
89: * @param int $errno The error number.
90: * @param string $errmsg The error message.
91: * @param string $filename The file where the error occured.
92: * @param int $linenum The line where the error occured.
93: * @param mixed $vars ?
94: *
95: * @return boolean Always false.
96: */
97: function _fatal($errno, $errmsg, $filename, $linenum, $vars)
98: {
99: /* Ignore strict errors for now since even PEAR will raise
100: * strict notices
101: */
102: if ($errno == E_STRICT || $errno == E_DEPRECATED) {
103: return false;
104: }
105:
106: $fatal = array(E_ERROR,
107: E_PARSE,
108: E_CORE_ERROR,
109: E_COMPILE_ERROR,
110: E_USER_ERROR);
111:
112: if (in_array($errno, $fatal)) {
113: $code = OUT_STDOUT | OUT_LOG | EX_UNAVAILABLE;
114: $msg = 'CRITICAL: You hit a fatal bug in kolab-filter. Please inform the Kolab developers at https://www.intevation.de/roundup/kolab/. The error was: ' . $errmsg;
115: } else {
116: $code = 0;
117: $msg = 'PHP Error: ' . $errmsg;
118: }
119:
120: $error = new PEAR_Error($msg, $code, null, null, 'FILE: ' . $filename . ', LINE: ' . $linenum);
121: $this->handle($error);
122:
123: return false;
124: }
125:
126: /**
127: * Log an error.
128: *
129: * @param PEAR_error $result The reponse of the transport.
130: */
131: function _log($result)
132: {
133: global $conf;
134:
135: $msg = $result->getMessage() . '; Code: ' . $result->getCode();
136:
137: $file = false;
138: $line = false;
139:
140: $user_info = $result->getUserInfo();
141:
142: if (!empty($user_info)) {
143: if (preg_match('/FILE: (.*), LINE: (.*)/', $user_info, $matches)) {
144: $file = $matches[1];
145: $line = $matches[2];
146: }
147: }
148:
149: if (!$file) {
150: $frames = $result->getBacktrace();
151: if (count($frames) > 1) {
152: $frame = $frames[1];
153: } else if (count($frames) == 1) {
154: $frame = $frames[0];
155: }
156: if (isset($frame['file'])) {
157: $file = $frame['file'];
158: }
159: if (isset($frame['line'])) {
160: $line = $frame['line'];
161: }
162: }
163:
164: if (!$file) {
165: /* Log all errors */
166: $file = __FILE__;
167: $line = __LINE__;
168: }
169:
170: /* In debugging mode the errors get delivered to the screen
171: * without a time stamp (mainly because of unit testing)
172: */
173: if (!isset($conf['kolab']['filter']['debug'])
174: || !$conf['kolab']['filter']['debug']) {
175: Horde::logMessage($msg, 'ERR');
176: } else {
177: $msg .= ' (Line ' . $frame['line'] . ' in ' . basename($frame['file']) . ")\n";
178: fwrite(STDOUT, $msg);
179: }
180: }
181: }
182: