8f6b86cc |
1 | <?php |
2 | |
3 | /** |
1a09384c |
4 | * mime.class |
8f6b86cc |
5 | * |
6 | * Copyright (c) 2002 The SquirrelMail Project Team |
7 | * Licensed under the GNU GPL. For full terms see the file COPYING. |
8 | * |
27da67ae |
9 | * |
8f6b86cc |
10 | * This contains functions needed to handle mime messages. |
11 | * |
12 | * $Id$ |
13 | */ |
14 | |
c9c7acf1 |
15 | |
16 | |
e8bedb2d |
17 | /* |
18 | * rdc822_header class |
19 | * input: header_string or array |
20 | */ |
c9c7acf1 |
21 | class rfc822_header |
22 | { |
e8bedb2d |
23 | var $date = '', |
24 | $subject = '', |
fc0dec58 |
25 | $from = array(), |
26 | $sender = '', |
27 | $reply_to = array(), |
28 | $to = array(), |
29 | $cc = array(), |
30 | $bcc = array(), |
31 | $in_reply_to = '', |
32 | $message_id = '', |
33 | $mime = false, |
34 | $content_type = '', |
35 | $disposition = '', |
36 | $xmailer = '', |
37 | $priority = 3, |
38 | $dnt = '', |
39 | $mlist = array(), |
40 | $more_headers = array(); /* only needed for constructing headers |
41 | in smtp.php */ |
e8bedb2d |
42 | |
c52ffd66 |
43 | function parseHeader($hdr) |
44 | { |
45 | if (is_array($hdr)) |
1d9392e4 |
46 | { |
47 | $hdr = implode('',$hdr); |
48 | } |
e8bedb2d |
49 | /* first we unfold the header */ |
1d9392e4 |
50 | $hdr = trim(str_replace(array("\r\n\t","\r\n "),array('',''),$hdr)); |
51 | /* |
52 | * now we can make a new header array with each element representing |
53 | * a headerline |
54 | */ |
55 | $hdr = explode("\r\n" , $hdr); |
56 | foreach ($hdr as $line) |
57 | { |
58 | $pos = strpos($line,':'); |
59 | if ($pos > 0) |
60 | { |
61 | $field = substr($line,0,$pos); |
62 | $value = trim(substr($line,$pos+1)); |
072dda67 |
63 | if(!preg_match('/^X.*/i',$field)) { |
1d9392e4 |
64 | $value = $this->stripComments($value); |
65 | } |
66 | $this->parseField($field,$value); |
67 | } |
68 | } |
69 | if ($this->content_type == '') |
70 | { |
71 | $this->parseContentType('text/plain; charset=us-ascii'); |
72 | } |
e8bedb2d |
73 | } |
319cf0d2 |
74 | |
c52ffd66 |
75 | function stripComments($value) |
76 | { |
e8bedb2d |
77 | $cnt = strlen($value); |
78 | $s = ''; |
79 | $i = 0; |
c52ffd66 |
80 | while ($i < $cnt) |
81 | { |
e8bedb2d |
82 | switch ($value{$i}) |
83 | { |
84 | case ('"'): |
85 | $s .= '"'; |
86 | $i++; |
c52ffd66 |
87 | while ($value{$i} != '"') |
88 | { |
89 | if ($value{$i} == '\\') |
90 | { |
e8bedb2d |
91 | $s .= '\\'; |
92 | $i++; |
93 | } |
94 | $s .= $value{$i}; |
95 | $i++; |
c52ffd66 |
96 | if ($i > $cnt) break; |
e8bedb2d |
97 | } |
98 | $s .= $value{$i}; |
99 | break; |
100 | case ('('): |
c52ffd66 |
101 | while ($value{$i} != ')') |
102 | { |
103 | if ($value{$i} == '\\') |
104 | { |
e8bedb2d |
105 | $i++; |
106 | } |
107 | $i++; |
108 | } |
109 | break; |
110 | default: |
111 | $s .= $value{$i}; |
112 | break; |
113 | } |
114 | $i++; |
115 | } |
116 | return $s; |
117 | } |
319cf0d2 |
118 | |
c9c7acf1 |
119 | function parseField($field,$value) |
120 | { |
e8bedb2d |
121 | $field = strtolower($field); |
122 | switch($field) |
123 | { |
124 | case ('date'): |
125 | $d = strtr($value, array(' ' => ' ')); |
126 | $d = explode(' ', $d); |
127 | $this->date = getTimeStamp($d); |
128 | break; |
129 | case ('subject'): |
130 | $this->subject = $value; |
131 | break; |
132 | case ('from'): |
133 | $this->from = $this->parseAddress($value,true); |
134 | break; |
135 | case ('sender'): |
136 | $this->sender = $this->parseAddress($value); |
137 | break; |
138 | case ('reply-to'): |
139 | $this->reply_to = $this->parseAddress($value, true); |
140 | break; |
141 | case ('to'): |
142 | $this->to = $this->parseAddress($value, true); |
143 | break; |
144 | case ('cc'): |
145 | $this->cc = $this->parseAddress($value, true); |
146 | break; |
147 | case ('bcc'): |
148 | $this->bcc = $this->parseAddress($value, true); |
149 | break; |
150 | case ('in-reply-to'): |
151 | $this->in_reply_to = $value; |
152 | break; |
153 | case ('message_id'): |
154 | $this->message_id = $value; |
155 | break; |
156 | case ('disposition-notification-to'): |
157 | $this->dnt = $this->parseAddress($value); |
158 | break; |
159 | case ('mime-Version'): |
160 | $value = str_replace(' ','',$value); |
c52ffd66 |
161 | if ($value == '1.0') |
162 | { |
e8bedb2d |
163 | $this->mime = true; |
164 | } |
165 | break; |
166 | case ('content-type'): |
167 | $this->parseContentType($value); |
168 | break; |
169 | case ('content-disposition'): |
170 | $this->parseDisposition($value); |
171 | break; |
01d3a290 |
172 | case ('user-agent'): |
e8bedb2d |
173 | case ('x-mailer'): |
174 | $this->xmailer = $value; |
175 | break; |
176 | case ('x-priority'): |
177 | $this->priority = $value; |
178 | break; |
179 | case ('list-post'): |
180 | $this->mlist('post',$value); |
181 | break; |
182 | case ('list-reply'): |
183 | $this->mlist('reply',$value); |
184 | break; |
185 | case ('list-subscribe'): |
186 | $this->mlist('subscribe',$value); |
187 | break; |
188 | case ('list-unsubscribe'): |
189 | $this->mlist('unsubscribe',$value); |
190 | break; |
191 | case ('list-archive'): |
192 | $this->mlist('archive',$value); |
193 | break; |
194 | case ('list-owner'): |
195 | $this->mlist('owner',$value); |
196 | break; |
197 | case ('list-help'): |
198 | $this->mlist('help',$value); |
199 | break; |
200 | case ('list-id'): |
201 | $this->mlist('id',$value); |
202 | break; |
203 | default: |
204 | break; |
205 | } |
206 | } |
207 | |
c9c7acf1 |
208 | function parseAddress($address, $ar=false, $addr_ar = array(), $group = '') |
209 | { |
e8bedb2d |
210 | $pos = 0; |
211 | $j = strlen( $address ); |
212 | $name = ''; |
213 | $addr = ''; |
214 | while ( $pos < $j ) { |
215 | switch ($address{$pos}) |
216 | { |
217 | case ('"'): /* get the personal name */ |
218 | $pos++; |
c52ffd66 |
219 | if ($address{$pos} == '"') |
220 | { |
e8bedb2d |
221 | $pos++; |
c52ffd66 |
222 | } else |
223 | { |
224 | while ( $pos < $j && $address{$pos} != '"') |
225 | { |
226 | if (substr($address, $pos, 2) == '\\"') |
227 | { |
228 | $name .= $address{$pos}; |
229 | $pos++; |
230 | } elseif (substr($address, $pos, 2) == '\\\\') |
231 | { |
232 | $name .= $address{$pos}; |
233 | $pos++; |
234 | } |
235 | $name .= $address{$pos}; |
e8bedb2d |
236 | $pos++; |
c52ffd66 |
237 | } |
e8bedb2d |
238 | } |
239 | $pos++; |
240 | break; |
241 | case ('<'): /* get email address */ |
242 | $addr_start=$pos; |
243 | $pos++; |
c52ffd66 |
244 | while ( $pos < $j && $address{$pos} != '>' ) |
245 | { |
e8bedb2d |
246 | $addr .= $address{$pos}; |
247 | $pos++; |
248 | } |
249 | $pos++; |
250 | break; |
251 | case ('('): /* rip off comments */ |
252 | $addr_start=$pos; |
253 | $pos++; |
c52ffd66 |
254 | while ( $pos < $j && $address{$pos} != ')' ) |
255 | { |
e8bedb2d |
256 | $addr .= $address{$pos}; |
257 | $pos++; |
258 | } |
259 | $address_start = substr($address,0,$addr_start); |
260 | $address_end = substr($address,$pos+1); |
261 | $address = $address_start . $address_end; |
262 | $j = strlen( $address ); |
263 | $pos = $addr_start; |
264 | $pos++; |
265 | break; |
266 | case (','): /* we reached a delimiter */ |
c52ffd66 |
267 | if ($addr == '') |
268 | { |
e8bedb2d |
269 | $addr = substr($address,0,$pos); |
270 | } elseif ($name == '') { |
8c3c4634 |
271 | $name = trim(substr($address,0,$addr_start)); |
e8bedb2d |
272 | } |
273 | |
274 | $at = strpos($addr, '@'); |
275 | $addr_structure = new address_structure(); |
276 | $addr_structure->personal = $name; |
277 | $addr_structure->group = $group; |
c52ffd66 |
278 | if ($at) |
279 | { |
e8bedb2d |
280 | $addr_structure->mailbox = substr($addr,0,$at); |
281 | $addr_structure->host = substr($addr,$at+1); |
c52ffd66 |
282 | } else |
283 | { |
e8bedb2d |
284 | $addr_structure->mailbox = $addr; |
285 | } |
286 | $address = trim(substr($address,$pos+1)); |
287 | $j = strlen( $address ); |
288 | $pos = 0; |
289 | $name = ''; |
290 | $addr = ''; |
291 | $addr_ar[] = $addr_structure; |
292 | break; |
293 | case (':'): /* process the group addresses */ |
294 | /* group marker */ |
295 | $group = substr($address,0,$pos); |
296 | $address = substr($address,$pos+1); |
297 | $result = $this->parseAddress($address, $ar, $addr_ar, $group); |
298 | $addr_ar = $result[0]; |
299 | $pos = $result[1]; |
300 | $address = substr($address,$pos); |
301 | $j = strlen( $address ); |
302 | $group = ''; |
303 | $pos++; |
304 | break; |
305 | case (';'): |
c52ffd66 |
306 | if ($group) |
307 | { |
e8bedb2d |
308 | $address = substr($address, 0, $pos-1); |
309 | } |
310 | $pos++; |
311 | break; |
312 | default: |
313 | $pos++; |
314 | break; |
315 | } |
316 | |
317 | } |
c52ffd66 |
318 | if ($addr == '') |
319 | { |
e8bedb2d |
320 | $addr = substr($address,0,$pos); |
c52ffd66 |
321 | } elseif ($name == '') |
322 | { |
8c3c4634 |
323 | $name = trim(substr($address,0,$addr_start)); |
e8bedb2d |
324 | } |
325 | $at = strpos($addr, '@'); |
326 | $addr_structure = new address_structure(); |
327 | $addr_structure->group = $group; |
c52ffd66 |
328 | if ($at) |
329 | { |
e8bedb2d |
330 | $addr_structure->mailbox = trim(substr($addr,0,$at)); |
331 | $addr_structure->host = trim(substr($addr,$at+1)); |
c52ffd66 |
332 | } else |
333 | { |
e8bedb2d |
334 | $addr_structure->mailbox = trim($addr); |
335 | } |
c52ffd66 |
336 | if ($group && $addr == '') /* no addresses found in group */ |
337 | { |
e8bedb2d |
338 | $name = "$group: Undisclosed recipients;"; |
339 | $addr_structure->personal = $name; |
340 | $addr_ar[] = $addr_structure; |
341 | return (array($addr_ar,$pos+1)); |
c52ffd66 |
342 | } else |
343 | { |
e8bedb2d |
344 | $addr_structure->personal = $name; |
c52ffd66 |
345 | if ($name || $addr) |
346 | { |
e8bedb2d |
347 | $addr_ar[] = $addr_structure; |
348 | } |
349 | } |
c52ffd66 |
350 | if ($ar) |
351 | { |
e8bedb2d |
352 | return ($addr_ar); |
c52ffd66 |
353 | } else |
354 | { |
e8bedb2d |
355 | return ($addr_ar[0]); |
356 | } |
8f6b86cc |
357 | } |
e8bedb2d |
358 | |
c52ffd66 |
359 | function parseContentType($value) |
360 | { |
e8bedb2d |
361 | $pos = strpos($value,';'); |
362 | $props = ''; |
c52ffd66 |
363 | if ($pos > 0) |
364 | { |
e8bedb2d |
365 | $type = trim(substr($value,0,$pos)); |
366 | $props = trim(substr($type,$pos+1)); |
c52ffd66 |
367 | } else |
368 | { |
e8bedb2d |
369 | $type = $value; |
370 | } |
371 | $content_type = new content_type($type); |
c52ffd66 |
372 | if ($props) |
373 | { |
e8bedb2d |
374 | $properties = $this->parseProperties($props); |
c52ffd66 |
375 | if (!isset($properties['charset'])) |
376 | { |
e8bedb2d |
377 | $properties['charset'] = 'us-ascii'; |
378 | } |
379 | $content_type->properties = $this->parseProperties($props); |
380 | } |
381 | $this->content_type = $content_type; |
382 | } |
383 | |
c52ffd66 |
384 | function parseProperties($value) |
385 | { |
e8bedb2d |
386 | $propArray = explode(';',$value); |
387 | $propResultArray = array(); |
c52ffd66 |
388 | foreach ($propArray as $prop) |
389 | { |
e8bedb2d |
390 | $prop = trim($prop); |
391 | $pos = strpos($prop,'='); |
c52ffd66 |
392 | if ($pos>0) |
393 | { |
e8bedb2d |
394 | $key = trim(substr($prop,0,$pos)); |
395 | $val = trim(substr($prop,$pos+1)); |
c52ffd66 |
396 | if ($val{0} == '"') |
397 | { |
e8bedb2d |
398 | $val = substr($val,1,-1); |
399 | } |
400 | $propResultArray[$key] = $val; |
401 | } |
402 | } |
403 | return $propResultArray; |
404 | } |
405 | |
c52ffd66 |
406 | function parseDisposition($value) |
407 | { |
e8bedb2d |
408 | $pos = strpos($value,';'); |
409 | $props = ''; |
c52ffd66 |
410 | if ($pos > 0) |
411 | { |
e8bedb2d |
412 | $name = trim(substr($value,0,$pos)); |
413 | $props = trim(substr($type,$pos+1)); |
c52ffd66 |
414 | } else |
415 | { |
e8bedb2d |
416 | $name = $value; |
417 | } |
418 | $props_a = $this->parseProperties($props); |
419 | $disp = new disposition($name); |
420 | $disp->properties = $props_a; |
421 | $this->disposition = $disp; |
422 | } |
423 | |
c52ffd66 |
424 | function mlist($field, $value) |
425 | { |
e8bedb2d |
426 | $res_a = array(); |
427 | $value_a = explode(',',$value); |
428 | foreach ($value_a as $val) { |
429 | $val = trim($val); |
c52ffd66 |
430 | if ($val{0} == '<') |
431 | { |
e8bedb2d |
432 | $val = substr($val,1,-1); |
433 | } |
c52ffd66 |
434 | if (substr($val,0,7) == 'mailto:') |
435 | { |
e8bedb2d |
436 | $res_a['mailto'] = substr($val,7); |
c52ffd66 |
437 | } else |
438 | { |
e8bedb2d |
439 | $res_a['href'] = $val; |
440 | } |
441 | } |
442 | $this->mlist[$field] = $res_a; |
443 | } |
444 | |
319cf0d2 |
445 | /* |
446 | * function to get the addres strings out of the header. |
447 | * Arguments: string or array of strings ! |
448 | * example1: header->getAddr_s('to'). |
449 | * example2: header->getAddr_s(array('to','cc','bcc')) |
450 | */ |
c52ffd66 |
451 | function getAddr_s($arr, $separator=', ') |
452 | { |
453 | if (is_array($arr)) |
454 | { |
319cf0d2 |
455 | $s = ''; |
c52ffd66 |
456 | foreach($arr as $arg ) |
457 | { |
319cf0d2 |
458 | $result = $this->getAddr_s($arg); |
c52ffd66 |
459 | if ($result) |
460 | { |
e8bedb2d |
461 | $s .= $separator . $result; |
319cf0d2 |
462 | } |
463 | } |
464 | if ($s) $s = substr($s,2); |
465 | return $s; |
c52ffd66 |
466 | } else |
467 | { |
319cf0d2 |
468 | $s = ''; |
469 | eval('$addr = $this->'.$arr.';') ; |
c52ffd66 |
470 | if (is_array($addr)) |
471 | { |
472 | foreach ($addr as $addr_o) |
473 | { |
474 | if (is_object($addr_o)) |
475 | { |
e8bedb2d |
476 | $s .= $addr_o->getAddress() . $separator; |
319cf0d2 |
477 | } |
478 | } |
e8bedb2d |
479 | $s = substr($s,0,-strlen($separator)); |
c52ffd66 |
480 | } else |
481 | { |
482 | if (is_object($addr)) |
483 | { |
319cf0d2 |
484 | $s .= $addr->getAddress(); |
485 | } |
486 | } |
487 | return $s; |
488 | } |
8f6b86cc |
489 | } |
319cf0d2 |
490 | |
c52ffd66 |
491 | function getAddr_a($arg, $excl_arr=array(), $arr = array()) |
492 | { |
493 | if (is_array($arg)) |
494 | { |
495 | foreach($arg as $argument ) |
496 | { |
319cf0d2 |
497 | $arr = $this->getAddr_a($argument, $excl_arr, $arr); |
498 | } |
499 | return $arr; |
c52ffd66 |
500 | } else |
501 | { |
319cf0d2 |
502 | eval('$addr = $this->'.$arg.';') ; |
c52ffd66 |
503 | if (is_array($addr)) |
504 | { |
505 | foreach ($addr as $addr_o) |
506 | { |
507 | if (is_object($addr_o)) |
508 | { |
509 | if (isset($addr_o->host) && $addr_o->host !='') |
510 | { |
319cf0d2 |
511 | $email = $addr_o->mailbox.'@'.$addr_o->host; |
c52ffd66 |
512 | } else |
513 | { |
319cf0d2 |
514 | $email = $addr_o->mailbox; |
515 | } |
516 | $email = strtolower($email); |
c52ffd66 |
517 | if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) |
518 | { |
319cf0d2 |
519 | $arr[$email] = $addr_o->personal; |
520 | } |
521 | } |
522 | } |
c52ffd66 |
523 | } else |
524 | { |
525 | if (is_object($addr)) |
526 | { |
527 | if (isset($addr->host)) |
528 | { |
319cf0d2 |
529 | $email = $addr->mailbox.'@'.$addr->host; |
c52ffd66 |
530 | } else |
531 | { |
319cf0d2 |
532 | $email = $addr->mailbox; |
533 | } |
534 | $email = strtolower($email); |
c52ffd66 |
535 | if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) |
536 | { |
319cf0d2 |
537 | $arr[$email] = $addr->personal; |
538 | } |
539 | } |
540 | } |
541 | return $arr; |
542 | } |
8f6b86cc |
543 | } |
e8bedb2d |
544 | |
c52ffd66 |
545 | function getContentType($type0, $type1) |
546 | { |
e8bedb2d |
547 | $type0 = $this->content_type->type0; |
548 | $type1 = $this->content_type->type1; |
549 | return $this->content_type->properties; |
550 | } |
8f6b86cc |
551 | } |
552 | |
c52ffd66 |
553 | class msg_header |
554 | { |
e8bedb2d |
555 | /** msg_header contains all variables available in a bodystructure **/ |
556 | /** entity like described in rfc2060 **/ |
557 | |
558 | var $type0 = '', |
559 | $type1 = '', |
560 | $parameters = array(), |
561 | $id = 0, |
562 | $description = '', |
563 | $encoding='', |
564 | $size = 0, |
565 | $md5='', |
566 | $disposition = '', |
567 | $language=''; |
568 | |
569 | /* |
570 | * returns addres_list of supplied argument |
571 | * arguments: array('to', 'from', ...) or just a string like 'to'. |
572 | * result: string: address1, addres2, .... |
573 | */ |
574 | |
c52ffd66 |
575 | function setVar($var, $value) |
576 | { |
e8bedb2d |
577 | $this->{$var} = $value; |
578 | } |
579 | |
c52ffd66 |
580 | function getParameter($par) |
581 | { |
e8bedb2d |
582 | $value = strtolower($par); |
c52ffd66 |
583 | if (isset($this->parameters[$par])) |
584 | { |
e8bedb2d |
585 | return $this->parameters[$par]; |
586 | } |
587 | return ''; |
588 | } |
589 | |
c52ffd66 |
590 | function setParameter($parameter, $value) |
591 | { |
e8bedb2d |
592 | $this->parameters[strtolower($parameter)] = $value; |
593 | } |
594 | } |
595 | |
596 | |
597 | |
c52ffd66 |
598 | class address_structure |
599 | { |
319cf0d2 |
600 | var $personal = '', $adl = '', $mailbox = '', $host = '', $group = ''; |
8f6b86cc |
601 | |
c52ffd66 |
602 | function getAddress($full=true) |
603 | { |
604 | if (is_object($this)) |
605 | { |
606 | if (isset($this->host) && $this->host !='') |
607 | { |
e8bedb2d |
608 | $email = $this->mailbox.'@'.$this->host; |
c52ffd66 |
609 | } else |
610 | { |
319cf0d2 |
611 | $email = $this->mailbox; |
e02d0fa7 |
612 | } |
c52ffd66 |
613 | if (trim($this->personal) !='') |
614 | { |
615 | if ($email) |
616 | { |
e8bedb2d |
617 | $addr = '"' . $this->personal . '" <' .$email.'>'; |
c52ffd66 |
618 | } else |
619 | { |
319cf0d2 |
620 | $addr = $this->personal; |
621 | } |
622 | $best_dpl = $this->personal; |
c52ffd66 |
623 | } else |
624 | { |
319cf0d2 |
625 | $addr = $email; |
626 | $best_dpl = $email; |
627 | } |
c52ffd66 |
628 | if ($full) |
629 | { |
319cf0d2 |
630 | return $addr; |
c52ffd66 |
631 | } else |
632 | { |
319cf0d2 |
633 | return $best_dpl; |
634 | } |
635 | } else return ''; |
636 | } |
8f6b86cc |
637 | } |
638 | |
c52ffd66 |
639 | class message |
640 | { |
8f6b86cc |
641 | /** message is the object that contains messages. It is a recursive |
642 | object in that through the $entities variable, it can contain |
643 | more objects of type message. See documentation in mime.txt for |
644 | a better description of how this works. |
645 | **/ |
e8bedb2d |
646 | var $rfc822_header = '', |
647 | $mime_header = '', |
648 | $flags = '', |
649 | $type0='', |
650 | $type1='', |
651 | $entities = array(), |
652 | $parent_ent, $entity, |
319cf0d2 |
653 | $parent = '', $decoded_body='', |
654 | $is_seen = 0, $is_answered = 0, $is_deleted = 0, $is_flagged = 0, |
e8bedb2d |
655 | $is_mdnsent = 0, |
c52ffd66 |
656 | $body_part = '', |
657 | $offset = 0, /* for fetching body parts out of raw messages */ |
658 | $length = 0; /* for fetching body parts out of raw messages */ |
8f6b86cc |
659 | |
c52ffd66 |
660 | function setEnt($ent) |
661 | { |
8f6b86cc |
662 | $this->entity_id= $ent; |
663 | } |
319cf0d2 |
664 | |
c52ffd66 |
665 | function addEntity ($msg) |
666 | { |
8f6b86cc |
667 | $msg->parent = &$this; |
668 | $this->entities[] = $msg; |
669 | } |
670 | |
812843b7 |
671 | function getFilename() |
672 | { |
673 | $filename = ''; |
674 | if (is_object($this->header->disposition)) |
675 | { |
676 | $filename = $this->header->disposition->getproperty('filename'); |
677 | if (!$filename) |
678 | { |
679 | $filename = $this->header->disposition->getproperty('name'); |
680 | } |
681 | } |
682 | if (!$filename) |
683 | { |
684 | $filename = 'untitled-'.$this->entity_id; |
685 | } |
686 | return $filename; |
687 | } |
688 | |
689 | |
c52ffd66 |
690 | function addRFC822Header($read) |
691 | { |
692 | $header = new rfc822_header(); |
693 | $this->rfc822_header = $header->parseHeader($read); |
8f6b86cc |
694 | } |
695 | |
c52ffd66 |
696 | function getEntity($ent) |
697 | { |
8f6b86cc |
698 | $cur_ent = $this->entity_id; |
319cf0d2 |
699 | $msg = $this; |
c52ffd66 |
700 | if ($cur_ent == '' || $cur_ent == '0') |
701 | { |
319cf0d2 |
702 | $cur_ent_a = array(); |
c52ffd66 |
703 | } else |
704 | { |
319cf0d2 |
705 | $cur_ent_a = explode('.',$this->entity_id); |
706 | } |
707 | $ent_a = explode('.',$ent); |
708 | |
709 | $cnt = count($ent_a); |
8f6b86cc |
710 | |
c52ffd66 |
711 | for ($i=0;$i<$cnt -1;$i++) |
712 | { |
713 | if (isset($cur_ent_a[$i]) && $cur_ent_a[$i] != $ent_a[$i]) |
714 | { |
319cf0d2 |
715 | $msg = $msg->parent; |
716 | $cur_ent_a = explode('.',$msg->entity_id); |
717 | $i--; |
c52ffd66 |
718 | } else if (!isset($cur_ent_a[$i])) |
719 | { |
720 | if (isset($msg->entities[($ent_a[$i]-1)])) |
721 | { |
319cf0d2 |
722 | $msg = $msg->entities[($ent_a[$i]-1)]; |
723 | } else { |
724 | $msg = $msg->entities[0]; |
725 | } |
726 | } |
c52ffd66 |
727 | if ($msg->type0 == 'message' && $msg->type1 == 'rfc822') |
728 | { |
319cf0d2 |
729 | /*this is a header for a message/rfc822 entity */ |
730 | $msg = $msg->entities[0]; |
731 | } |
732 | } |
08c18186 |
733 | |
c52ffd66 |
734 | if ($msg->type0 == 'message' && $msg->type1 == 'rfc822') |
735 | { |
319cf0d2 |
736 | /*this is a header for a message/rfc822 entity */ |
737 | $msg = $msg->entities[0]; |
738 | } |
8f6b86cc |
739 | |
a2aea42e |
740 | if (isset($msg->entities[($ent_a[$cnt-1])-1])) |
c52ffd66 |
741 | { |
a2aea42e |
742 | if (is_object($msg->entities[($ent_a[$cnt-1])-1])) |
743 | { |
744 | $msg = $msg->entities[($ent_a[$cnt-1]-1)]; |
745 | } |
746 | } |
08c18186 |
747 | |
319cf0d2 |
748 | return $msg; |
8f6b86cc |
749 | } |
e8bedb2d |
750 | |
c52ffd66 |
751 | function setBody($s) |
752 | { |
e8bedb2d |
753 | $this->body_part = $s; |
754 | } |
755 | |
c52ffd66 |
756 | function clean_up() |
757 | { |
e8bedb2d |
758 | $msg = $this; |
759 | $msg->body_part = ''; |
760 | $i=0; |
c52ffd66 |
761 | while ( isset($msg->entities[$i])) |
762 | { |
e8bedb2d |
763 | $msg->entities[$i]->clean_up(); |
764 | $i++; |
765 | } |
766 | } |
319cf0d2 |
767 | |
c52ffd66 |
768 | function getMailbox() |
769 | { |
770 | $msg = $this; |
771 | while (is_object($msg->parent)) |
772 | { |
319cf0d2 |
773 | $msg = $msg->parent; |
c52ffd66 |
774 | } |
775 | return $msg->mailbox; |
319cf0d2 |
776 | } |
777 | |
c52ffd66 |
778 | function calcEntity($msg) |
779 | { |
780 | if ($this->type0 == 'message' && $this->type1 == 'rfc822') |
781 | { |
782 | $msg->entity_id = $this->entity_id .'.0'; /* header of message/rfc822 */ |
783 | } else if (isset($this->entity_id) && $this->entity_id !='') |
784 | { |
785 | $ent_no = count($this->entities)+1; |
786 | $par_ent = substr($this->entity_id,-2); |
787 | if ($par_ent{0} == '.') |
788 | { |
789 | $par_ent = $par_ent{1}; |
790 | } |
791 | if ($par_ent == '0') |
792 | { |
793 | $ent_no = count($this->entities)+1; |
794 | if ($ent_no > 0) |
795 | { |
796 | $ent = substr($this->entity_id,0,strrpos($this->entity_id,'.')); |
797 | if ($ent) |
798 | { |
799 | $ent = $ent . ".$ent_no"; |
800 | } else |
801 | { |
802 | $ent = $ent_no; |
803 | } |
804 | $msg->entity_id = $ent; |
805 | } else |
806 | { |
807 | $msg->entity_id = $ent_no; |
808 | } |
809 | } else |
810 | { |
811 | $ent = $this->entity_id . ".$ent_no"; |
812 | $msg->entity_id = $ent; |
813 | } |
814 | } else |
815 | { |
816 | $msg->entity_id = '0'; |
817 | } |
818 | return $msg->entity_id; |
819 | } |
820 | |
821 | |
8f6b86cc |
822 | /* |
823 | * Bodystructure parser, a recursive function for generating the |
824 | * entity-tree with all the mime-parts. |
825 | * |
826 | * It follows RFC2060 and stores all the described fields in the |
827 | * message object. |
828 | * |
829 | * Question/Bugs: |
830 | * |
831 | * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net. |
832 | * |
833 | */ |
c52ffd66 |
834 | function parseStructure($read, $i=0) |
835 | { |
319cf0d2 |
836 | $arg_no = 0; |
837 | $arg_a = array(); |
838 | $cnt = strlen($read); |
c52ffd66 |
839 | while ($i < $cnt) |
840 | { |
319cf0d2 |
841 | $char = strtoupper($read{$i}); |
c52ffd66 |
842 | switch ($char) |
843 | { |
319cf0d2 |
844 | case '(': |
c52ffd66 |
845 | if ($arg_no == 0 ) |
846 | { |
847 | if (!isset($msg)) |
848 | { |
319cf0d2 |
849 | $msg = new message(); |
850 | $hdr = new msg_header(); |
851 | $hdr->type0 = 'text'; |
852 | $hdr->type1 = 'plain'; |
853 | $hdr->encoding = 'us-ascii'; |
c52ffd66 |
854 | $msg->entity_id = $this->calcEntity($msg); |
855 | } else |
856 | { |
319cf0d2 |
857 | $msg->header->type0 = 'multipart'; |
858 | $msg->type0 = 'multipart'; |
c52ffd66 |
859 | while ($read{$i} == '(') |
860 | { |
861 | $res = $msg->parseStructure($read,$i); |
862 | $i = $res[1]; |
863 | $msg->addEntity($res[0]); |
319cf0d2 |
864 | } |
865 | } |
c52ffd66 |
866 | } else |
867 | { |
e8bedb2d |
868 | switch ($arg_no) |
869 | { |
870 | case 1: |
319cf0d2 |
871 | /* multipart properties */ |
872 | $i++; |
c52ffd66 |
873 | $res = $this->parseProperties($read,$i); |
924b0cac |
874 | |
c52ffd66 |
875 | $arg_a[] = $res[0]; |
876 | $i = $res[1]; |
319cf0d2 |
877 | $arg_no++; |
878 | break; |
e8bedb2d |
879 | case 2: |
c52ffd66 |
880 | if (isset($msg->type0) && $msg->type0 == 'multipart') |
881 | { |
319cf0d2 |
882 | $i++; |
c52ffd66 |
883 | $res = $msg->parseDisposition($read,$i); |
884 | $arg_a[] = $res[0]; |
885 | $i = $res[1]; |
886 | } else /* properties */ |
887 | { |
888 | $res = $msg->parseProperties($read,$i); |
889 | $arg_a[] = $res[0]; |
890 | $i = $res[1]; |
319cf0d2 |
891 | } |
892 | $arg_no++; |
893 | break; |
e8bedb2d |
894 | case 3: |
c52ffd66 |
895 | if (isset($msg->type0) && $msg->type0 == 'multipart') |
896 | { |
08c18186 |
897 | $i++; |
c52ffd66 |
898 | $res= $msg->parseLanguage($read,$i); |
899 | $arg_a[] = $res[0]; |
900 | $i = $res[1]; |
08c18186 |
901 | } |
e8bedb2d |
902 | case 7: |
c52ffd66 |
903 | if ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822') |
904 | { |
319cf0d2 |
905 | $msg->header->type0 = $arg_a[0]; |
906 | $msg->type0 = $arg_a[0]; |
319cf0d2 |
907 | $msg->header->type1 = $arg_a[1]; |
908 | $msg->type1 = $arg_a[1]; |
e8bedb2d |
909 | $rfc822_hdr = new rfc822_header(); |
c52ffd66 |
910 | $res = $msg->parseEnvelope($read,$i,$rfc822_hdr); |
911 | $i = $res[1]; |
912 | $msg->rfc822_header = $res[0]; |
319cf0d2 |
913 | $i++; |
c52ffd66 |
914 | while ($i < $cnt && $read{$i} != '(') |
915 | { |
319cf0d2 |
916 | $i++; |
917 | } |
c52ffd66 |
918 | $res = $msg->parseStructure($read,$i); |
919 | $i = $res[1]; |
920 | $msg->addEntity($res[0]); |
319cf0d2 |
921 | } |
922 | break; |
e8bedb2d |
923 | case 8: |
319cf0d2 |
924 | $i++; |
c52ffd66 |
925 | $res = $msg->parseDisposition($read,$i); |
926 | $arg_a[] = $res[0]; |
927 | $i = $res[1]; |
319cf0d2 |
928 | $arg_no++; |
929 | break; |
e8bedb2d |
930 | case 9: |
319cf0d2 |
931 | if ($arg_a[0] == 'text' || |
c52ffd66 |
932 | ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) |
933 | { |
319cf0d2 |
934 | $i++; |
c52ffd66 |
935 | $res = $msg->parseDisposition($read,$i); |
936 | $arg_a[] = $res[0]; |
937 | $i = $res[1]; |
938 | } else |
939 | { |
31e0cfba |
940 | $i++; |
c52ffd66 |
941 | $res = $msg->parseLanguage($read,$i); |
942 | $arg_a[] = $res[0]; |
943 | $i = $res[1]; |
319cf0d2 |
944 | } |
945 | $arg_no++; |
946 | break; |
e8bedb2d |
947 | case 10: |
319cf0d2 |
948 | if ($arg_a[0] == 'text' || |
c52ffd66 |
949 | ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) |
950 | { |
31e0cfba |
951 | $i++; |
c52ffd66 |
952 | $res = $msg->parseLanguage($read,$i); |
953 | $arg_a[] = $res[0]; |
954 | $i = $res[1]; |
955 | } else |
956 | { |
957 | $i = $msg->parseParenthesis($read,$i); |
319cf0d2 |
958 | $arg_a[] = ''; /* not yet desribed in rfc2060 */ |
959 | } |
960 | $arg_no++; |
961 | break; |
e8bedb2d |
962 | default: |
319cf0d2 |
963 | /* unknown argument, skip this part */ |
c52ffd66 |
964 | $i = $msg->parseParenthesis($read,$i); |
319cf0d2 |
965 | $arg_a[] = ''; |
966 | $arg_no++; |
967 | break; |
968 | } /* switch */ |
969 | } |
970 | break; |
971 | case '"': |
972 | /* inside an entity -> start processing */ |
973 | $debug = substr($read,$i,20); |
c52ffd66 |
974 | $res = $msg->parseQuote($read,$i); |
975 | $arg_s = $res[0]; |
976 | $i = $res[1]; |
319cf0d2 |
977 | $arg_no++; |
978 | if ($arg_no < 3) $arg_s = strtolower($arg_s); /* type0 and type1 */ |
979 | $arg_a[] = $arg_s; |
980 | break; |
e8bedb2d |
981 | case 'n': |
319cf0d2 |
982 | case 'N': |
983 | /* probably NIL argument */ |
08c18186 |
984 | if (strtoupper(substr($read,$i,4)) == 'NIL ' || |
c52ffd66 |
985 | strtoupper(substr($read,$i,4)) == 'NIL)') |
986 | { |
319cf0d2 |
987 | $arg_a[] = ''; |
988 | $arg_no++; |
989 | $i = $i+2; |
990 | } |
991 | break; |
992 | case '{': |
993 | /* process the literal value */ |
c52ffd66 |
994 | $res = $msg->parseLiteral($read,$i); |
995 | $arg_s = $res[0]; |
996 | $i = $res[1]; |
319cf0d2 |
997 | $arg_no++; |
998 | break; |
999 | case (is_numeric($read{$i}) ): |
1000 | /* process integers */ |
1001 | if ($read{$i} == ' ') break; |
1002 | $arg_s = $read{$i};; |
1003 | $i++; |
c52ffd66 |
1004 | while (preg_match('/^[0-9]{1}$/',$read{$i})) |
1005 | { |
319cf0d2 |
1006 | $arg_s .= $read{$i}; |
1007 | $i++; |
1008 | } |
1009 | $arg_no++; |
1010 | $arg_a[] = $arg_s; |
1011 | break; |
1012 | case ')': |
c52ffd66 |
1013 | if (isset($msg->type0) && $msg->type0 == 'multipart') |
1014 | { |
319cf0d2 |
1015 | $multipart = true; |
c52ffd66 |
1016 | } else |
1017 | { |
319cf0d2 |
1018 | $multipart = false; |
1019 | } |
c52ffd66 |
1020 | if (!$multipart) |
1021 | { |
319cf0d2 |
1022 | if ($arg_a[0] == 'text' || |
c52ffd66 |
1023 | ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) |
1024 | { |
319cf0d2 |
1025 | $shifted_args = true; |
c52ffd66 |
1026 | } else |
1027 | { |
319cf0d2 |
1028 | $shifted_args = false; |
1029 | } |
1030 | $hdr->type0 = $arg_a[0]; |
1031 | $hdr->type1 = $arg_a[1]; |
8f6b86cc |
1032 | |
319cf0d2 |
1033 | $msg->type0 = $arg_a[0]; |
1034 | $msg->type1 = $arg_a[1]; |
8f6b86cc |
1035 | |
319cf0d2 |
1036 | $arr = $arg_a[2]; |
c52ffd66 |
1037 | if (is_array($arr)) |
1038 | { |
e8bedb2d |
1039 | $hdr->parameters = $arg_a[2]; |
319cf0d2 |
1040 | } |
1041 | $hdr->id = str_replace( '<', '', str_replace( '>', '', $arg_a[3] ) ); |
1042 | $hdr->description = $arg_a[4]; |
1043 | $hdr->encoding = strtolower($arg_a[5]); |
1044 | $hdr->entity_id = $msg->entity_id; |
1045 | $hdr->size = $arg_a[6]; |
c52ffd66 |
1046 | if ($shifted_args) |
1047 | { |
319cf0d2 |
1048 | $hdr->lines = $arg_a[7]; |
c52ffd66 |
1049 | if (isset($arg_a[8])) |
1050 | { |
319cf0d2 |
1051 | $hdr->md5 = $arg_a[8]; |
1052 | } |
c52ffd66 |
1053 | if (isset($arg_a[9])) |
1054 | { |
319cf0d2 |
1055 | $hdr->disposition = $arg_a[9]; |
1056 | } |
c52ffd66 |
1057 | if (isset($arg_a[10])) |
1058 | { |
319cf0d2 |
1059 | $hdr->language = $arg_a[10]; |
1060 | } |
c52ffd66 |
1061 | } else |
1062 | { |
1063 | if (isset($arg_a[7])) |
1064 | { |
319cf0d2 |
1065 | $hdr->md5 = $arg_a[7]; |
1066 | } |
c52ffd66 |
1067 | if (isset($arg_a[8])) |
1068 | { |
319cf0d2 |
1069 | $hdr->disposition = $arg_a[8]; |
1070 | } |
c52ffd66 |
1071 | if (isset($arg_a[9])) |
1072 | { |
319cf0d2 |
1073 | $hdr->language = $arg_a[9]; |
1074 | } |
1075 | } |
1076 | $msg->header = $hdr; |
1077 | $arg_no = 0; |
1078 | $i++; |
c52ffd66 |
1079 | if (substr($msg->entity_id,-2) == '.0' && $msg->type0 !='multipart') |
1080 | { |
319cf0d2 |
1081 | $msg->entity_id++; |
1082 | } |
c52ffd66 |
1083 | return (array($msg, $i)); |
1084 | } else |
1085 | { |
1086 | $hdr->type0 = 'multipart'; |
1087 | $hdr->type1 = $arg_a[0]; |
1088 | $msg->type0 = 'multipart'; |
1089 | $msg->type1 = $arg_a[0]; |
1090 | if (is_array($arg_a[1])) |
1091 | { |
1092 | $hdr->parameters = $arg_a[1]; |
1093 | } |
1094 | if (isset($arg_a[2])) |
1095 | { |
1096 | $hdr->disposition = $arg_a[2]; |
1097 | } |
1098 | if (isset($arg_a[3])) |
1099 | { |
1100 | $hdr->language = $arg_a[3]; |
1101 | } |
1102 | $msg->header = $hdr; |
1103 | return (array($msg, $i)); |
e8bedb2d |
1104 | } |
319cf0d2 |
1105 | default: |
1106 | break; |
1107 | } /* switch */ |
1108 | $i++; |
1109 | } /* while */ |
1110 | } /* parsestructure */ |
1111 | |
c52ffd66 |
1112 | function parseProperties($read, $i) |
1113 | { |
319cf0d2 |
1114 | $properties = array(); |
1115 | $arg_s = ''; |
1116 | $prop_name = ''; |
c52ffd66 |
1117 | while ($read{$i} != ')') |
1118 | { |
1119 | if ($read{$i} == '"') |
1120 | { |
1121 | $res = $this->parseQuote($read,$i); |
1122 | $arg_s = $res[0]; |
1123 | $i = $res[1]; |
1124 | } else if ($read{$i} == '{') |
1125 | { |
1126 | $res = $this->parseLiteral($read,$i); |
1127 | $arg_s = $res[0]; |
1128 | $i = $res[1]; |
319cf0d2 |
1129 | } |
c52ffd66 |
1130 | if ($prop_name == '' && $arg_s) |
1131 | { |
1132 | $prop_name = strtolower($arg_s); |
319cf0d2 |
1133 | $properties[$prop_name] = ''; |
1134 | $arg_s = ''; |
c52ffd66 |
1135 | } elseif ($prop_name != '' && $arg_s != '') |
1136 | { |
319cf0d2 |
1137 | $properties[$prop_name] = $arg_s; |
1138 | $prop_name = ''; |
1139 | $arg_s = ''; |
1140 | } |
1141 | $i++; |
1142 | } |
c52ffd66 |
1143 | return (array($properties, $i)); |
8f6b86cc |
1144 | } |
1145 | |
c52ffd66 |
1146 | function parseEnvelope($read, $i, $hdr) |
1147 | { |
8f6b86cc |
1148 | $arg_no = 0; |
319cf0d2 |
1149 | $arg_a = array(); |
1150 | $cnt = strlen($read); |
c52ffd66 |
1151 | while ($i< $cnt && $read{$i} != ')') |
1152 | { |
319cf0d2 |
1153 | $i++; |
1154 | $char = strtoupper($read{$i}); |
e8bedb2d |
1155 | switch ($char) |
1156 | { |
1157 | case '"': |
c52ffd66 |
1158 | $res = $this->parseQuote($read,$i); |
1159 | $arg_a[] = $res[0]; |
1160 | $i = $res[1]; |
319cf0d2 |
1161 | $arg_no++; |
1162 | break; |
e8bedb2d |
1163 | case '{': |
c52ffd66 |
1164 | $res = $this->parseLiteral($read,$i); |
1165 | $arg_a[] = $res[0]; |
1166 | $i = $res[1]; |
319cf0d2 |
1167 | $arg_no++; |
1168 | break; |
e8bedb2d |
1169 | case 'N': |
319cf0d2 |
1170 | /* probably NIL argument */ |
08c18186 |
1171 | if (strtoupper(substr($read,$i,3)) == 'NIL') { |
319cf0d2 |
1172 | $arg_a[] = ''; |
1173 | $arg_no++; |
1174 | $i = $i+2; |
1175 | } |
1176 | break; |
e8bedb2d |
1177 | case '(': |
319cf0d2 |
1178 | /* Address structure |
1179 | * With group support. |
1180 | * Note: Group support is useless on SMTP connections |
1181 | * because the protocol doesn't support it |
1182 | */ |
1183 | $addr_a = array(); |
1184 | $group = ''; |
1185 | $a=0; |
c52ffd66 |
1186 | while ($i < $cnt && $read{$i} != ')') |
1187 | { |
1188 | if ($read{$i} == '(') |
1189 | { |
1190 | $res = $this->parseAddress($read,$i); |
1191 | $addr = $res[0]; |
1192 | $i = $res[1]; |
1193 | if ($addr->host == '' && $addr->mailbox != '') |
1194 | { |
319cf0d2 |
1195 | /* start of group */ |
1196 | $group = $addr->mailbox; |
1197 | $group_addr = $addr; |
1198 | $j = $a; |
c52ffd66 |
1199 | } elseif ($group && $addr->host == '' && $addr->mailbox == '') |
1200 | { |
319cf0d2 |
1201 | /* end group */ |
c52ffd66 |
1202 | if ($a == $j+1) /* no group members */ |
1203 | { |
319cf0d2 |
1204 | $group_addr->group = $group; |
1205 | $group_addr->mailbox = ''; |
1206 | $group_addr->personal = "$group: Undisclosed recipients;"; |
1207 | $addr_a[] = $group_addr; |
1208 | $group =''; |
1209 | } |
c52ffd66 |
1210 | } else |
1211 | { |
319cf0d2 |
1212 | $addr->group = $group; |
1213 | $addr_a[] = $addr; |
1214 | } |
1215 | $a++; |
1216 | } |
1217 | $i++; |
1218 | } |
1219 | $arg_a[] = $addr_a; |
1220 | break; |
e8bedb2d |
1221 | default: |
319cf0d2 |
1222 | break; |
1223 | } |
1224 | $i++; |
1225 | } |
c52ffd66 |
1226 | if (count($arg_a) > 9) |
1227 | { |
319cf0d2 |
1228 | /* argument 1: date */ |
8f6b86cc |
1229 | $d = strtr($arg_a[0], array(' ' => ' ')); |
1230 | $d = explode(' ', $d); |
1231 | $hdr->date = getTimeStamp($d); |
319cf0d2 |
1232 | /* argument 2: subject */ |
c52ffd66 |
1233 | if (!trim($arg_a[1])) |
1234 | { |
319cf0d2 |
1235 | $arg_a[1]= _("(no subject)"); |
1236 | } |
1237 | $hdr->subject = $arg_a[1]; |
1238 | /* argument 3: from */ |
1239 | $hdr->from = $arg_a[2][0]; |
1240 | /* argument 4: sender */ |
1241 | $hdr->sender = $arg_a[3][0]; |
1242 | /* argument 5: reply-to */ |
1243 | $hdr->replyto = $arg_a[4][0]; |
1244 | /* argument 6: to */ |
1245 | $hdr->to = $arg_a[5]; |
1246 | /* argument 7: cc */ |
1247 | $hdr->cc = $arg_a[6]; |
1248 | /* argument 8: bcc */ |
1249 | $hdr->bcc = $arg_a[7]; |
1250 | /* argument 9: in-reply-to */ |
1251 | $hdr->inreplyto = $arg_a[8]; |
1252 | /* argument 10: message-id */ |
1253 | $hdr->message_id = $arg_a[9]; |
08c18186 |
1254 | } |
c52ffd66 |
1255 | return (array($hdr,$i)); |
8f6b86cc |
1256 | } |
319cf0d2 |
1257 | |
c52ffd66 |
1258 | function parseLiteral($read, $i) |
1259 | { |
319cf0d2 |
1260 | $lit_cnt = ''; |
1261 | $i++; |
c52ffd66 |
1262 | while ($read{$i} != '}') |
1263 | { |
319cf0d2 |
1264 | $lit_cnt .= $read{$i}; |
1265 | $i++; |
1266 | } |
1267 | $lit_cnt +=2; /* add the { and } characters */ |
1268 | $s = ''; |
c52ffd66 |
1269 | for ($j = 0; $j < $lit_cnt; $j++) |
1270 | { |
319cf0d2 |
1271 | $i++; |
1272 | $s .= $read{$i}; |
1273 | } |
c52ffd66 |
1274 | return (array($s, $i)); |
8f6b86cc |
1275 | } |
319cf0d2 |
1276 | |
c52ffd66 |
1277 | function parseQuote($read, $i) |
1278 | { |
319cf0d2 |
1279 | $i++; |
1280 | $s = ''; |
c52ffd66 |
1281 | while ($read{$i} != '"') |
1282 | { |
1283 | if ($read{$i} == '\\') |
1284 | { |
319cf0d2 |
1285 | $i++; |
1286 | } |
1287 | $s .= $read{$i}; |
1288 | $i++; |
1289 | } |
c52ffd66 |
1290 | return (array($s, $i)); |
8f6b86cc |
1291 | } |
319cf0d2 |
1292 | |
c52ffd66 |
1293 | function parseAddress($read, $i) |
1294 | { |
319cf0d2 |
1295 | $arg_a = array(); |
c52ffd66 |
1296 | while ($read{$i} != ')' ) |
1297 | { |
319cf0d2 |
1298 | $char = strtoupper($read{$i}); |
e8bedb2d |
1299 | switch ($char) |
1300 | { |
1301 | case '"': |
c52ffd66 |
1302 | $res = $this->parseQuote($read,$i); |
1303 | $arg_a[] = $res[0]; |
1304 | $i = $res[1]; |
319cf0d2 |
1305 | break; |
e8bedb2d |
1306 | case '{': |
c52ffd66 |
1307 | $res = $this->parseLiteral($read,$i); |
1308 | $arg_a[] = $res[0]; |
1309 | $i = $res[1]; |
319cf0d2 |
1310 | break; |
e8bedb2d |
1311 | case 'n': |
1312 | case 'N': |
1313 | if (strtoupper(substr($read,$i,3)) == 'NIL') { |
319cf0d2 |
1314 | $arg_a[] = ''; |
1315 | $i = $i+2; |
1316 | } |
08c18186 |
1317 | break; |
e8bedb2d |
1318 | default: |
319cf0d2 |
1319 | break; |
1320 | } |
1321 | $i++; |
1322 | } |
c52ffd66 |
1323 | if (count($arg_a) == 4) |
1324 | { |
319cf0d2 |
1325 | $adr = new address_structure(); |
1326 | $adr->personal = $arg_a[0]; |
1327 | $adr->adl = $arg_a[1]; |
1328 | $adr->mailbox = $arg_a[2]; |
1329 | $adr->host = $arg_a[3]; |
c52ffd66 |
1330 | } else |
1331 | { |
08c18186 |
1332 | $adr = ''; |
1333 | } |
c52ffd66 |
1334 | return (array($adr,$i)); |
8f6b86cc |
1335 | } |
319cf0d2 |
1336 | |
c52ffd66 |
1337 | function parseDisposition($read,$i) |
1338 | { |
8f6b86cc |
1339 | $arg_a = array(); |
c52ffd66 |
1340 | while ($read{$i} != ')') |
1341 | { |
e8bedb2d |
1342 | switch ($read{$i}) |
1343 | { |
1344 | case '"': |
c52ffd66 |
1345 | $res = $this->parseQuote($read,$i); |
1346 | $arg_a[] = $res[0]; |
1347 | $i = $res[1]; |
319cf0d2 |
1348 | break; |
e8bedb2d |
1349 | case '{': |
c52ffd66 |
1350 | $res = $this->parseLiteral($read,$i); |
1351 | $arg_a[] = $res[0]; |
1352 | $i = $res[1]; |
319cf0d2 |
1353 | break; |
e8bedb2d |
1354 | case '(': |
c52ffd66 |
1355 | $res = $this->parseProperties($read,$i); |
1356 | $arg_a[] = $res[0]; |
1357 | $i = $res[1]; |
319cf0d2 |
1358 | break; |
e8bedb2d |
1359 | default: |
319cf0d2 |
1360 | break; |
1361 | } |
1362 | $i++; |
e02d0fa7 |
1363 | } |
c52ffd66 |
1364 | if (isset($arg_a[0])) |
1365 | { |
319cf0d2 |
1366 | $disp = new disposition($arg_a[0]); |
c52ffd66 |
1367 | if (isset($arg_a[1])) |
1368 | { |
319cf0d2 |
1369 | $disp->properties = $arg_a[1]; |
1370 | } |
1371 | } |
c52ffd66 |
1372 | if (is_object($disp)) |
1373 | { |
1374 | return (array($disp, $i)); |
1375 | } else |
1376 | { |
1377 | return (array('',$i)); |
08c18186 |
1378 | } |
8f6b86cc |
1379 | } |
319cf0d2 |
1380 | |
c52ffd66 |
1381 | function parseLanguage($read,$i) |
1382 | { |
08c18186 |
1383 | /* no idea how to process this one without examples */ |
31e0cfba |
1384 | $arg_a = array(); |
c52ffd66 |
1385 | while ($read{$i} != ')') |
1386 | { |
e8bedb2d |
1387 | switch ($read{$i}) |
1388 | { |
1389 | case '"': |
c52ffd66 |
1390 | $res = $this->parseQuote($read,$i); |
1391 | $arg_a[] = $res[0]; |
1392 | $i = $res[1]; |
08c18186 |
1393 | break; |
e8bedb2d |
1394 | case '{': |
c52ffd66 |
1395 | $res = $this->parseLiteral($read,$i); |
1396 | $arg_a[] = $res[0]; |
1397 | $i = $res[1]; |
08c18186 |
1398 | break; |
e8bedb2d |
1399 | case '(': |
c52ffd66 |
1400 | $res = $this->parseProperties($read,$i); |
1401 | $arg_a[] = $res[0]; |
1402 | $i = $res[1]; |
08c18186 |
1403 | break; |
e8bedb2d |
1404 | default: |
08c18186 |
1405 | break; |
1406 | } |
1407 | $i++; |
1408 | } |
c52ffd66 |
1409 | if (isset($arg_a[0])) |
1410 | { |
31e0cfba |
1411 | $lang = new language($arg_a[0]); |
c52ffd66 |
1412 | if (isset($arg_a[1])) |
1413 | { |
31e0cfba |
1414 | $lang->properties = $arg_a[1]; |
1415 | } |
1416 | } |
c52ffd66 |
1417 | if (is_object($lang)) |
1418 | { |
1419 | return (array($lang, $i)); |
1420 | } else |
1421 | { |
1422 | return (array('', $i)); |
31e0cfba |
1423 | } |
8f6b86cc |
1424 | } |
319cf0d2 |
1425 | |
c52ffd66 |
1426 | function parseParenthesis($read,$i) |
1427 | { |
1428 | while ($read{$i} != ')') |
1429 | { |
e8bedb2d |
1430 | switch ($read{$i}) |
1431 | { |
1432 | case '"': |
c52ffd66 |
1433 | $res = $this->parseQuote($read,$i); |
1434 | $i = $res[1]; |
319cf0d2 |
1435 | break; |
e8bedb2d |
1436 | case '{': |
c52ffd66 |
1437 | $res = $this->parseLiteral($read,$i); |
1438 | $i = $res[1]; |
319cf0d2 |
1439 | break; |
e8bedb2d |
1440 | case '(': |
c52ffd66 |
1441 | $res = $this->parseParenthesis($read,$i); |
1442 | $i = $res[1]; |
319cf0d2 |
1443 | break; |
e8bedb2d |
1444 | default: |
319cf0d2 |
1445 | break; |
1446 | } |
1447 | $i++; |
1448 | } |
c52ffd66 |
1449 | return $i; |
1450 | } |
1451 | |
1452 | /* function to fill the message structure in case the bodystructure |
1453 | isn't available NOT FINISHED YET |
1454 | */ |
1455 | function parseMessage($read, $type0, $type1) |
1456 | { |
1457 | switch ($type0) |
1458 | { |
1459 | case 'message': |
1460 | $rfc822_header = true; |
1461 | $mime_header = false; |
1462 | break; |
1463 | case 'multipart': |
1464 | $mime_header = true; |
1465 | $rfc822_header = false; |
1466 | break; |
1467 | default: |
1468 | return $read; |
1469 | } |
1470 | |
1471 | for ($i=1; $i < $count; $i++) |
1472 | { |
1473 | $line = trim($body[$i]); |
1474 | if ( ( $mime_header || $rfc822_header) && |
1475 | (preg_match("/^.*boundary=\"?(.+(?=\")|.+).*/i",$line,$reg)) ) |
1476 | { |
1477 | $bnd = $reg[1]; |
1478 | $bndreg = $bnd; |
1479 | $bndreg = str_replace("\\","\\\\",$bndreg); |
1480 | $bndreg = str_replace("?","\\?",$bndreg); |
1481 | $bndreg = str_replace("+","\\+",$bndreg); |
1482 | $bndreg = str_replace(".","\\.",$bndreg); |
1483 | $bndreg = str_replace("/","\\/",$bndreg); |
1484 | $bndreg = str_replace("-","\\-",$bndreg); |
1485 | $bndreg = str_replace("(","\\(",$bndreg); |
1486 | $bndreg = str_replace(")","\\)",$bndreg); |
1487 | } elseif ( $rfc822_header && $line == '' ) |
1488 | { |
1489 | $rfc822_header = false; |
1490 | if ($msg->type0 == 'multipart') |
1491 | { |
1492 | $mime_header = true; |
1493 | } |
1494 | } |
1495 | |
1496 | if (($line{0} == '-' || $rfc822_header) && isset($boundaries[0])) |
1497 | { |
1498 | $cnt=count($boundaries)-1; |
1499 | $bnd = $boundaries[$cnt]['bnd']; |
1500 | $bndreg = $boundaries[$cnt]['bndreg']; |
1501 | |
1502 | $regstr = '/^--'."($bndreg)".".*".'/'; |
1503 | if (preg_match($regstr,$line,$reg) ) |
1504 | { |
1505 | $bndlen = strlen($reg[1]); |
1506 | $bndend = false; |
1507 | if (strlen($line) > ($bndlen + 3)) |
1508 | { |
1509 | if ($line{$bndlen+2} == '-' && $line{$bndlen+3} == '-') |
1510 | $bndend = true; |
1511 | } |
1512 | if ($bndend) |
1513 | { |
1514 | /* calc offset and return $msg */ |
1515 | // $entStr = CalcEntity("$entStr",-1); |
1516 | array_pop($boundaries); |
1517 | $mime_header = true; |
1518 | $bnd_end = true; |
1519 | } else |
1520 | { |
1521 | $mime_header = true; |
1522 | $bnd_end = false; |
1523 | // $entStr = CalcEntity("$entStr",0); |
1524 | $content_indx++; |
1525 | } |
1526 | } else |
1527 | { |
1528 | if ($header) |
1529 | { |
1530 | } |
1531 | } |
1532 | } |
1533 | } |
319cf0d2 |
1534 | } |
1535 | |
c52ffd66 |
1536 | function findDisplayEntity ($entity = array(), $alt_order = array('text/plain','text/html')) |
1537 | { |
8f288482 |
1538 | $found = false; |
1539 | $type = $this->type0.'/'.$this->type1; |
1540 | if ( $type == 'multipart/alternative') |
1541 | { |
1542 | $msg = $this->findAlternativeEntity($alt_order); |
1543 | if (count($msg->entities) == 0) |
1544 | { |
1545 | $entity[] = $msg->entity_id; |
1546 | } else |
1547 | { |
1548 | $entity = $msg->findDisplayEntity($entity, $alt_order); |
1549 | } |
1550 | $found = true; |
1551 | } else if ( $type == 'multipart/related') |
1552 | { |
319cf0d2 |
1553 | $msgs = $this->findRelatedEntity(); |
8f288482 |
1554 | foreach ($msgs as $msg) |
1555 | { |
1556 | if (count($msg->entities) == 0) |
1557 | { |
1558 | $entity[] = $msg->entity_id; |
1559 | } else |
1560 | { |
1561 | $entity = $msg->findDisplayEntity($entity,$alt_order); |
1562 | } |
1563 | } |
1564 | if (count($msgs) > 0) { |
1565 | $found = true; |
1566 | } |
1567 | } else if ($this->type0 == 'text' && |
1568 | ($this->type1 == 'plain' || |
1569 | $this->type1 == 'html' || |
1570 | $this->type1 == 'message') && |
1571 | isset($this->entity_id) ) |
1572 | { |
1573 | if (count($this->entities) == 0) |
1574 | { |
1575 | if (strtolower($this->header->disposition->name) != 'attachment') |
1576 | { |
1577 | $entity[] = $this->entity_id; |
1578 | } |
1579 | } |
1580 | } |
1581 | $i = 0; |
1582 | if(!$found) { |
1583 | foreach ($this->entities as $ent) { |
1584 | if(strtolower($ent->header->disposition->name) != 'attachment' && |
1585 | ($ent->type0 != 'message' && $ent->type1 != 'rfc822')) |
1586 | { |
1587 | $entity = $ent->findDisplayEntity($entity, $alt_order); |
1588 | } |
1589 | } |
1590 | } |
1591 | /* |
1592 | while ( isset($this->entities[$i]) && !$found && |
1593 | (strtolower($this->entities[$i]->header->disposition->name) |
1594 | != 'attachment') && |
1595 | ($this->entities[$i]->type0 != 'message' && |
1596 | $this->entities[$i]->type1 != 'rfc822' ) |
1597 | ) |
1598 | { |
1599 | $entity = $this->entities[$i]->findDisplayEntity($entity, $alt_order); |
1600 | $i++; |
1601 | } |
1602 | */ |
1603 | return( $entity ); |
8f6b86cc |
1604 | } |
319cf0d2 |
1605 | |
c52ffd66 |
1606 | function findAlternativeEntity ($alt_order) |
1607 | { |
319cf0d2 |
1608 | /* if we are dealing with alternative parts then we choose the best |
1609 | * viewable message supported by SM. |
1610 | */ |
1611 | $best_view = 0; |
8f288482 |
1612 | $entity = array(); |
1613 | $altcount = count($alt_order); |
1614 | foreach($this->entities as $ent) |
1615 | { |
1616 | $type = $ent->header->type0.'/'.$ent->header->type1; |
1617 | if ($type == 'multipart/related') |
1618 | { |
1619 | $type = $ent->header->getParameter('type'); |
1620 | } |
1621 | for ($j = $best_view; $j < $altcount; $j++) |
1622 | { |
1623 | if ($alt_order[$j] == $type && $j >= $best_view) |
1624 | { |
1625 | $best_view = $j; |
1626 | $entity = $ent; |
1627 | } |
1628 | } |
319cf0d2 |
1629 | } |
8f288482 |
1630 | return $entity; |
319cf0d2 |
1631 | } |
1632 | |
c52ffd66 |
1633 | function findRelatedEntity () |
1634 | { |
319cf0d2 |
1635 | $msgs = array(); |
8f288482 |
1636 | $entcount = count($this->entities); |
1637 | for ($i = 0; $i < $entcount; $i++) |
1638 | { |
319cf0d2 |
1639 | $type = $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1; |
c52ffd66 |
1640 | if ($this->header->getParameter('type') == $type) |
8f288482 |
1641 | { |
1642 | $msgs[] = $this->entities[$i]; |
1643 | } |
319cf0d2 |
1644 | } |
1645 | return $msgs; |
1646 | } |
1647 | |
c52ffd66 |
1648 | function getAttachments($exclude_id=array(), $result = array()) |
1649 | { |
1650 | if ($this->type0 == 'message' && $this->type1 == 'rfc822') |
1651 | { |
319cf0d2 |
1652 | $this = $this->entities[0]; |
1653 | } |
c52ffd66 |
1654 | if (count($this->entities)) |
1655 | { |
1656 | foreach ($this->entities as $entity) |
1657 | { |
319cf0d2 |
1658 | $exclude = false; |
c52ffd66 |
1659 | foreach ($exclude_id as $excl) |
1660 | { |
13c312be |
1661 | if ($entity->entity_id === $excl) |
c52ffd66 |
1662 | { |
319cf0d2 |
1663 | $exclude = true; |
1664 | } |
1665 | } |
c52ffd66 |
1666 | if (!$exclude) |
1667 | { |
1a09384c |
1668 | if ($entity->type0 == 'multipart' && |
c52ffd66 |
1669 | $entity->type1 != 'related') |
1670 | { |
319cf0d2 |
1671 | $result = $entity->getAttachments($exclude_id, $result); |
c52ffd66 |
1672 | } else if ($entity->type0 != 'multipart') |
1673 | { |
319cf0d2 |
1674 | $result[] = $entity; |
1675 | } |
1676 | } |
1677 | } |
c52ffd66 |
1678 | } else |
1679 | { |
1680 | $exclude = false; |
1681 | foreach ($exclude_id as $excl) |
1682 | { |
1683 | if ($this->entity_id == $excl) |
1684 | { |
1685 | $exclude = true; |
1686 | } |
1687 | } |
1688 | if (!$exclude) |
1689 | { |
1690 | $result[] = $this; |
1691 | } |
319cf0d2 |
1692 | } |
1693 | return $result; |
1694 | } |
8f6b86cc |
1695 | } |
1696 | |
c52ffd66 |
1697 | class smime_message |
1698 | { |
1699 | } |
1700 | |
1701 | class disposition |
1702 | { |
1703 | function disposition($name) |
1704 | { |
e8bedb2d |
1705 | $this->name = $name; |
1706 | $this->properties = array(); |
1707 | } |
924b0cac |
1708 | |
1709 | function getProperty($par) |
1710 | { |
1711 | $value = strtolower($par); |
1712 | if (isset($this->properties[$par])) |
1713 | { |
1714 | return $this->properties[$par]; |
1715 | } |
1716 | return ''; |
1717 | } |
1718 | |
8f6b86cc |
1719 | } |
1720 | |
c52ffd66 |
1721 | class language |
1722 | { |
1723 | function language($name) |
1724 | { |
e8bedb2d |
1725 | $this->name = $name; |
1726 | $this->properties = array(); |
1727 | } |
1728 | } |
1729 | |
c52ffd66 |
1730 | class content_type |
1731 | { |
e8bedb2d |
1732 | var $type0='text', |
1733 | $type1='plain', |
1734 | $properties=''; |
c52ffd66 |
1735 | function content_type($type) |
1736 | { |
e8bedb2d |
1737 | $pos = strpos($type,'/'); |
c52ffd66 |
1738 | if ($pos > 0) |
1739 | { |
e8bedb2d |
1740 | $this->type0 = substr($type,0,$pos); |
1741 | $this->type1 = substr($type,$pos+1); |
c52ffd66 |
1742 | } else |
1743 | { |
e8bedb2d |
1744 | $this->type0 = $type; |
1745 | } |
1746 | $this->properties = array(); |
c52ffd66 |
1747 | } |
31e0cfba |
1748 | } |
1749 | |
fc0dec58 |
1750 | ?> |