From aa16b4af8f67d91b1bfd2c584a665a53c403f47c Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Wed, 23 Dec 2009 03:01:39 -0500
Subject: [PATCH] - Improved handling of message parts of type message/rfc822 (fixed e.g. inline images in multipart/alternative messages attached as message/rfc822)

---
 program/include/rcube_imap.php |   72 +++++++++++++++++++++++++-----------
 1 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 31156e4..2408fa2 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -1258,7 +1258,7 @@
    *
    * @access private
    */
-  function &_structure_part($part, $count=0, $parent='', $raw_headers=null)
+  function &_structure_part($part, $count=0, $parent='', $mime_headers=null, $raw_headers=null)
     {
     $struct = new rcube_message_part;
     $struct->mime_id = empty($parent) ? (string)$count : "$parent.$count";
@@ -1280,28 +1280,43 @@
 
       // build parts list for headers pre-fetching
       for ($i=0, $count=0; $i<count($part); $i++)
-        if (is_array($part[$i]) && count($part[$i]) > 3)
-	  // fetch message headers if message/rfc822 or named part (could contain Content-Location header)
-	  if (strtolower($part[$i][0]) == 'message' ||
-	    (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL'))) {
-	    $part_headers[] = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1;
-	    }
-
+        if (is_array($part[$i]) && count($part[$i]) > 3) {
+          // fetch message headers if message/rfc822 or named part (could contain Content-Location header)
+	  if (!is_array($part[$i][0])) {
+            $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1;
+            if (strtolower($part[$i][0]) == 'message' && strtolower($part[$i][1]) == 'rfc822') {
+	      $raw_part_headers[] = $tmp_part_id;
+	      $mime_part_headers[] = $tmp_part_id;
+              }
+            else if (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL')) {
+	      $mime_part_headers[] = $tmp_part_id;
+	      }
+            }
+          }
+        
       // pre-fetch headers of all parts (in one command for better performance)
-      if ($part_headers)
-        $part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, $part_headers);
+      // @TODO: we could do this before _structure_part() call, to fetch
+      // headers for parts on all levels
+      if ($mime_part_headers)
+        $mime_part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox,
+          $this->_msg_id, $mime_part_headers);
+      // we'll need a real content-type of message/rfc822 part
+      if ($raw_part_headers)
+        $raw_part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox,
+          $this->_msg_id, $raw_part_headers, false);
 
       $struct->parts = array();
       for ($i=0, $count=0; $i<count($part); $i++)
         if (is_array($part[$i]) && count($part[$i]) > 3) {
+          $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1;
           $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id,
-		$part_headers[$struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1]);
+	    $mime_part_headers[$tmp_part_id], $raw_part_headers[$tmp_part_id]);
 	}
 
       return $struct;
       }
-    
-    
+
+
     // regular part
     $struct->ctype_primary = strtolower($part[0]);
     $struct->ctype_secondary = strtolower($part[1]);
@@ -1362,18 +1377,30 @@
     
     // fetch message headers if message/rfc822 or named part (could contain Content-Location header)
     if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) {
-      if (empty($raw_headers))
-        $raw_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $struct->mime_id);
-      $struct->headers = $this->_parse_headers($raw_headers) + $struct->headers;
-    }
+      if (empty($mime_headers))
+        $mime_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $struct->mime_id);
+      $struct->headers = $this->_parse_headers($mime_headers) + $struct->headers;
+
+      // get real headers for message of type 'message/rfc822'
+      if ($struct->mimetype == 'message/rfc822') {
+        if (empty($raw_headers))
+          $raw_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, (array)$struct->mime_id, false);
+        $struct->real_headers = $this->_parse_headers($raw_headers);
+
+        // get real content-type of message/rfc822
+        if (preg_match('/^([a-z0-9_\/-]+)/i', $struct->real_headers['content-type'], $matches)) {
+          $struct->real_mimetype = strtolower($matches[1]);
+          }                                                    
+        }
+      }
 
     if ($struct->ctype_primary=='message') {
-      if (is_array($part[8]) && empty($struct->parts))
+      if (is_array($part[8]) && $di != 8 && empty($struct->parts))
         $struct->parts[] = $this->_structure_part($part[8], ++$count, $struct->mime_id);
-    }
+      }
 
     // normalize filename property
-    $this->_set_part_filename($struct, $raw_headers);
+    $this->_set_part_filename($struct, $mime_headers);
 
     return $struct;
     }
@@ -1711,8 +1738,8 @@
     // make sure mailbox exists
     if ($to_mbox != 'INBOX' && !in_array($to_mbox, $this->_list_mailboxes()))
       {
-      if (in_array($to_mbox_in, $this->default_folders))
-        $this->create_mailbox($to_mbox_in, TRUE);
+      if (in_array($tbox, $this->default_folders))
+        $this->create_mailbox($tbox, TRUE);
       else
         return FALSE;
       }
@@ -3081,6 +3108,7 @@
   private function _parse_headers($headers)
     {
     $a_headers = array();
+    $headers = preg_replace('/\r?\n(\t| )+/', ' ', $headers);
     $lines = explode("\n", $headers);
     $c = count($lines);
     for ($i=0; $i<$c; $i++)

--
Gitblit v1.9.1