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