fixes for r12283: mistakenly passed already-split date to date_unparsed,
[squirrelmail.git] / class / mime / Message.class.php
index 2d54b359de051da99f1b6f9d8c9bf18b6ee4d68f..8677c92b971d02bb6e257d295f3a428567c8eb95 100644 (file)
@@ -5,7 +5,7 @@
  *
  * This file contains functions needed to handle mime messages.
  *
- * @copyright © 2003-2005 The SquirrelMail Project Team
+ * @copyright © 2003-2007 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
  */
 
 /**
- * The object that contains a message
+ * 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.
+ * 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
  * @subpackage mime
  * @since 1.3.0
@@ -119,9 +119,8 @@ class Message {
      */
     var $length = 0;
     /**
-     * Local attachment filename
-     * location where the tempory attachment
-     * is stored. For use in delivery class.
+     * Local attachment filename location where the tempory attachment is
+     * stored. For use in delivery class.
      * @var string
      */
     var $att_local_name = '';
@@ -615,18 +614,19 @@ class Message {
 
         if (count($arg_a) > 9) {
             $d = strtr($arg_a[0], array('  ' => ' '));
-            $d = explode(' ', $d);
-        if (!$arg_a[1]) $arg_a[1] = _("(no subject)");
+            $d_parts = explode(' ', $d);
+            if (!$arg_a[1]) $arg_a[1] = _("(no subject)");
 
-            $hdr->date = getTimeStamp($d); /* argument 1: date */
+            $hdr->date = getTimeStamp($d_parts); /* argument 1: date */
+            $hdr->date_unparsed = strtr($d,'<>','  '); /* original date */
             $hdr->subject = $arg_a[1];     /* argument 2: subject */
             $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->reply_to = 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         */
-            $hdr->inreplyto = $arg_a[8];   /* argument 9: in-reply-to */
+            $hdr->in_reply_to = $arg_a[8];   /* argument 9: in-reply-to */
             $hdr->message_id = $arg_a[9];  /* argument 10: message-id */
         }
         return $hdr;
@@ -659,14 +659,25 @@ class Message {
     }
 
     /**
+     * function parseQuote
+     *
+     * This extract the string value from a quoted string. After the end-quote
+     * character is found it returns the string. The offset $i when calling
+     * this function points to the first double quote. At the end it points to
+     * The ending quote. This function takes care of escaped double quotes.
+     * "some \"string\""
+     * ^               ^
+     * initial $i      end position $i
+     *
      * @param string $read
-     * @param integer $i
-     * @return string
-     * @todo document me
+     * @param integer $i offset in $read
+     * @return string string inbetween the double quotes
+     * @author Marc Groot Koerkamp
      */
     function parseQuote($read, &$i) {
         $s = '';
         $iPos = ++$i;
+        $iPosStart = $iPos;
         while (true) {
             $iPos = strpos($read,'"',$iPos);
             if (!$iPos) break;
@@ -674,6 +685,38 @@ class Message {
                 $s = substr($read,$i,($iPos-$i));
                 $i = $iPos;
                 break;
+            } else if ($iPos > 1 && $read{$iPos -1} == '\\' && $read{$iPos-2} == '\\') {
+                // This is an unique situation where the fast detection of the string
+                // fails. If the quote string ends with \\ then we need to iterate
+                // through the entire string to make sure we detect the unexcaped
+                // double quotes correctly.
+                $s = '';
+                $bEscaped = false;
+                $k = 0;
+                 for ($j=$iPosStart,$iCnt=strlen($read);$j<$iCnt;++$j) {
+                    $cChar = $read{$j};
+                    switch ($cChar) {
+                        case '\\':
+                           $bEscaped = !$bEscaped;
+                            $s .= $cChar;
+                            break;
+                         case '"':
+                            if ($bEscaped) {
+                                $s .= $cChar;
+                                $bEscaped = false;
+                            } else {
+                                $i = $j;
+                                break 3;
+                            }
+                            break;
+                         default:
+                            if ($bEscaped) {
+                               $bEscaped = false;
+                            }
+                            $s .= $cChar;
+                            break;
+                    }
+                }
             }
             ++$iPos;
             if ($iPos > strlen($read)) {
@@ -896,9 +939,9 @@ class Message {
             } else { /* Treat as multipart/mixed */
                 foreach ($this->entities as $ent) {
                     if(!(is_object($ent->header->disposition) && strtolower($ent->header->disposition->name) == 'attachment') &&
-                (!isset($ent->header->parameters['filename'])) &&
-                (!isset($ent->header->parameters['name'])) &&
-                       (($ent->type0 != 'message') && ($ent->type1 != 'rfc822'))) {
+                            (!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;
                     }
@@ -910,10 +953,10 @@ class Message {
             foreach ($alt_order as $alt) {
                 if( ($alt == $type) && isset($this->entity_id) ) {
                     if ((count($this->entities) == 0) &&
-                (!isset($this->header->parameters['filename'])) &&
-                (!isset($this->header->parameters['name'])) &&
-                isset($this->header->disposition) && is_object($this->header->disposition) &&
-                        !(is_object($this->header->disposition) && strtolower($this->header->disposition->name) == 'attachment')) {
+                            (!isset($this->header->parameters['filename'])) &&
+                            (!isset($this->header->parameters['name'])) &&
+                            isset($this->header->disposition) && is_object($this->header->disposition) &&
+                            !(is_object($this->header->disposition) && strtolower($this->header->disposition->name) == 'attachment')) {
                         $entity[] = $this->entity_id;
                         $found = true;
                     }
@@ -1057,6 +1100,18 @@ class Message {
         $attachment->mime_header = $mime_header;
         $this->entities[]=$attachment;
     }
-}
 
-?>
\ No newline at end of file
+    /**
+     * Delete all attachments from this object from disk.
+     * @since 1.5.1
+     */
+    function purgeAttachments() {
+        if ($this->att_local_name && file_exists($this->att_local_name)) {
+            unlink($this->att_local_name);
+        }
+        // recursively delete attachments from entities contained in this object
+        for ($i=0, $entCount=count($this->entities);$i< $entCount; ++$i) {
+            $this->entities[$i]->purgeAttachments();
+        }
+    }
+}