/**
* Message.class.php
*
- * Copyright (c) 2003 The SquirrelMail Project Team
+ * Copyright (c) 2003-2005 The SquirrelMail Project Team
* Licensed under the GNU GPL. For full terms see the file COPYING.
*
* This contains functions needed to handle mime messages.
*
- * $Id$
+ * @version $Id$
+ * @package squirrelmail
*/
+/**
+ * The object that contains a 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.
+ * @package squirrelmail
+ */
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 $rfc822_header = '',
$mime_header = '',
$flags = '',
$type0='',
$type1='',
$entities = array(),
- $entity_id = '',
+ $entity_id = '',
$parent_ent, $entity,
$parent = '', $decoded_body='',
$is_seen = 0, $is_answered = 0, $is_deleted = 0, $is_flagged = 0,
$body_part = '',
$offset = 0, /* for fetching body parts out of raw messages */
$length = 0, /* for fetching body parts out of raw messages */
- $att_local_name = ''; /* location where the tempory attachment
- is stored. For future usage in smtp.php */
+ $att_local_name = ''; /* location where the tempory attachment
+ is stored. For future usage in smtp.php */
function setEnt($ent) {
$this->entity_id= $ent;
}
function getFilename() {
- $filename = '';
- $filename = $this->header->getParameter('filename');
- if (!$filename) {
- $filename = $this->header->getParameter('name');
- }
-
- if (!$filename) {
- $filename = 'untitled-'.$this->entity_id;
- }
- return $filename;
+ $filename = '';
+ $header = $this->header;
+ if (is_object($header->disposition)) {
+ $filename = $header->disposition->getProperty('filename');
+ if (trim($filename) == '') {
+ $name = decodeHeader($header->disposition->getProperty('name'));
+ if (!trim($name)) {
+ $name = $header->getParameter('name');
+ if(!trim($name)) {
+ if (!trim( $header->id )) {
+ $filename = 'untitled-[' . $this->entity_id . ']' ;
+ } else {
+ $filename = 'cid: ' . $header->id;
+ }
+ } else {
+ $filename = $name;
+ }
+ } else {
+ $filename = $name;
+ }
+ }
+ } else {
+ $filename = $header->getParameter('filename');
+ if (!trim($filename)) {
+ $filename = $header->getParameter('name');
+ if (!trim($filename)) {
+ if (!trim( $header->id )) {
+ $filename = 'untitled-[' . $this->entity_id . ']' ;
+ } else {
+ $filename = 'cid: ' . $header->id;
+ }
+ }
+ }
+ }
+ return $filename;
}
$cur_ent_a = explode('.', $this->entity_id);
}
$ent_a = explode('.', $ent);
-
+
for ($i = 0,$entCount = count($ent_a) - 1; $i < $entCount; ++$i) {
if (isset($cur_ent_a[$i]) && ($cur_ent_a[$i] != $ent_a[$i])) {
$msg = $msg->parent;
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';
- }
+ 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);
- }
-
- }
+ $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;
+ if ($sub_msg) {
+ $message = $sub_msg;
+ } else {
+ $message = new Message();
+ }
+
for ($cnt = strlen($read); $i < $cnt; ++$i) {
$char = strtoupper($read{$i});
switch ($char) {
$msg->header->type0 = 'multipart';
$msg->type0 = 'multipart';
while ($read{$i} == '(') {
- $msg->addEntity($this->parseBodyStructure($read, $i, $msg));
+ $msg->addEntity($msg->parseBodyStructure($read, $i, $msg));
}
}
break;
case 1:
/* multipart properties */
++$i;
- $arg_a[] = $this->parseProperties($read, $i);
+ $arg_a[] = $msg->parseProperties($read, $i);
++$arg_no;
break;
case 2:
if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
++$i;
- $arg_a[] = $this->parseDisposition($read, $i);
+ $arg_a[] = $msg->parseDisposition($read, $i);
} else { /* properties */
- $arg_a[] = $this->parseProperties($read, $i);
+ $arg_a[] = $msg->parseProperties($read, $i);
}
++$arg_no;
break;
case 3:
if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
++$i;
- $arg_a[]= $this->parseLanguage($read, $i);
+ $arg_a[]= $msg->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 = $this->parseEnvelope($read, $i, $rfc822_hdr);
+ $msg->rfc822_header = $msg->parseEnvelope($read, $i, $rfc822_hdr);
while (($i < $cnt) && ($read{$i} != '(')) {
++$i;
}
- $msg->addEntity($this->parseBodyStructure($read, $i,$msg));
+ $msg->addEntity($msg->parseBodyStructure($read, $i,$msg));
}
break;
case 8:
++$i;
- $arg_a[] = $this->parseDisposition($read, $i);
+ $arg_a[] = $msg->parseDisposition($read, $i);
++$arg_no;
break;
case 9:
++$i;
if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
- $arg_a[] = $this->parseDisposition($read, $i);
+ $arg_a[] = $msg->parseDisposition($read, $i);
} else {
- $arg_a[] = $this->parseLanguage($read, $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[] = $this->parseLanguage($read, $i);
+ $arg_a[] = $msg->parseLanguage($read, $i);
} else {
- $i = $this->parseParenthesis($read, $i);
+ $i = $msg->parseParenthesis($read, $i);
$arg_a[] = ''; /* not yet described in rfc2060 */
}
++$arg_no;
break;
default:
/* unknown argument, skip this part */
- $i = $this->parseParenthesis($read, $i);
+ $i = $msg->parseParenthesis($read, $i);
$arg_a[] = '';
++$arg_no;
break;
break;
case '"':
/* inside an entity -> start processing */
- $arg_s = $this->parseQuote($read, $i);
+ $arg_s = $msg->parseQuote($read, $i);
++$arg_no;
if ($arg_no < 3) {
$arg_s = strtolower($arg_s); /* type0 and type1 */
break;
case '{':
/* process the literal value */
- $arg_s = $this->parseLiteral($read, $i);
+ $arg_a[] = $msg->parseLiteral($read, $i);
++$arg_no;
break;
- case '0':
+ case '0':
case is_numeric($read{$i}):
/* process integers */
if ($read{$i} == ' ') { break; }
- ++$arg_no;
- if (preg_match('/^([0-9]+).*/',substr($read,$i), $regs)) {
- $i += strlen($regs[1])-1;
- $arg_a[] = $regs[1];
- } else {
- $arg_a[] = 0;
- }
+ ++$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'));
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;
+ /* 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) {
$d = strtr($arg_a[0], array(' ' => ' '));
$d = explode(' ', $d);
- if (!$arg_a[1]) $arg_1[1] = _("(no subject)");
+ if (!$arg_a[1]) $arg_a[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 */
+ $hdr->from = is_array($arg_a[2]) ? $arg_a[2][0] : ''; /* argument 3: from */
+ $hdr->sender = is_array($arg_a[3]) ? $arg_a[3][0] : ''; /* argument 4: sender */
+ $hdr->replyto = is_array($arg_a[4]) ? $arg_a[4][0] : ''; /* argument 5: reply-to */
$hdr->to = $arg_a[5]; /* argument 6: to */
$hdr->cc = $arg_a[6]; /* argument 7: cc */
$hdr->bcc = $arg_a[7]; /* argument 8: bcc */
function parseLiteral($read, &$i) {
$lit_cnt = '';
- ++$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;
- } else { /* should never happen */
- $i += 3; /* } + \r + \n */
- $s = '';
- }
+ ++$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 = '';
- $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;
- }
- }
+ $iPos = ++$i;
+ while (true) {
+ $iPos = strpos($read,'"',$iPos);
+ if (!$iPos) break;
+ if ($iPos && $read{$iPos -1} != '\\') {
+ $s = substr($read,$i,($iPos-$i));
+ $i = $iPos;
+ break;
+ }
+ ++$iPos;
+ if ($iPos > strlen($read)) {
+ break;
+ }
+ }
return $s;
}
} else { /* Treat as multipart/mixed */
foreach ($this->entities as $ent) {
if((strtolower($ent->header->disposition->name) != 'attachment') &&
+ (!isset($ent->header->parameters['filename'])) &&
+ (!isset($ent->header->parameters['name'])) &&
(($ent->type0 != 'message') && ($ent->type1 != 'rfc822'))) {
$entity = $ent->findDisplayEntity($entity, $alt_order, $strict);
$found = true;
}
} else { /* If not multipart, then just compare with each entry from $alt_order */
$type = $this->type0.'/'.$this->type1;
-// $alt_order[] = "message/rfc822";
+// $alt_order[] = "message/rfc822";
foreach ($alt_order as $alt) {
if( ($alt == $type) && isset($this->entity_id) ) {
- if ((count($this->entities) == 0) &&
+ if ((count($this->entities) == 0) &&
+ (!isset($ent->header->parameters['filename'])) &&
+ (!isset($ent->header->parameters['name'])) &&
(strtolower($this->header->disposition->name) != 'attachment')) {
$entity[] = $this->entity_id;
$found = true;
$found = true;
}
}
-
}
if(!$strict && !$found) {
if (($this->type0 == 'text') &&
$type = $ent->header->type0 . '/' . $ent->header->type1;
if ($type == 'multipart/related') {
$type = $ent->header->getParameter('type');
+ // Mozilla bug. Mozilla does not provide the parameter type.
+ if (!$type) $type = 'text/html';
}
$altCount = count($alt_order);
for ($j = $best_view; $j < $altCount; ++$j) {
function findRelatedEntity() {
$msgs = array();
-
+ $related_type = $this->header->getParameter('type');
+ // Mozilla bug. Mozilla does not provide the parameter type.
+ if (!$related_type) $related_type = 'text/html';
$entCount = count($this->entities);
for ($i = 0; $i < $entCount; ++$i) {
$type = $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1;
- if ($this->header->getParameter('type') == $type) {
+ if ($related_type == $type) {
$msgs[] = $this->entities[$i];
}
}
-
return $msgs;
}
function getAttachments($exclude_id=array(), $result = array()) {
/*
- if (($this->type0 == 'message') &&
- ($this->type1 == 'rfc822') &&
- ($this->entity_id) ) {
+ if (($this->type0 == 'message') &&
+ ($this->type1 == 'rfc822') &&
+ ($this->entity_id) ) {
$this = $this->entities[0];
}
*/
}
return $result;
}
-
+
function initAttachment($type, $name, $location) {
$attachment = new Message();
$mime_header = new MessageHeader();
$mime_header->setParameter('name', $name);
- $pos = strpos($type, '/');
- if ($pos > 0) {
- $mime_header->type0 = substr($type, 0, $pos);
- $mime_header->type1 = substr($type, $pos+1);
- } else {
- $mime_header->type0 = $type;
- }
- $attachment->att_local_name = $location;
- $disposition = new Disposition('attachment');
- $disposition->properties['filename'] = $name;
- $mime_header->disposition = $disposition;
- $attachment->mime_header = $mime_header;
- $this->entities[]=$attachment;
+ $pos = strpos($type, '/');
+ if ($pos > 0) {
+ $mime_header->type0 = substr($type, 0, $pos);
+ $mime_header->type1 = substr($type, $pos+1);
+ } else {
+ $mime_header->type0 = $type;
+ }
+ $attachment->att_local_name = $location;
+ $disposition = new Disposition('attachment');
+ $disposition->properties['filename'] = $name;
+ $mime_header->disposition = $disposition;
+ $attachment->mime_header = $mime_header;
+ $this->entities[]=$attachment;
}
}
-?>
+?>
\ No newline at end of file