{$var} = $value; } /* * function to get the addres strings out of the header. * Arguments: string or array of strings ! * example1: header->getAddr_s('to'). * example2: header->getAddr_s(array('to','cc','bcc')) */ function getAddr_s($arr) { if (is_array($arr)) { $s = ''; foreach($arr as $arg ) { $result = $this->getAddr_s($arg); if ($result) { $s .= ', ' . $result; } } if ($s) $s = substr($s,2); return $s; } else { $s = ''; eval('$addr = $this->'.$arr.';') ; if (is_array($addr)) { foreach ($addr as $addr_o) { if (is_object($addr_o)) { $s .= $addr_o->getAddress() . ', '; } } $s = substr($s,0,-2); } else { if (is_object($addr)) { $s .= $addr->getAddress(); } } return $s; } } function getAddr_a($arg, $excl_arr=array(), $arr = array()) { if (is_array($arg)) { foreach($arg as $argument ) { $arr = $this->getAddr_a($argument, $excl_arr, $arr); } return $arr; } else { eval('$addr = $this->'.$arg.';') ; if (is_array($addr)) { foreach ($addr as $addr_o) { if (is_object($addr_o)) { if (isset($addr_o->host) && $addr_o->host !='') { $email = $addr_o->mailbox.'@'.$addr_o->host; } else { $email = $addr_o->mailbox; } $email = strtolower($email); if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) { $arr[$email] = $addr_o->personal; } } } } else { if (is_object($addr)) { if (isset($addr->host)) { $email = $addr->mailbox.'@'.$addr->host; } else { $email = $addr->mailbox; } $email = strtolower($email); if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) { $arr[$email] = $addr->personal; } } } return $arr; } } } class address_structure { var $personal = '', $adl = '', $mailbox = '', $host = '', $group = ''; function getAddress($full=true) { if (is_object($this)) { if (isset($this->host) && $this->host !='') { $email = '<'.$this->mailbox.'@'.$this->host.'>'; } else { $email = $this->mailbox; } if (trim($this->personal) !='') { if ($email) { $addr = '"' . $this->personal . '" ' .$email; } else { $addr = $this->personal; } $best_dpl = $this->personal; } else { $addr = $email; $best_dpl = $email; } if ($full) { return $addr; } else { return $best_dpl; } } else return ''; } } class message { /** message is the object that contains messages. It is a recursive object in that through the $entities variable, it can contain more objects of type message. See documentation in mime.txt for a better description of how this works. **/ var $header = '', $entities = array(), $mailbox = 'INBOX', $id = 0, $envelope = '', $parent_ent, $entity, $type0='', $type1='', $parent = '', $decoded_body='', $is_seen = 0, $is_answered = 0, $is_deleted = 0, $is_flagged = 0, $is_mdnsent = 0; function setEnt($ent) { $this->entity_id= $ent; } function setBody($body) { $this->decoded_body = $body; } function addEntity ($msg) { $msg->parent = &$this; $this->entities[] = $msg; } function addRFC822Header($read) { $header = new msg_header(); $this->header = sqimap_parse_RFC822Header($read,$header); } function getEntity($ent) { $cur_ent = $this->entity_id; $msg = $this; if ($cur_ent == '' || $cur_ent == '0') { $cur_ent_a = array(); } else { $cur_ent_a = explode('.',$this->entity_id); } $ent_a = explode('.',$ent); $cnt = count($ent_a); for ($i=0;$i<$cnt -1;$i++) { if (isset($cur_ent_a[$i]) && $cur_ent_a[$i] != $ent_a[$i]) { $msg = $msg->parent; $cur_ent_a = explode('.',$msg->entity_id); $i--; } else if (!isset($cur_ent_a[$i])) { if (isset($msg->entities[($ent_a[$i]-1)])) { $msg = $msg->entities[($ent_a[$i]-1)]; } else { $msg = $msg->entities[0]; } } if ($msg->type0 == 'message' && $msg->type1 == 'rfc822') { /*this is a header for a message/rfc822 entity */ $msg = $msg->entities[0]; } } if ($msg->type0 == 'message' && $msg->type1 == 'rfc822') { /*this is a header for a message/rfc822 entity */ $msg = $msg->entities[0]; } if (isset($msg->entities[($ent_a[$cnt-1])-1])) { $msg = $msg->entities[($ent_a[$cnt-1]-1)]; } return $msg; } function getMailbox() { $msg = $this; while (is_object($msg->parent)) { $msg = $msg->parent; } return $msg->mailbox; } /* * Bodystructure parser, a recursive function for generating the * entity-tree with all the mime-parts. * * It follows RFC2060 and stores all the described fields in the * message object. * * Question/Bugs: * * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net. * */ function &parseStructure($read, $i=0, $message = false) { $arg_no = 0; $arg_a = array(); $cnt = strlen($read); while ($i < $cnt) { $char = strtoupper($read{$i}); switch ($char) { case '(': if ($arg_no == 0 ) { if (!isset($msg)) { $msg = new message(); $hdr = new msg_header(); $hdr->type0 = 'text'; $hdr->type1 = 'plain'; $hdr->encoding = 'us-ascii'; if ($this->type0 == 'message' && $this->type1 == 'rfc822') { $msg->entity_id = $this->entity_id .'.0'; /* header of message/rfc822 */ } else if (isset($this->entity_id) && $this->entity_id !='') { $ent_no = count($this->entities)+1; $par_ent = substr($this->entity_id,-2); if ($par_ent{0} == '.') { $par_ent = $par_ent{1}; } if ($par_ent == '0') { $ent_no = count($this->entities)+1; if ($ent_no > 0) { $ent = substr($this->entity_id,0,strrpos($this->entity_id,'.')); if ($ent) { $ent = $ent . ".$ent_no"; } else { $ent = $ent_no; } $msg->entity_id = $ent; } else { $msg->entity_id = $ent_no; } } else { $ent = $this->entity_id . ".$ent_no"; $msg->entity_id = $ent; } } else { $msg->entity_id = '0'; } } else { $msg->header->type0 = 'multipart'; $msg->type0 = 'multipart'; while ($read{$i} == '(') { $msg->addEntity($msg->parseStructure($read,&$i)); } } } else { switch ($arg_no) { case 1: /* multipart properties */ $i++; $arg_a[] = $this->parseProperties($read,&$i); $arg_no++; break; case 2: if (isset($msg->type0) && $msg->type0 == 'multipart') { $i++; $arg_a[]= $msg->parseDisposition($read,&$i); } else { /* properties */ /* properties */ $arg_a[] = $msg->parseProperties($read,&$i); } $arg_no++; break; case 3: if (isset($msg->type0) && $msg->type0 == 'multipart') { $i++; $arg_a[]= $msg->parseLanguage($read,&$i); } case 7: if ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822') { $msg->header->type0 = $arg_a[0]; $msg->type0 = $arg_a[0]; $msg->header->type1 = $arg_a[1]; $msg->type1 = $arg_a[1]; $msg->parseEnvelope($read,&$i,&$hdr); $i++; while ($i < $cnt && $read{$i} != '(') { $i++; } $msg->addEntity($msg->parseStructure($read,&$i)); } break; case 8: $i++; $arg_a[] = $msg->parseDisposition($read,&$i); $arg_no++; break; case 9: if ($arg_a[0] == 'text' || ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) { $i++; $arg_a[] = $msg->parseDisposition($read,&$i); } else { $i++; $arg_a[] = $msg->parseLanguage($read,&$i); } $arg_no++; break; case 10: if ($arg_a[0] == 'text' || ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) { $i++; $arg_a[] = $msg->parseLanguage($read,&$i); } else { $msg->parseParenthesis($read,&$i); $arg_a[] = ''; /* not yet desribed in rfc2060 */ } $arg_no++; break; default: /* unknown argument, skip this part */ $msg->parseParenthesis($read,&$i); $arg_a[] = ''; $arg_no++; break; } /* switch */ } break; case '"': /* inside an entity -> start processing */ $debug = substr($read,$i,20); $arg_s = $msg->parseQuote($read,&$i); $arg_no++; if ($arg_no < 3) $arg_s = strtolower($arg_s); /* type0 and type1 */ $arg_a[] = $arg_s; break; case 'N': /* probably NIL argument */ if (strtoupper(substr($read,$i,4)) == 'NIL ' || strtoupper(substr($read,$i,4)) == 'NIL)') { $arg_a[] = ''; $arg_no++; $i = $i+2; } break; case '{': /* process the literal value */ $arg_a[] = $msg->parseLiteral($read,&$i); $arg_no++; break; case (is_numeric($read{$i}) ): /* process integers */ if ($read{$i} == ' ') break; $arg_s = $read{$i};; $i++; while (preg_match('/\d+/',$read{$i})) { // != ' ') { $arg_s .= $read{$i}; $i++; } $arg_no++; $arg_a[] = $arg_s; break; case ')': if (isset($msg->type0) && $msg->type0 == 'multipart') { $multipart = true; } else { $multipart = false; } if (!$multipart) { if ($arg_a[0] == 'text' || ($arg_a[0] == 'message' && $arg_a[1] == 'rfc822')) { $shifted_args = true; } else { $shifted_args = false; } $hdr->type0 = $arg_a[0]; $hdr->type1 = $arg_a[1]; $msg->type0 = $arg_a[0]; $msg->type1 = $arg_a[1]; $arr = $arg_a[2]; if (is_array($arr)) { foreach($arr as $name => $value) { $hdr->{$name} = $value; } } $hdr->id = str_replace( '<', '', str_replace( '>', '', $arg_a[3] ) ); $hdr->description = $arg_a[4]; $hdr->encoding = strtolower($arg_a[5]); $hdr->entity_id = $msg->entity_id; $hdr->size = $arg_a[6]; if ($shifted_args) { $hdr->lines = $arg_a[7]; if (isset($arg_a[8])) { $hdr->md5 = $arg_a[8]; } if (isset($arg_a[9])) { $hdr->disposition = $arg_a[9]; } if (isset($arg_a[10])) { $hdr->language = $arg_a[10]; } } else { if (isset($arg_a[7])) { $hdr->md5 = $arg_a[7]; } if (isset($arg_a[8])) { $hdr->disposition = $arg_a[8]; } if (isset($arg_a[9])) { $hdr->language = $arg_a[9]; } } $msg->header = $hdr; $arg_no = 0; $i++; if (substr($msg->entity_id,-2) == '.0' && $msg->type0 !='multipart') { $msg->entity_id++; } return $msg; } else { $hdr->type0 = 'multipart'; $hdr->type1 = $arg_a[0]; $msg->type0 = 'multipart'; $msg->type1 = $arg_a[0]; if (isset($arg_a[1])) { $arr = $arg_a[1]; if (is_array($arr)) { foreach($arr as $name => $value) { $hdr->{$name} = $value; } } } if (isset($arg_a[2])) { $hdr->disposition = $arg_a[2]; } if (isset($arg_a[3])) { $hdr->language = $arg_a[3]; } $msg->header = $hdr; return $msg; } default: break; } /* switch */ $i++; } /* while */ } /* parsestructure */ function parseProperties($read, $i) { $properties = array(); $arg_s = ''; $prop_name = ''; while ($read{$i} != ')') { if ($read{$i} == '"') { $arg_s = $this->parseQuote($read,&$i); } else if ($read{$i} == '{') { $arg_s = $this->parseLiteral($read,&$i); } if ($prop_name == '' && $arg_s) { $prop_name = strtolower($arg_s); $properties[$prop_name] = ''; $arg_s = ''; } elseif ($prop_name != '' && $arg_s != '') { $properties[$prop_name] = $arg_s; $prop_name = ''; $arg_s = ''; } $i++; } return $properties; } function parseEnvelope($read, $i, $hdr) { $arg_no = 0; $arg_a = array(); $cnt = strlen($read); while ($i< $cnt && $read{$i} != ')') { $i++; $char = strtoupper($read{$i}); switch ($char) { case '"': $arg_a[] = $this->parseQuote($read,&$i); $arg_no++; break; case '{': $arg_a[] = $this->parseLiteral($read,&$i); $arg_no++; break; case 'N': /* probably NIL argument */ if (strtoupper(substr($read,$i,3)) == 'NIL') { $arg_a[] = ''; $arg_no++; $i = $i+2; } break; case '(': /* Address structure * With group support. * Note: Group support is useless on SMTP connections * because the protocol doesn't support it */ $addr_a = array(); $group = ''; $a=0; while ($i < $cnt && $read{$i} != ')') { if ($read{$i} == '(') { $addr = $this->parseAddress($read,&$i); if ($addr->host == '' && $addr->mailbox != '') { /* start of group */ $group = $addr->mailbox; $group_addr = $addr; $j = $a; } elseif ($group && $addr->host == '' && $addr->mailbox == '') { /* end group */ if ($a == $j+1) { /* no group members */ $group_addr->group = $group; $group_addr->mailbox = ''; $group_addr->personal = "$group: Undisclosed recipients;"; $addr_a[] = $group_addr; $group =''; } } else { $addr->group = $group; $addr_a[] = $addr; } $a++; } $i++; } $arg_a[] = $addr_a; break; default: break; } $i++; } if (count($arg_a) > 9) { /* argument 1: date */ $d = strtr($arg_a[0], array(' ' => ' ')); $d = explode(' ', $d); $hdr->date = getTimeStamp($d); /* argument 2: subject */ if (!trim($arg_a[1])) { $arg_a[1]= _("(no subject)"); } $hdr->subject = $arg_a[1]; /* argument 3: from */ $hdr->from = $arg_a[2][0]; /* argument 4: sender */ $hdr->sender = $arg_a[3][0]; /* argument 5: reply-to */ $hdr->replyto = $arg_a[4][0]; /* argument 6: to */ $hdr->to = $arg_a[5]; /* argument 7: cc */ $hdr->cc = $arg_a[6]; /* argument 8: bcc */ $hdr->bcc = $arg_a[7]; /* argument 9: in-reply-to */ $hdr->inreplyto = $arg_a[8]; /* argument 10: message-id */ $hdr->message_id = $arg_a[9]; } } function parseLiteral($read, $i) { $lit_cnt = ''; $i++; while ($read{$i} != '}') { $lit_cnt .= $read{$i}; $i++; } $lit_cnt +=2; /* add the { and } characters */ $s = ''; for ($j = 0; $j < $lit_cnt; $j++) { $i++; $s .= $read{$i}; } return $s; } function parseQuote($read, $i) { $i++; $s = ''; while ($read{$i} != '"') { if ($read{$i} == '\\') { $i++; } $s .= $read{$i}; $i++; } return $s; } function parseAddress($read, $i) { $arg_a = array(); while ($read{$i} != ')' ) { //&& $i < count($read)) { $char = strtoupper($read{$i}); switch ($char) { case '"': $arg_a[] = $this->parseQuote($read,&$i); break; case '{': $arg_a[] = $this->parseLiteral($read,&$i); break; case 'N': if (strtolower(substr($read,$i,3)) == 'nil') { $arg_a[] = ''; $i = $i+2; } break; default: break; } $i++; } if (count($arg_a) == 4) { $adr = new address_structure(); $adr->personal = $arg_a[0]; $adr->adl = $arg_a[1]; $adr->mailbox = $arg_a[2]; $adr->host = $arg_a[3]; } else { $adr = ''; } return $adr; } function parseDisposition($read,&$i) { $arg_a = array(); while ($read{$i} != ')') { switch ($read{$i}) { case '"': $arg_a[] = $this->parseQuote($read,&$i); break; case '{': $arg_a[] = $this->parseLiteral($read,&$i); break; case '(': $arg_a[] = $this->parseProperties($read,&$i); break; default: break; } $i++; } if (isset($arg_a[0])) { $disp = new disposition($arg_a[0]); if (isset($arg_a[1])) { $disp->properties = $arg_a[1]; } } if (is_object($disp)) { return $disp; } } function parseLanguage($read,&$i) { /* no idea how to process this one without examples */ $arg_a = array(); while ($read{$i} != ')') { switch ($read{$i}) { case '"': $arg_a[] = $this->parseQuote($read,&$i); break; case '{': $arg_a[] = $this->parseLiteral($read,&$i); break; case '(': $arg_a[] = $this->parseProperties($read,&$i); break; default: break; } $i++; } if (isset($arg_a[0])) { $lang = new language($arg_a[0]); if (isset($arg_a[1])) { $lang->properties = $arg_a[1]; } } if (is_object($lang)) { return $lang; } else { return ''; } } function parseParenthesis($read,&$i) { while ($read{$i} != ')') { switch ($read{$i}) { case '"': $this->parseQuote($read,&$i); break; case '{': $this->parseLiteral($read,&$i); break; case '(': $this->parseParenthesis($read,&$i); break; default: break; } $i++; } } function findDisplayEntity ($entity = array(), $alt_order = array('text/plain','text/html')) { $found = false; $type = $this->type0.'/'.$this->type1; if ( $type == 'multipart/alternative') { $msg = $this->findAlternativeEntity($alt_order); if (count($msg->entities) == 0) { $entity[] = $msg->entity_id; } else { $msg->findDisplayEntity(&$entity, $alt_order); } $found = true; } else if ( $type == 'multipart/related') { $msgs = $this->findRelatedEntity(); for ($i = 0; $i < count($msgs); $i++) { $msg = $msgs[$i]; if (count($msg->entities) == 0) { $entity[] = $msg->entity_id; } else { $msg->findDisplayEntity(&$entity,$alt_order); } $found = true; } } else if ( $this->type0 == 'text' && ( $this->type1 == 'plain' || $this->type1 == 'html' || $this->type1 == 'message') && isset($this->entity_id) ) { if (count($this->entities) == 0) { if (!$this->header->disposition->name == 'attachment') { $entity[] = $this->entity_id; } } } $i = 0; while ( isset($this->entities[$i]) && !$found && !($this->entities[$i]->header->disposition->name == 'attachment') && !($this->entities[$i]->type0 == 'message' && $this->entities[$i]->type1 == 'rfc822' ) ) { $this->entities[$i]->findDisplayEntity(&$entity, $alt_order); $i++; } if ( !isset($entity[0]) ) { $entity[]=""; } return( $entity ); } function findAlternativeEntity ($alt_order) { /* if we are dealing with alternative parts then we choose the best * viewable message supported by SM. */ $best_view = 0; $ent_id = 0; $k = 0; for ($i = 0; $i < count($this->entities); $i ++) { $type = $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1; if ($type == 'multipart/related') { $type = $this->entities[$i]->header->type; } for ($j = $k; $j < count($alt_order); $j++) { if ($alt_order[$j] == $type && $j > $best_view) { $best_view = $j; $ent_id = $i; $k = $j; } } } return $this->entities[$ent_id]; } function findRelatedEntity () { $msgs = array(); for ($i = 0; $i < count($this->entities); $i ++) { $type = $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1; if ($this->header->type == $type) { $msgs[] = $this->entities[$i]; } } return $msgs; } function getAttachments($exclude_id=array(), $result = array()) { if ($this->type0 == 'message' && $this->type1 == 'rfc822') { $this = $this->entities[0]; } if (count($this->entities)) { foreach ($this->entities as $entity) { $exclude = false; foreach ($exclude_id as $excl) { if ($entity->entity_id == $excl) { $exclude = true; } } if (!$exclude) { if ($entity->type0 == 'multipart' && $entity->type1 != 'related') { $result = $entity->getAttachments($exclude_id, $result); } else if ($entity->type0 != 'multipart') { $result[] = $entity; } } } } else { $exclude = false; foreach ($exclude_id as $excl) { if ($this->entity_id == $excl) { $exclude = true; } } if (!$exclude) { $result[] = $this; } } return $result; } } class disposition { function disposition($name) { $this->name = $name; $this->properties = array(); } } class language { function language($name) { $this->name = $name; $this->properties = array(); } } ?>