Adding a comment with an explanation for translators.
[squirrelmail.git] / class / mime / Message.class.php
index 68beb9dba846bf2c65dbcca628e8445e4a078ff4..f05abf4b76f78b5a894a63b7658f5ec8df1654a0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * This file contains functions needed to handle mime messages.
  *
- * @copyright © 2003-2006 The SquirrelMail Project Team
+ * @copyright © 2003-2009 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -86,6 +86,11 @@ class Message {
      * @var boolean
      */
     var $is_answered = 0;
+    /**
+     * Message forward status
+     * @var boolean
+     */
+    var $is_forwarded = 0;
     /**
      * Message \deleted status
      * @var boolean
@@ -357,7 +362,7 @@ class Message {
                                 $hdr = new MessageHeader();
                                 $hdr->type0 = 'text';
                                 $hdr->type1 = 'plain';
-                                $hdr->encoding = 'us-ascii';
+                                $hdr->encoding = '7bit';
                             } else {
                                 $msg->header->type0 = 'multipart';
                                 $msg->type0 = 'multipart';
@@ -539,6 +544,70 @@ class Message {
                 }
             }
         }
+        return $this->handleRfc2231($properties);
+    }
+
+    /**
+     * Joins RFC-2231 continuations, converts encoding to RFC-2047 style
+     * @param array $properties
+     * @return array
+     */
+    function handleRfc2231($properties) {
+
+        /* STAGE 1: look for multi-line parameters, convert to the single line
+           form, and normalize values */
+
+        $cont = array();
+        foreach($properties as $key=>$value) {
+            /* Look for parameters followed by "*", a number, and an optional "*"
+               at the end. */
+            if (preg_match('/^(.*\*)(\d+)(|\*)$/', $key, $matches)) {
+                unset($properties[$key]);
+                $prop_name = $matches[1];
+                if (!isset($cont[$prop_name])) $cont[$prop_name] = array();
+
+                /* An asterisk at the end of parameter name indicates that there
+                   may be an encoding information present, and the parameter
+                   value is percent-hex encoded. If parameter is not encoded, we
+                   encode it to simplify further processing.
+                */
+                if ($matches[3] == '') $value = rawurlencode($value);
+                /* Use the number from parameter name as segment index */
+                $cont[$prop_name][$matches[2]] = $value;
+            }
+        }
+        foreach($cont as $key=>$values) {
+            /* Sort segments of multi-line parameters by index number. */
+            ksort($values);
+            /* Join segments. We can do it safely, because:
+               - All segments are encoded.
+               - Per RFC-2231, chapter 4.1 notes.
+            */
+            $value = implode('', $values);
+            /* Add language and character set field delimiters if not present,
+               as required per RFC-2231, chapter 4.1, note #5. */
+            if (strpos($value, "'") === false) $value = "''".$value;
+            $properties[$key] = $value;
+        }
+
+        /* STAGE 2: Convert single line RFC-2231 encoded parameters, and
+           previously converted multi-line parameters, to RFC-2047 encoding */
+
+        foreach($properties as $key=>$value) {
+            if ($idx = strpos($key, '*')) {
+                unset($properties[$key]);
+                /* Extract the charset & language. */
+                $charset = substr($value,0,strpos($value,"'"));
+                $value = substr($value,strlen($charset)+1);
+                $language = substr($value,0,strpos($value,"'"));
+                $value = substr($value,strlen($language)+1);
+                /* No character set defaults to US-ASCII */
+                if (!$charset) $charset = 'US-ASCII';
+                if ($language) $language = '*'.$language;
+                /* Convert to RFC-2047 base64 encoded string. */
+                $properties[substr($key, 0, $idx)] = '=?'.$charset.$language.'?B?'.base64_encode(rawurldecode($value)).'?=';
+            }
+        }
         return $properties;
     }
 
@@ -614,18 +683,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;
@@ -819,7 +889,7 @@ class Message {
      * @return integer
      */
     function parseParenthesis($read, $i) {
-        for (; $read{$i} != ')'; ++$i) {
+        for ($i++; $read{$i} != ')'; ++$i) {
             switch ($read{$i}) {
                 case '"': $this->parseQuote($read, $i); break;
                 case '{': $this->parseLiteral($read, $i); break;
@@ -1105,8 +1175,12 @@ class Message {
      * @since 1.5.1
      */
     function purgeAttachments() {
-        if ($this->att_local_name && file_exists($this->att_local_name)) {
-            unlink($this->att_local_name);
+        if ($this->att_local_name) {
+            global $username, $attachment_dir;
+            $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
+            if ( file_exists($hashed_attachment_dir . '/' . $this->att_local_name) ) {
+                unlink($hashed_attachment_dir . '/' . $this->att_local_name);
+            }
         }
         // recursively delete attachments from entities contained in this object
         for ($i=0, $entCount=count($this->entities);$i< $entCount; ++$i) {