/**
* Message.class.php
*
- * Copyright (c) 2002 The SquirrelMail Project Team
+ * Copyright (c) 2003 The SquirrelMail Project Team
* Licensed under the GNU GPL. For full terms see the file COPYING.
*
* This contains functions needed to handle mime messages.
}
function addEntity ($msg) {
- $msg->parent = &$this;
$this->entities[] = $msg;
}
return $msg->mailbox;
}
- function calcEntity($msg) {
- 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 != '')) {
- $entCount = count($this->entities) + 1;
- $par_ent = substr($this->entity_id, -2);
- if ($par_ent{0} == '.') {
- $par_ent = $par_ent{1};
- }
- if ($par_ent == '0') {
- if ($entCount > 0) {
- $ent = substr($this->entity_id, 0, strrpos($this->entity_id, '.'));
- $ent = ($ent ? $ent . '.' : '') . $entCount;
- $msg->entity_id = $ent;
- } else {
- $msg->entity_id = $entCount;
- }
- } else {
- $ent = $this->entity_id . '.' . $entCount;
- $msg->entity_id = $ent;
- }
- } else {
- $msg->entity_id = '0';
- }
-
- return $msg->entity_id;
- }
-
-
/*
* Bodystructure parser, a recursive function for generating the
* entity-tree with all the mime-parts.
* Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net)
*
*/
- function parseStructure($read, $i = 0) {
+ function parseStructure($read, &$i, $sub_msg = '') {
+ $msg = Message::parseBodyStructure($read, $i, $sub_msg);
+ if($msg) $msg->setEntIds($msg,false,0);
+ return $msg;
+ }
+
+ function setEntIds(&$msg,$init=false,$i=0) {
+ $iCnt = count($msg->entities);
+ if ($init !==false) {
+ $iEntSub = $i+1;
+ if ($msg->parent->type0 == 'message' &&
+ $msg->parent->type1 == 'rfc822' &&
+ $msg->type0 == 'multipart') {
+ $iEntSub = '0';
+ }
+ if ($init) {
+ $msg->entity_id = "$init.$iEntSub";
+ } else {
+ $msg->entity_id = $iEntSub;
+ }
+ } else if ($iCnt) {
+ $msg->entity_id='0';
+ } else {
+ $msg->entity_id='1';
+ }
+ for ($i=0;$i<$iCnt;++$i) {
+ $msg->entities[$i]->parent =& $msg;
+ if (strrchr($msg->entity_id, '.') != '.0') {
+ $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->entity_id,$i);
+ } else {
+ $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->parent->entity_id,$i);
+ }
+
+ }
+ }
+
+ function parseBodyStructure($read, &$i, $sub_msg = '') {
$arg_no = 0;
$arg_a = array();
+ if ($sub_msg) {
+ $message = $sub_msg;
+ } else {
+ $message = new Message();
+ }
+ $this = $message;
for ($cnt = strlen($read); $i < $cnt; ++$i) {
$char = strtoupper($read{$i});
switch ($char) {
$hdr->type0 = 'text';
$hdr->type1 = 'plain';
$hdr->encoding = 'us-ascii';
- $msg->entity_id = $this->calcEntity($msg);
} else {
$msg->header->type0 = 'multipart';
$msg->type0 = 'multipart';
while ($read{$i} == '(') {
- $res = $msg->parseStructure($read, $i);
- $i = $res[1];
- $msg->addEntity($res[0]);
+ $msg->addEntity($this->parseBodyStructure($read, $i, $msg));
}
}
break;
case 2:
if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
++$i;
- $arg_a[] = $msg->parseDisposition($read, $i);
+ $arg_a[] = $this->parseDisposition($read, $i);
} else { /* properties */
- $arg_a[] = $msg->parseProperties($read, $i);
+ $arg_a[] = $this->parseProperties($read, $i);
}
++$arg_no;
break;
case 3:
if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
++$i;
- $arg_a[]= $msg->parseLanguage($read, $i);
+ $arg_a[]= $this->parseLanguage($read, $i);
}
case 7:
if (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822')) {
$msg->type0 = $arg_a[0];
$msg->type1 = $arg_a[1];
$rfc822_hdr = new Rfc822Header();
- $msg->rfc822_header = $msg->parseEnvelope($read, $i, $rfc822_hdr);
+ $msg->rfc822_header = $this->parseEnvelope($read, $i, $rfc822_hdr);
while (($i < $cnt) && ($read{$i} != '(')) {
++$i;
}
- $res = $msg->parseStructure($read, $i);
- $i = $res[1];
- $msg->addEntity($res[0]);
+ $msg->addEntity($this->parseBodyStructure($read, $i,$msg));
}
break;
case 8:
++$i;
- $arg_a[] = $msg->parseDisposition($read, $i);
+ $arg_a[] = $this->parseDisposition($read, $i);
++$arg_no;
break;
case 9:
++$i;
if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
- $arg_a[] = $msg->parseDisposition($read, $i);
+ $arg_a[] = $this->parseDisposition($read, $i);
} else {
- $arg_a[] = $msg->parseLanguage($read, $i);
+ $arg_a[] = $this->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);
+ $arg_a[] = $this->parseLanguage($read, $i);
} else {
- $i = $msg->parseParenthesis($read, $i);
+ $i = $this->parseParenthesis($read, $i);
$arg_a[] = ''; /* not yet described in rfc2060 */
}
++$arg_no;
break;
default:
/* unknown argument, skip this part */
- $i = $msg->parseParenthesis($read, $i);
+ $i = $this->parseParenthesis($read, $i);
$arg_a[] = '';
++$arg_no;
break;
break;
case '"':
/* inside an entity -> start processing */
- $debug = substr($read, $i, 20);
- $arg_s = $msg->parseQuote($read, $i);
+ $arg_s = $this->parseQuote($read, $i);
++$arg_no;
if ($arg_no < 3) {
$arg_s = strtolower($arg_s); /* type0 and type1 */
case 'n':
case 'N':
/* probably NIL argument */
- if (strtoupper(substr($read, $i, 4)) == 'NIL ') {
+ $tmpnil = strtoupper(substr($read, $i, 4));
+ if ($tmpnil == 'NIL ' || $tmpnil == 'NIL)') {
$arg_a[] = '';
++$arg_no;
$i += 2;
break;
case '{':
/* process the literal value */
- $arg_s = $msg->parseLiteral($read, $i);
+ $arg_s = $this->parseLiteral($read, $i);
++$arg_no;
break;
+ case '0':
case is_numeric($read{$i}):
/* process integers */
if ($read{$i} == ' ') { break; }
- $arg_s = $read{$i};;
- for (++$i; preg_match('/^[0-9]{1}$/', $read{$i}); ++$i) {
- $arg_s .= $read{$i};
- }
- ++$arg_no;
- $arg_a[] = $arg_s;
+ ++$arg_no;
+ if (preg_match('/^([0-9]+).*/',substr($read,$i), $regs)) {
+ $i += strlen($regs[1])-1;
+ $arg_a[] = $regs[1];
+ } else {
+ $arg_a[] = 0;
+ }
break;
case ')':
$multipart = (isset($msg->type0) && ($msg->type0 == 'multipart'));
$hdr->disposition = (isset($arg_a[8+$s]) ? $arg_a[8+$s] : $hdr->disposition);
$hdr->language = (isset($arg_a[9+$s]) ? $arg_a[9+$s] : $hdr->language);
$msg->header = $hdr;
- if ((strrchr($msg->entity_id, '.') == '.0') && ($msg->type0 !='multipart')) {
- $msg->entity_id = $this->entity_id . '.1';
- }
} else {
$hdr->type0 = 'multipart';
$hdr->type1 = $arg_a[0];
$hdr->language = (isset($arg_a[3]) ? $arg_a[3] : $hdr->language);
$msg->header = $hdr;
}
- ++$i;
- return (array($msg, $i));
+ return $msg;
default: break;
} /* switch */
-
} /* for */
} /* parsestructure */
function parseEnvelope($read, &$i, $hdr) {
$arg_no = 0;
$arg_a = array();
-
+ ++$i;
for ($cnt = strlen($read); ($i < $cnt) && ($read{$i} != ')'); ++$i) {
- ++$i;
$char = strtoupper($read{$i});
switch ($char) {
case '"':
break;
case '{':
$arg_a[] = $this->parseLiteral($read, $i);
+ /* temp bugfix (SM 1.5 will have a working clean version)
+ too much work to implement that version right now */
+// --$i;
++$arg_no;
break;
case 'N':
}
if (count($arg_a) > 9) {
- /* argument 1: date */
$d = strtr($arg_a[0], array(' ' => ' '));
$d = explode(' ', $d);
- $hdr->date = getTimeStamp($d);
-
- /* argument 2: subject */
- $arg_a[1] = (!trim($arg_a[1]) ? _("(no subject)") : $arg_a[1]);
- $hdr->subject = $arg_a[1];
+ if (!$arg_a[1]) $arg_1[1] = _("(no subject)");
+ $hdr->date = getTimeStamp($d); /* argument 1: date */
+ $hdr->subject = $arg_a[1]; /* argument 2: subject */
$hdr->from = $arg_a[2][0]; /* argument 3: from */
$hdr->sender = $arg_a[3][0]; /* argument 4: sender */
$hdr->replyto = $arg_a[4][0]; /* argument 5: reply-to */
function parseLiteral($read, &$i) {
$lit_cnt = '';
- for (++$i; $read{$i} != '}'; ++$i) {
- $lit_cnt .= $read{$i};
- }
-
- $lit_cnt +=2; /* add the { and } characters */
- $s = '';
- for ($j = 0; $j < $lit_cnt; ++$j) {
- $s .= $read{++$i};
- }
- return (array($s, $i));
+ ++$i;
+ $iPos = strpos($read,'}',$i);
+ if ($iPos) {
+ $lit_cnt = substr($read, $i, $iPos - $i);
+ $i += strlen($lit_cnt) + 3; /* skip } + \r + \n */
+ /* Now read the literal */
+ $s = ($lit_cnt ? substr($read,$i,$lit_cnt): '');
+ $i += $lit_cnt;
+ /* temp bugfix (SM 1.5 will have a working clean version)
+ too much work to implement that version right now */
+ --$i;
+ } else { /* should never happen */
+ $i += 3; /* } + \r + \n */
+ $s = '';
+ }
+ return $s;
}
function parseQuote($read, &$i) {
$s = '';
- for (++$i; $read{$i} != '"'; ++$i) {
- if ($read{$i} == '\\') {
- ++$i;
- }
- $s .= $read{$i};
- }
+ $iPos = ++$i;
+ while (true) {
+ $iPos = strpos($read,'"',$iPos);
+ if ($iPos === false) break;
+ if ($iPos && $read{$iPos -1} != '\\') {
+ $s = substr($read,$i,($iPos-$i));
+ $i = $iPos;
+ break;
+ }
+ }
return $s;
}
function parseAddress($read, &$i) {
$arg_a = array();
-
for (; $read{$i} != ')'; ++$i) {
$char = strtoupper($read{$i});
switch ($char) {
- case '"':
- case '{':
- $arg_a[] = ($char == '"' ? $this->parseQuote($read, $i) : $this->parseLiteral($read, $i));
- break;
+ case '"': $arg_a[] = $this->parseQuote($read, $i); break;
+ case '{': $arg_a[] = $this->parseLiteral($read, $i); break;
case 'n':
case 'N':
if (strtoupper(substr($read, $i, 3)) == 'NIL') {
}
} else { /* If not multipart, then just compare with each entry from $alt_order */
$type = $this->type0.'/'.$this->type1;
+// $alt_order[] = "message/rfc822";
foreach ($alt_order as $alt) {
if( ($alt == $type) && isset($this->entity_id) ) {
if ((count($this->entities) == 0) &&
$found = true;
}
}
+
}
if(!$strict && !$found) {
if (($this->type0 == 'text') &&
}
}
}
-
return $entity;
}
}
function getAttachments($exclude_id=array(), $result = array()) {
- if (($this->type0 == 'message') && ($this->type1 == 'rfc822')) {
+/*
+ if (($this->type0 == 'message') &&
+ ($this->type1 == 'rfc822') &&
+ ($this->entity_id) ) {
$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;
$result[] = $this;
}
}
-
return $result;
}