6 * Copyright (c) 2002 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
10 * This contains functions needed to handle mime messages.
19 * input: header_string or array
40 $more_headers = array(); /* only needed for constructing headers
43 function parseHeader($hdr)
47 $hdr = implode('',$hdr);
49 /* first we unfold the header */
50 $hdr = trim(str_replace(array("\r\n\t","\r\n "),array('',''),$hdr));
52 * now we can make a new header array with each element representing
55 $hdr = explode("\r\n" , $hdr);
56 foreach ($hdr as $line)
58 $pos = strpos($line,':');
61 $field = substr($line,0,$pos);
62 $value = trim(substr($line,$pos+
1));
63 if(!preg_match('/^X.*/i',$field)) {
64 $value = $this->stripComments($value);
66 $this->parseField($field,$value);
69 if ($this->content_type
== '')
71 $this->parseContentType('text/plain; charset=us-ascii');
75 function stripComments($value)
77 $cnt = strlen($value);
87 while ($value{$i} != '"')
89 if ($value{$i} == '\\')
101 while ($value{$i} != ')')
103 if ($value{$i} == '\\')
119 function parseField($field,$value)
121 $field = strtolower($field);
125 $d = strtr($value, array(' ' => ' '));
126 $d = explode(' ', $d);
127 $this->date
= getTimeStamp($d);
130 $this->subject
= $value;
133 $this->from
= $this->parseAddress($value,true);
136 $this->sender
= $this->parseAddress($value);
139 $this->reply_to
= $this->parseAddress($value, true);
142 $this->to
= $this->parseAddress($value, true);
145 $this->cc
= $this->parseAddress($value, true);
148 $this->bcc
= $this->parseAddress($value, true);
150 case ('in-reply-to'):
151 $this->in_reply_to
= $value;
154 $this->message_id
= $value;
156 case ('disposition-notification-to'):
157 $this->dnt
= $this->parseAddress($value);
159 case ('mime-Version'):
160 $value = str_replace(' ','',$value);
166 case ('content-type'):
167 $this->parseContentType($value);
169 case ('content-disposition'):
170 $this->parseDisposition($value);
173 $this->xmailer
= $value;
176 $this->priority
= $value;
179 $this->mlist('post',$value);
182 $this->mlist('reply',$value);
184 case ('list-subscribe'):
185 $this->mlist('subscribe',$value);
187 case ('list-unsubscribe'):
188 $this->mlist('unsubscribe',$value);
190 case ('list-archive'):
191 $this->mlist('archive',$value);
194 $this->mlist('owner',$value);
197 $this->mlist('help',$value);
200 $this->mlist('id',$value);
207 function parseAddress($address, $ar=false, $addr_ar = array(), $group = '')
210 $j = strlen( $address );
213 while ( $pos < $j ) {
214 switch ($address{$pos})
216 case ('"'): /* get the personal name */
218 if ($address{$pos} == '"')
223 while ( $pos < $j && $address{$pos} != '"')
225 if (substr($address, $pos, 2) == '\\"')
227 $name .= $address{$pos};
229 } elseif (substr($address, $pos, 2) == '\\\\')
231 $name .= $address{$pos};
234 $name .= $address{$pos};
240 case ('<'): /* get email address */
243 while ( $pos < $j && $address{$pos} != '>' )
245 $addr .= $address{$pos};
250 case ('('): /* rip off comments */
253 while ( $pos < $j && $address{$pos} != ')' )
255 $addr .= $address{$pos};
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 );
265 case (','): /* we reached a delimiter */
268 $addr = substr($address,0,$pos);
269 } elseif ($name == '') {
270 $name = trim(substr($address,0,$addr_start));
273 $at = strpos($addr, '@');
274 $addr_structure = new address_structure();
275 $addr_structure->personal
= $name;
276 $addr_structure->group
= $group;
279 $addr_structure->mailbox
= substr($addr,0,$at);
280 $addr_structure->host
= substr($addr,$at+
1);
283 $addr_structure->mailbox
= $addr;
285 $address = trim(substr($address,$pos+
1));
286 $j = strlen( $address );
290 $addr_ar[] = $addr_structure;
292 case (':'): /* process the group addresses */
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];
299 $address = substr($address,$pos);
300 $j = strlen( $address );
307 $address = substr($address, 0, $pos-1);
319 $addr = substr($address,0,$pos);
320 } elseif ($name == '')
322 $name = trim(substr($address,0,$addr_start));
324 $at = strpos($addr, '@');
325 $addr_structure = new address_structure();
326 $addr_structure->group
= $group;
329 $addr_structure->mailbox
= trim(substr($addr,0,$at));
330 $addr_structure->host
= trim(substr($addr,$at+
1));
333 $addr_structure->mailbox
= trim($addr);
335 if ($group && $addr == '') /* no addresses found in group */
337 $name = "$group: Undisclosed recipients;";
338 $addr_structure->personal
= $name;
339 $addr_ar[] = $addr_structure;
340 return (array($addr_ar,$pos+
1));
343 $addr_structure->personal
= $name;
346 $addr_ar[] = $addr_structure;
354 return ($addr_ar[0]);
358 function parseContentType($value)
360 $pos = strpos($value,';');
364 $type = trim(substr($value,0,$pos));
365 $props = trim(substr($type,$pos+
1));
370 $content_type = new content_type($type);
373 $properties = $this->parseProperties($props);
374 if (!isset($properties['charset']))
376 $properties['charset'] = 'us-ascii';
378 $content_type->properties
= $this->parseProperties($props);
380 $this->content_type
= $content_type;
383 function parseProperties($value)
385 $propArray = explode(';',$value);
386 $propResultArray = array();
387 foreach ($propArray as $prop)
390 $pos = strpos($prop,'=');
393 $key = trim(substr($prop,0,$pos));
394 $val = trim(substr($prop,$pos+
1));
397 $val = substr($val,1,-1);
399 $propResultArray[$key] = $val;
402 return $propResultArray;
405 function parseDisposition($value)
407 $pos = strpos($value,';');
411 $name = trim(substr($value,0,$pos));
412 $props = trim(substr($type,$pos+
1));
417 $props_a = $this->parseProperties($props);
418 $disp = new disposition($name);
419 $disp->properties
= $props_a;
420 $this->disposition
= $disp;
423 function mlist($field, $value)
426 $value_a = explode(',',$value);
427 foreach ($value_a as $val) {
431 $val = substr($val,1,-1);
433 if (substr($val,0,7) == 'mailto:')
435 $res_a['mailto'] = substr($val,7);
438 $res_a['href'] = $val;
441 $this->mlist
[$field] = $res_a;
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'))
450 function getAddr_s($arr, $separator=', ')
455 foreach($arr as $arg )
457 $result = $this->getAddr_s($arg);
460 $s .= $separator . $result;
463 if ($s) $s = substr($s,2);
468 eval('$addr = $this->'.$arr.';') ;
471 foreach ($addr as $addr_o)
473 if (is_object($addr_o))
475 $s .= $addr_o->getAddress() . $separator;
478 $s = substr($s,0,-strlen($separator));
481 if (is_object($addr))
483 $s .= $addr->getAddress();
490 function getAddr_a($arg, $excl_arr=array(), $arr = array())
494 foreach($arg as $argument )
496 $arr = $this->getAddr_a($argument, $excl_arr, $arr);
501 eval('$addr = $this->'.$arg.';') ;
504 foreach ($addr as $addr_o)
506 if (is_object($addr_o))
508 if (isset($addr_o->host
) && $addr_o->host
!='')
510 $email = $addr_o->mailbox
.'@'.$addr_o->host
;
513 $email = $addr_o->mailbox
;
515 $email = strtolower($email);
516 if ($email && !isset($arr[$email]) && !isset($excl_arr[$email]))
518 $arr[$email] = $addr_o->personal
;
524 if (is_object($addr))
526 if (isset($addr->host
))
528 $email = $addr->mailbox
.'@'.$addr->host
;
531 $email = $addr->mailbox
;
533 $email = strtolower($email);
534 if ($email && !isset($arr[$email]) && !isset($excl_arr[$email]))
536 $arr[$email] = $addr->personal
;
544 function getContentType($type0, $type1)
546 $type0 = $this->content_type
->type0
;
547 $type1 = $this->content_type
->type1
;
548 return $this->content_type
->properties
;
554 /** msg_header contains all variables available in a bodystructure **/
555 /** entity like described in rfc2060 **/
559 $parameters = array(),
569 * returns addres_list of supplied argument
570 * arguments: array('to', 'from', ...) or just a string like 'to'.
571 * result: string: address1, addres2, ....
574 function setVar($var, $value)
576 $this->{$var} = $value;
579 function getParameter($par)
581 $value = strtolower($par);
582 if (isset($this->parameters
[$par]))
584 return $this->parameters
[$par];
589 function setParameter($parameter, $value)
591 $this->parameters
[strtolower($parameter)] = $value;
597 class address_structure
599 var $personal = '', $adl = '', $mailbox = '', $host = '', $group = '';
601 function getAddress($full=true)
603 if (is_object($this))
605 if (isset($this->host
) && $this->host
!='')
607 $email = $this->mailbox
.'@'.$this->host
;
610 $email = $this->mailbox
;
612 if (trim($this->personal
) !='')
616 $addr = '"' . $this->personal
. '" <' .$email.'>';
619 $addr = $this->personal
;
621 $best_dpl = $this->personal
;
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.
645 var $rfc822_header = '',
651 $parent_ent, $entity,
652 $parent = '', $decoded_body='',
653 $is_seen = 0, $is_answered = 0, $is_deleted = 0, $is_flagged = 0,
656 $offset = 0, /* for fetching body parts out of raw messages */
657 $length = 0; /* for fetching body parts out of raw messages */
659 function setEnt($ent)
661 $this->entity_id
= $ent;
664 function addEntity ($msg)
666 $msg->parent
= &$this;
667 $this->entities
[] = $msg;
670 function getFilename()
673 if (is_object($this->header
->disposition
))
675 $filename = $this->header
->disposition
->getproperty('filename');
678 $filename = $this->header
->disposition
->getproperty('name');
683 $filename = 'untitled-'.$this->entity_id
;
689 function addRFC822Header($read)
691 $header = new rfc822_header();
692 $this->rfc822_header
= $header->parseHeader($read);
695 function getEntity($ent)
697 $cur_ent = $this->entity_id
;
699 if ($cur_ent == '' ||
$cur_ent == '0')
701 $cur_ent_a = array();
704 $cur_ent_a = explode('.',$this->entity_id
);
706 $ent_a = explode('.',$ent);
708 $cnt = count($ent_a);
710 for ($i=0;$i<$cnt -1;$i++
)
712 if (isset($cur_ent_a[$i]) && $cur_ent_a[$i] != $ent_a[$i])
715 $cur_ent_a = explode('.',$msg->entity_id
);
717 } else if (!isset($cur_ent_a[$i]))
719 if (isset($msg->entities
[($ent_a[$i]-1)]))
721 $msg = $msg->entities
[($ent_a[$i]-1)];
723 $msg = $msg->entities
[0];
726 if ($msg->type0
== 'message' && $msg->type1
== 'rfc822')
728 /*this is a header for a message/rfc822 entity */
729 $msg = $msg->entities
[0];
733 if ($msg->type0
== 'message' && $msg->type1
== 'rfc822')
735 /*this is a header for a message/rfc822 entity */
736 $msg = $msg->entities
[0];
739 if (isset($msg->entities
[($ent_a[$cnt-1])-1]))
741 if (is_object($msg->entities
[($ent_a[$cnt-1])-1]))
743 $msg = $msg->entities
[($ent_a[$cnt-1]-1)];
752 $this->body_part
= $s;
758 $msg->body_part
= '';
760 while ( isset($msg->entities
[$i]))
762 $msg->entities
[$i]->clean_up();
767 function getMailbox()
770 while (is_object($msg->parent
))
774 return $msg->mailbox
;
777 function calcEntity($msg)
779 if ($this->type0
== 'message' && $this->type1
== 'rfc822')
781 $msg->entity_id
= $this->entity_id
.'.0'; /* header of message/rfc822 */
782 } else if (isset($this->entity_id
) && $this->entity_id
!='')
784 $ent_no = count($this->entities
)+
1;
785 $par_ent = substr($this->entity_id
,-2);
786 if ($par_ent{0} == '.')
788 $par_ent = $par_ent{1};
792 $ent_no = count($this->entities
)+
1;
795 $ent = substr($this->entity_id
,0,strrpos($this->entity_id
,'.'));
798 $ent = $ent . ".$ent_no";
803 $msg->entity_id
= $ent;
806 $msg->entity_id
= $ent_no;
810 $ent = $this->entity_id
. ".$ent_no";
811 $msg->entity_id
= $ent;
815 $msg->entity_id
= '0';
817 return $msg->entity_id
;
822 * Bodystructure parser, a recursive function for generating the
823 * entity-tree with all the mime-parts.
825 * It follows RFC2060 and stores all the described fields in the
830 * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net.
833 function parseStructure($read, $i=0)
837 $cnt = strlen($read);
840 $char = strtoupper($read{$i});
848 $msg = new message();
849 $hdr = new msg_header();
850 $hdr->type0
= 'text';
851 $hdr->type1
= 'plain';
852 $hdr->encoding
= 'us-ascii';
853 $msg->entity_id
= $this->calcEntity($msg);
856 $msg->header
->type0
= 'multipart';
857 $msg->type0
= 'multipart';
858 while ($read{$i} == '(')
860 $res = $msg->parseStructure($read,$i);
862 $msg->addEntity($res[0]);
870 /* multipart properties */
872 $res = $this->parseProperties($read,$i);
879 if (isset($msg->type0
) && $msg->type0
== 'multipart')
882 $res = $msg->parseDisposition($read,$i);
885 } else /* properties */
887 $res = $msg->parseProperties($read,$i);
894 if (isset($msg->type0
) && $msg->type0
== 'multipart')
897 $res= $msg->parseLanguage($read,$i);
902 if ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')
904 $msg->header
->type0
= $arg_a[0];
905 $msg->type0
= $arg_a[0];
906 $msg->header
->type1
= $arg_a[1];
907 $msg->type1
= $arg_a[1];
908 $rfc822_hdr = new rfc822_header();
909 $res = $msg->parseEnvelope($read,$i,$rfc822_hdr);
911 $msg->rfc822_header
= $res[0];
913 while ($i < $cnt && $read{$i} != '(')
917 $res = $msg->parseStructure($read,$i);
919 $msg->addEntity($res[0]);
924 $res = $msg->parseDisposition($read,$i);
930 if ($arg_a[0] == 'text' ||
931 ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822'))
934 $res = $msg->parseDisposition($read,$i);
940 $res = $msg->parseLanguage($read,$i);
947 if ($arg_a[0] == 'text' ||
948 ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822'))
951 $res = $msg->parseLanguage($read,$i);
956 $i = $msg->parseParenthesis($read,$i);
957 $arg_a[] = ''; /* not yet desribed in rfc2060 */
962 /* unknown argument, skip this part */
963 $i = $msg->parseParenthesis($read,$i);
971 /* inside an entity -> start processing */
972 $debug = substr($read,$i,20);
973 $res = $msg->parseQuote($read,$i);
977 if ($arg_no < 3) $arg_s = strtolower($arg_s); /* type0 and type1 */
982 /* probably NIL argument */
983 if (strtoupper(substr($read,$i,4)) == 'NIL ' ||
984 strtoupper(substr($read,$i,4)) == 'NIL)')
992 /* process the literal value */
993 $res = $msg->parseLiteral($read,$i);
998 case (is_numeric($read{$i}) ):
999 /* process integers */
1000 if ($read{$i} == ' ') break;
1001 $arg_s = $read{$i};;
1003 while (preg_match('/^[0-9]{1}$/',$read{$i}))
1005 $arg_s .= $read{$i};
1012 if (isset($msg->type0
) && $msg->type0
== 'multipart')
1021 if ($arg_a[0] == 'text' ||
1022 ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822'))
1024 $shifted_args = true;
1027 $shifted_args = false;
1029 $hdr->type0
= $arg_a[0];
1030 $hdr->type1
= $arg_a[1];
1032 $msg->type0
= $arg_a[0];
1033 $msg->type1
= $arg_a[1];
1038 $hdr->parameters
= $arg_a[2];
1040 $hdr->id
= str_replace( '<', '', str_replace( '>', '', $arg_a[3] ) );
1041 $hdr->description
= $arg_a[4];
1042 $hdr->encoding
= strtolower($arg_a[5]);
1043 $hdr->entity_id
= $msg->entity_id
;
1044 $hdr->size
= $arg_a[6];
1047 $hdr->lines
= $arg_a[7];
1048 if (isset($arg_a[8]))
1050 $hdr->md5
= $arg_a[8];
1052 if (isset($arg_a[9]))
1054 $hdr->disposition
= $arg_a[9];
1056 if (isset($arg_a[10]))
1058 $hdr->language
= $arg_a[10];
1062 if (isset($arg_a[7]))
1064 $hdr->md5
= $arg_a[7];
1066 if (isset($arg_a[8]))
1068 $hdr->disposition
= $arg_a[8];
1070 if (isset($arg_a[9]))
1072 $hdr->language
= $arg_a[9];
1075 $msg->header
= $hdr;
1078 if (substr($msg->entity_id
,-2) == '.0' && $msg->type0
!='multipart')
1082 return (array($msg, $i));
1085 $hdr->type0
= 'multipart';
1086 $hdr->type1
= $arg_a[0];
1087 $msg->type0
= 'multipart';
1088 $msg->type1
= $arg_a[0];
1089 if (is_array($arg_a[1]))
1091 $hdr->parameters
= $arg_a[1];
1093 if (isset($arg_a[2]))
1095 $hdr->disposition
= $arg_a[2];
1097 if (isset($arg_a[3]))
1099 $hdr->language
= $arg_a[3];
1101 $msg->header
= $hdr;
1102 return (array($msg, $i));
1109 } /* parsestructure */
1111 function parseProperties($read, $i)
1113 $properties = array();
1116 while ($read{$i} != ')')
1118 if ($read{$i} == '"')
1120 $res = $this->parseQuote($read,$i);
1123 } else if ($read{$i} == '{')
1125 $res = $this->parseLiteral($read,$i);
1129 if ($prop_name == '' && $arg_s)
1131 $prop_name = strtolower($arg_s);
1132 $properties[$prop_name] = '';
1134 } elseif ($prop_name != '' && $arg_s != '')
1136 $properties[$prop_name] = $arg_s;
1142 return (array($properties, $i));
1145 function parseEnvelope($read, $i, $hdr)
1149 $cnt = strlen($read);
1150 while ($i< $cnt && $read{$i} != ')')
1153 $char = strtoupper($read{$i});
1157 $res = $this->parseQuote($read,$i);
1163 $res = $this->parseLiteral($read,$i);
1169 /* probably NIL argument */
1170 if (strtoupper(substr($read,$i,3)) == 'NIL') {
1177 /* Address structure
1178 * With group support.
1179 * Note: Group support is useless on SMTP connections
1180 * because the protocol doesn't support it
1185 while ($i < $cnt && $read{$i} != ')')
1187 if ($read{$i} == '(')
1189 $res = $this->parseAddress($read,$i);
1192 if ($addr->host
== '' && $addr->mailbox
!= '')
1194 /* start of group */
1195 $group = $addr->mailbox
;
1196 $group_addr = $addr;
1198 } elseif ($group && $addr->host
== '' && $addr->mailbox
== '')
1201 if ($a == $j+
1) /* no group members */
1203 $group_addr->group
= $group;
1204 $group_addr->mailbox
= '';
1205 $group_addr->personal
= "$group: Undisclosed recipients;";
1206 $addr_a[] = $group_addr;
1211 $addr->group
= $group;
1225 if (count($arg_a) > 9)
1227 /* argument 1: date */
1228 $d = strtr($arg_a[0], array(' ' => ' '));
1229 $d = explode(' ', $d);
1230 $hdr->date
= getTimeStamp($d);
1231 /* argument 2: subject */
1232 if (!trim($arg_a[1]))
1234 $arg_a[1]= _("(no subject)");
1236 $hdr->subject
= $arg_a[1];
1237 /* argument 3: from */
1238 $hdr->from
= $arg_a[2][0];
1239 /* argument 4: sender */
1240 $hdr->sender
= $arg_a[3][0];
1241 /* argument 5: reply-to */
1242 $hdr->replyto
= $arg_a[4][0];
1243 /* argument 6: to */
1244 $hdr->to
= $arg_a[5];
1245 /* argument 7: cc */
1246 $hdr->cc
= $arg_a[6];
1247 /* argument 8: bcc */
1248 $hdr->bcc
= $arg_a[7];
1249 /* argument 9: in-reply-to */
1250 $hdr->inreplyto
= $arg_a[8];
1251 /* argument 10: message-id */
1252 $hdr->message_id
= $arg_a[9];
1254 return (array($hdr,$i));
1257 function parseLiteral($read, $i)
1261 while ($read{$i} != '}')
1263 $lit_cnt .= $read{$i};
1266 $lit_cnt +
=2; /* add the { and } characters */
1268 for ($j = 0; $j < $lit_cnt; $j++
)
1273 return (array($s, $i));
1276 function parseQuote($read, $i)
1280 while ($read{$i} != '"')
1282 if ($read{$i} == '\\')
1289 return (array($s, $i));
1292 function parseAddress($read, $i)
1295 while ($read{$i} != ')' )
1297 $char = strtoupper($read{$i});
1301 $res = $this->parseQuote($read,$i);
1306 $res = $this->parseLiteral($read,$i);
1312 if (strtoupper(substr($read,$i,3)) == 'NIL') {
1322 if (count($arg_a) == 4)
1324 $adr = new address_structure();
1325 $adr->personal
= $arg_a[0];
1326 $adr->adl
= $arg_a[1];
1327 $adr->mailbox
= $arg_a[2];
1328 $adr->host
= $arg_a[3];
1333 return (array($adr,$i));
1336 function parseDisposition($read,$i)
1339 while ($read{$i} != ')')
1344 $res = $this->parseQuote($read,$i);
1349 $res = $this->parseLiteral($read,$i);
1354 $res = $this->parseProperties($read,$i);
1363 if (isset($arg_a[0]))
1365 $disp = new disposition($arg_a[0]);
1366 if (isset($arg_a[1]))
1368 $disp->properties
= $arg_a[1];
1371 if (is_object($disp))
1373 return (array($disp, $i));
1376 return (array('',$i));
1380 function parseLanguage($read,$i)
1382 /* no idea how to process this one without examples */
1384 while ($read{$i} != ')')
1389 $res = $this->parseQuote($read,$i);
1394 $res = $this->parseLiteral($read,$i);
1399 $res = $this->parseProperties($read,$i);
1408 if (isset($arg_a[0]))
1410 $lang = new language($arg_a[0]);
1411 if (isset($arg_a[1]))
1413 $lang->properties
= $arg_a[1];
1416 if (is_object($lang))
1418 return (array($lang, $i));
1421 return (array('', $i));
1425 function parseParenthesis($read,$i)
1427 while ($read{$i} != ')')
1432 $res = $this->parseQuote($read,$i);
1436 $res = $this->parseLiteral($read,$i);
1440 $res = $this->parseParenthesis($read,$i);
1451 /* function to fill the message structure in case the bodystructure
1452 isn't available NOT FINISHED YET
1454 function parseMessage($read, $type0, $type1)
1459 $rfc822_header = true;
1460 $mime_header = false;
1463 $mime_header = true;
1464 $rfc822_header = false;
1470 for ($i=1; $i < $count; $i++
)
1472 $line = trim($body[$i]);
1473 if ( ( $mime_header ||
$rfc822_header) &&
1474 (preg_match("/^.*boundary=\"?(.+(?=\")|.+).*/i",$line,$reg)) )
1478 $bndreg = str_replace("\\","\\\\",$bndreg);
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 } elseif ( $rfc822_header && $line == '' )
1488 $rfc822_header = false;
1489 if ($msg->type0
== 'multipart')
1491 $mime_header = true;
1495 if (($line{0} == '-' ||
$rfc822_header) && isset($boundaries[0]))
1497 $cnt=count($boundaries)-1;
1498 $bnd = $boundaries[$cnt]['bnd'];
1499 $bndreg = $boundaries[$cnt]['bndreg'];
1501 $regstr = '/^--'."($bndreg)".".*".'/';
1502 if (preg_match($regstr,$line,$reg) )
1504 $bndlen = strlen($reg[1]);
1506 if (strlen($line) > ($bndlen +
3))
1508 if ($line{$bndlen+
2} == '-' && $line{$bndlen+
3} == '-')
1513 /* calc offset and return $msg */
1514 // $entStr = CalcEntity("$entStr",-1);
1515 array_pop($boundaries);
1516 $mime_header = true;
1520 $mime_header = true;
1522 // $entStr = CalcEntity("$entStr",0);
1535 function findDisplayEntity ($entity = array(), $alt_order = array('text/plain','text/html'))
1538 $type = $this->type0
.'/'.$this->type1
;
1539 if ( $type == 'multipart/alternative')
1541 $msg = $this->findAlternativeEntity($alt_order);
1542 if (count($msg->entities
) == 0)
1544 $entity[] = $msg->entity_id
;
1547 $entity = $msg->findDisplayEntity($entity, $alt_order);
1550 } else if ( $type == 'multipart/related')
1552 $msgs = $this->findRelatedEntity();
1553 foreach ($msgs as $msg)
1555 if (count($msg->entities
) == 0)
1557 $entity[] = $msg->entity_id
;
1560 $entity = $msg->findDisplayEntity($entity,$alt_order);
1563 if (count($msgs) > 0) {
1566 } else if ($this->type0
== 'text' &&
1567 ($this->type1
== 'plain' ||
1568 $this->type1
== 'html' ||
1569 $this->type1
== 'message') &&
1570 isset($this->entity_id
) )
1572 if (count($this->entities
) == 0)
1574 if (strtolower($this->header
->disposition
->name
) != 'attachment')
1576 $entity[] = $this->entity_id
;
1582 foreach ($this->entities
as $ent) {
1583 if(strtolower($ent->header
->disposition
->name
) != 'attachment' &&
1584 ($ent->type0
!= 'message' && $ent->type1
!= 'rfc822'))
1586 $entity = $ent->findDisplayEntity($entity, $alt_order);
1591 while ( isset($this->entities[$i]) && !$found &&
1592 (strtolower($this->entities[$i]->header->disposition->name)
1594 ($this->entities[$i]->type0 != 'message' &&
1595 $this->entities[$i]->type1 != 'rfc822' )
1598 $entity = $this->entities[$i]->findDisplayEntity($entity, $alt_order);
1605 function findAlternativeEntity ($alt_order)
1607 /* if we are dealing with alternative parts then we choose the best
1608 * viewable message supported by SM.
1612 $altcount = count($alt_order);
1613 foreach($this->entities
as $ent)
1615 $type = $ent->header
->type0
.'/'.$ent->header
->type1
;
1616 if ($type == 'multipart/related')
1618 $type = $ent->header
->getParameter('type');
1620 for ($j = $best_view; $j < $altcount; $j++
)
1622 if ($alt_order[$j] == $type && $j >= $best_view)
1632 function findRelatedEntity ()
1635 $entcount = count($this->entities
);
1636 for ($i = 0; $i < $entcount; $i++
)
1638 $type = $this->entities
[$i]->header
->type0
.'/'.$this->entities
[$i]->header
->type1
;
1639 if ($this->header
->getParameter('type') == $type)
1641 $msgs[] = $this->entities
[$i];
1647 function getAttachments($exclude_id=array(), $result = array())
1649 if ($this->type0
== 'message' && $this->type1
== 'rfc822')
1651 $this = $this->entities
[0];
1653 if (count($this->entities
))
1655 foreach ($this->entities
as $entity)
1658 foreach ($exclude_id as $excl)
1660 if ($entity->entity_id
=== $excl)
1667 if ($entity->type0
== 'multipart' &&
1668 $entity->type1
!= 'related')
1670 $result = $entity->getAttachments($exclude_id, $result);
1671 } else if ($entity->type0
!= 'multipart')
1673 $result[] = $entity;
1680 foreach ($exclude_id as $excl)
1682 if ($this->entity_id
== $excl)
1702 function disposition($name)
1704 $this->name
= $name;
1705 $this->properties
= array();
1708 function getProperty($par)
1710 $value = strtolower($par);
1711 if (isset($this->properties
[$par]))
1713 return $this->properties
[$par];
1722 function language($name)
1724 $this->name
= $name;
1725 $this->properties
= array();
1734 function content_type($type)
1736 $pos = strpos($type,'/');
1739 $this->type0
= substr($type,0,$pos);
1740 $this->type1
= substr($type,$pos+
1);
1743 $this->type0
= $type;
1745 $this->properties
= array();