1: <?php
2: 3: 4:
5:
6:
7: require_once dirname(__FILE__) . '/Base.php';
8:
9:
10: require_once dirname(__FILE__) . '/Transport.php';
11:
12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
25: class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base
26: {
27: 28: 29: 30: 31:
32: private $_application;
33:
34: 35: 36: 37: 38:
39: private $_temporary;
40:
41: 42: 43: 44: 45:
46: var ;
47:
48: 49: 50: 51: 52: 53: 54: 55: 56:
57: public function __construct(
58: Horde_Kolab_Filter_Configuration $config,
59: Horde_Kolab_Filter_Temporary $temporary,
60: Horde_Log_Logger $logger,
61: Horde_Kolab_Filter $application
62: ) {
63: parent::__construct($config, $logger);
64: $this->_temporary = $temporary;
65: $this->_application = $application;
66: }
67:
68: 69: 70: 71: 72:
73: public function init()
74: {
75: parent::init();
76: $this->_temporary->init();
77: }
78:
79: 80: 81: 82: 83: 84: 85: 86:
87: function _parse($inh, $transport)
88: {
89: global $conf;
90:
91: if (empty($transport)) {
92: if (isset($conf['kolab']['filter']['delivery_backend'])) {
93: $transport = $conf['kolab']['filter']['delivery_backend'];
94: } else {
95: $transport = 'lmtp';
96: }
97: }
98:
99: $this->_tmpfh = $this->_temporary->getHandle();
100:
101: $ical = false;
102: $add_headers = array();
103: $headers_done = false;
104:
105:
106: $headers_done = false;
107: while (!feof($inh) && !$headers_done) {
108: $buffer = fgets($inh, 8192);
109: $line = rtrim( $buffer, "\r\n");
110: if ($line == '') {
111:
112: $headers_done = true;
113: } else if (preg_match('#^Content-Type: text/calendar#i', $line)) {
114: Horde::logMessage("Found iCal data in message", 'DEBUG');
115: $ical = true;
116: } else if (preg_match('#^Message-ID: (.*)#i', $line, $regs)) {
117: $this->_id = $regs[1];
118: }
119: if (@fwrite($this->_tmpfh, $buffer) === false) {
120: $msg = $php_errormsg;
121: return PEAR::raiseError(sprintf("Error: Could not write to %s: %s",
122: $this->_tmpfile, $msg),
123: OUT_LOG | EX_IOERR);
124: }
125: }
126:
127: if ($ical) {
128: 129: 130:
131: while (!feof($inh)) {
132: $buffer = fread($inh, 8192);
133: if (@fwrite($this->_tmpfh, $buffer) === false) {
134: $msg = $php_errormsg;
135: return PEAR::raiseError(sprintf("Error: Could not write to %s: %s",
136: $this->_tmpfile, $msg),
137: OUT_LOG | EX_IOERR);
138: }
139: }
140: } else {
141: 142: 143: 144:
145: while (!feof($inh)) {
146: $buffer = fread($inh, 8192);
147: if (@fwrite($this->_tmpfh, $buffer) === false) {
148: $msg = $php_errormsg;
149: return PEAR::raiseError(sprintf("Error: Could not write to %s: %s",
150: $this->_tmpfile, $msg),
151: OUT_LOG | EX_IOERR);
152: }
153: if (strpos($buffer, 'text/calendar')) {
154: $ical = true;
155: }
156: }
157: }
158:
159:
160: if (@fclose($this->_tmpfh) === false) {
161: $msg = $php_errormsg;
162: return PEAR::raiseError(sprintf("Error: Failed closing %s: %s",
163: $this->_tmpfile, $msg),
164: OUT_LOG | EX_IOERR);
165: }
166:
167: $recipients = $this->_config->getRecipients();
168:
169: if ($ical) {
170: require_once 'Horde/Kolab/Resource.php';
171: $newrecips = array();
172: foreach ($recipients as $recip) {
173: if (strpos($recip, '+')) {
174: list($local, $rest) = explode('+', $recip, 2);
175: list($rest, $domain) = explode('@', $recip, 2);
176: $resource = $local . '@' . $domain;
177: } else {
178: $resource = $recip;
179: }
180: Horde::logMessage(sprintf("Calling resmgr_filter(%s, %s, %s, %s)",
181: $this->_fqhostname, $this->_sender,
182: $resource, $this->_tmpfile), 'DEBUG');
183: $r = new Kolab_Resource();
184: $rc = $r->handleMessage($this->_fqhostname, $this->_sender,
185: $resource, $this->_tmpfile);
186: $r->cleanup();
187: if (is_a($rc, 'PEAR_Error')) {
188: return $rc;
189: } else if (is_a($rc, 'Horde_Kolab_Resource_Reply')) {
190: $result = $this->_transportItipReply($rc);
191: if (is_a($result, 'PEAR_Error')) {
192: return $result;
193: }
194: Horde::logMessage('Successfully sent iTip reply', 'DEBUG');
195: } else if ($rc === true) {
196: $newrecips[] = $resource;
197: }
198: }
199: $recipients = $newrecips;
200: $this->_add_headers[] = 'X-Kolab-Scheduling-Message: TRUE';
201: } else {
202: $this->_add_headers[] = 'X-Kolab-Scheduling-Message: FALSE';
203: }
204:
205:
206: if (empty($recipients)) {
207: $this->_logger->debug('No recipients left.');
208: return;
209: } else {
210: $result = $this->_deliver($transport, $recipients);
211: if (is_a($result, 'PEAR_Error')) {
212: return $result;
213: }
214: }
215:
216: $this->_logger->debug('Filter_Incoming successfully completed.');
217: }
218:
219: private function _transportItipReply(Horde_Kolab_Resource_Reply $reply)
220: {
221: global $conf;
222:
223: if (isset($conf['kolab']['filter']['itipreply'])) {
224: $driver = $conf['kolab']['filter']['itipreply']['driver'];
225: $host = $conf['kolab']['filter']['itipreply']['params']['host'];
226: $port = $conf['kolab']['filter']['itipreply']['params']['port'];
227: } else {
228: $driver = 'smtp';
229: $host = 'localhost';
230: $port = 25;
231: }
232:
233: $transport = Horde_Kolab_Filter_Transport::factory(
234: $driver,
235: array('host' => $host, 'port' => $port)
236: );
237:
238: $result = $transport->start($reply->getSender(), $reply->getRecipient());
239: if (is_a($result, 'PEAR_Error')) {
240: return PEAR::raiseError('Unable to send iTip reply: ' . $result->getMessage(),
241: OUT_LOG | EX_TEMPFAIL);
242: }
243:
244: $result = $transport->data($reply->getData());
245: if (is_a($result, 'PEAR_Error')) {
246: return PEAR::raiseError('Unable to send iTip reply: ' . $result->getMessage(),
247: OUT_LOG | EX_TEMPFAIL);
248: }
249:
250: $result = $transport->end();
251: if (is_a($result, 'PEAR_Error')) {
252: return PEAR::raiseError('Unable to send iTip reply: ' . $result->getMessage(),
253: OUT_LOG | EX_TEMPFAIL);
254: }
255: }
256:
257: 258: 259: 260: 261: 262: 263:
264: function _deliver($transport, $recipients)
265: {
266: global $conf;
267:
268: if (isset($conf['kolab']['filter']['lmtp_host'])) {
269: $host = $conf['kolab']['filter']['lmtp_host'];
270: } else {
271: $host = 'localhost';
272: }
273: if (isset($conf['kolab']['filter']['lmtp_port'])) {
274: $port = $conf['kolab']['filter']['lmtp_port'];
275: } else {
276: $port = 2003;
277: }
278:
279:
280: $userDb = $this->_application->getUserDb();
281:
282: $hosts = array();
283: foreach ($recipients as $recipient) {
284: if (strpos($recipient, '+')) {
285: list($local, $rest) = explode('+', $recipient, 2);
286: list($rest, $domain) = explode('@', $recipient, 2);
287: $real_recipient = $local . '@' . $domain;
288: } else {
289: $real_recipient = $recipient;
290: }
291: try {
292:
293: $userDb->server->connectGuid();
294: $guid = $userDb->search->searchGuidForUidOrMail($real_recipient);
295: if (empty($guid)) {
296: throw new Horde_Kolab_Filter_Exception_Temporary(
297: sprintf('User %s does not exist!', $real_recipient)
298: );
299: }
300: $imapserver = $userDb->objects->fetch(
301: $guid, 'Horde_Kolab_Server_Object_Kolab_User'
302: )->getSingle('kolabHomeServer');
303: } catch (Horde_Kolab_Server_Exception $e) {
304:
305:
306:
307:
308: throw new Horde_Kolab_Filter_Exception_Temporary(
309: sprintf(
310: 'Failed identifying IMAP host of user %s. Error was: %s',
311: $real_recipient, $e->getMessage()
312: ),
313: $e
314: );
315: }
316: if (!empty($imapserver)) {
317: $uhost = $imapserver;
318: } else {
319: $uhost = $host;
320: }
321: $hosts[$uhost][] = $recipient;
322: }
323:
324: foreach (array_keys($hosts) as $imap_host) {
325: $params = array('host' => $imap_host, 'port' => $port);
326: if ($imap_host != $host) {
327: $params['user'] = $conf['kolab']['filter']['lmtp_user'];
328: $params['pass'] = $conf['kolab']['filter']['lmtp_pass'];
329: }
330: $transport = &Horde_Kolab_Filter_Transport::factory($transport, $params);
331:
332: $tmpf = $this->_temporary->getReadHandle();
333: if (!$tmpf) {
334: $msg = $php_errormsg;
335: return PEAR::raiseError(sprintf("Error: Could not open %s for writing: %s",
336: $this->_tmpfile, $msg),
337: OUT_LOG | EX_IOERR);
338: }
339:
340: $result = $transport->start($this->_config->getSender(), $hosts[$imap_host]);
341: if (is_a($result, 'PEAR_Error')) {
342: return $result;
343: }
344:
345: $headers_done = false;
346: while (!feof($tmpf) && !$headers_done) {
347: $buffer = fgets($tmpf, 8192);
348: if (!$headers_done && rtrim($buffer, "\r\n") == '') {
349: $headers_done = true;
350: foreach ($this->_add_headers as $h) {
351: $result = $transport->data("$h\r\n");
352: if (is_a($result, 'PEAR_Error')) {
353: return $result;
354: }
355: }
356: }
357: $result = $transport->data($buffer);
358: if (is_a($result, 'PEAR_Error')) {
359: return $result;
360: }
361: }
362:
363: while (!feof($tmpf)) {
364: $buffer = fread($tmpf, 8192);
365: $len = strlen($buffer);
366:
367: 368: 369: 370:
371: while ($buffer{$len-1} == "\r" && $len < 8192 + 100) {
372: $buffer .= fread($tmpf, 1);
373: $len++;
374: }
375: $result = $transport->data($buffer);
376: if (is_a($result, 'PEAR_Error')) {
377: return $result;
378: }
379: }
380: return $transport->end();
381: }
382: }
383: }
384: ?>
385: