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