From a4f77800443173a73ff05a172ac6b0dd4d5e9a42 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 05 Mar 2010 07:57:58 -0500
Subject: [PATCH] - Fix check_recent action when skip_deleted=true (#1486535)

---
 program/include/rcube_imap.php |  363 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 210 insertions(+), 153 deletions(-)

diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 9ca1167..66e6fa7 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -56,7 +56,6 @@
   var $default_charset = 'ISO-8859-1';
   var $struct_charset = NULL;
   var $default_folders = array('INBOX');
-  var $default_folders_lc = array('inbox');
   var $fetch_add_headers = '';
   var $cache = array();
   var $cache_keys = array();  
@@ -105,14 +104,15 @@
     if ($use_ssl && extension_loaded('openssl'))
       $ICL_SSL = $use_ssl == 'imaps' ? 'ssl' : $use_ssl;
     else if ($use_ssl) {
-      raise_error(array('code' => 403, 'type' => 'imap', 'file' => __FILE__,
-                        'message' => 'Open SSL not available;'), TRUE, FALSE);
+      raise_error(array('code' => 403, 'type' => 'imap',
+        'file' => __FILE__, 'line' => __LINE__,
+        'message' => "Open SSL not available"), TRUE, FALSE);
       $port = 143;
     }
 
     $ICL_PORT = $port;
     $IMAP_USE_INTERNAL_DATE = false;
-    
+
     $attempt = 0;
     do {
       $data = rcmail::get_instance()->plugins->exec_hook('imap_connect', array('host' => $host, 'user' => $user, 'attempt' => ++$attempt));
@@ -136,21 +136,21 @@
     else if (!$this->conn && $GLOBALS['iil_error'])
       {
       $this->error_code = $GLOBALS['iil_errornum'];
-      raise_error(array('code' => 403,
-                       'type' => 'imap',
-                       'message' => $GLOBALS['iil_error']), TRUE, FALSE);
+      raise_error(array('code' => 403, 'type' => 'imap',
+        'file' => __FILE__, 'line' => __LINE__,
+        'message' => $GLOBALS['iil_error']), TRUE, FALSE);
       }
 
     // get server properties
     if ($this->conn)
       {
-      if (!empty($this->conn->delimiter))
-        $this->delimiter = $this->conn->delimiter;
       if (!empty($this->conn->rootdir))
         {
         $this->set_rootdir($this->conn->rootdir);
         $this->root_ns = preg_replace('/[.\/]$/', '', $this->conn->rootdir);
         }
+      if (empty($this->delimiter))
+	$this->get_hierarchy_delimiter();
       }
 
     return $this->conn ? TRUE : FALSE;
@@ -241,15 +241,10 @@
     if (is_array($arr))
       {
       $this->default_folders = $arr;
-      $this->default_folders_lc = array();
 
       // add inbox if not included
-      if (!in_array_nocase('INBOX', $this->default_folders))
+      if (!in_array('INBOX', $this->default_folders))
         array_unshift($this->default_folders, 'INBOX');
-
-      // create a second list with lower cased names
-      foreach ($this->default_folders as $mbox)
-        $this->default_folders_lc[] = strtolower($mbox);
       }
     }
 
@@ -414,7 +409,7 @@
       }
 
     // INBOX should always be available
-    if (!in_array_nocase('INBOX', $a_out))
+    if (!in_array('INBOX', $a_out))
       array_unshift($a_out, 'INBOX');
 
     // sort mailboxes
@@ -500,6 +495,9 @@
     if (!$force && is_array($a_mailbox_cache[$mailbox]) && isset($a_mailbox_cache[$mailbox][$mode]))
       return $a_mailbox_cache[$mailbox][$mode];
 
+    if (!is_array($a_mailbox_cache[$mailbox]))
+      $a_mailbox_cache[$mailbox] = array();
+
     // RECENT count is fetched a bit different
     if ($mode == 'RECENT')
        $count = iil_C_CheckForRecent($this->conn, $mailbox);
@@ -517,18 +515,19 @@
       // not very performant but more precise (using UNDELETED)
       $index = $this->_search_index($mailbox, $search_str);
       $count = is_array($index) ? count($index) : 0;
+
+      if ($mode == 'ALL')
+        $_SESSION['maxuid'][$mailbox] = $index ? $this->_id2uid(max($index)) : 0;
       }
-    else
-      {
+    else {
       if ($mode == 'UNSEEN')
         $count = iil_C_CountUnseen($this->conn, $mailbox);
-      else
+      else {
         $count = iil_C_CountMessages($this->conn, $mailbox);
+        $_SESSION['maxuid'][$mailbox] = $count ? $this->_id2uid($count) : 0;
       }
+    }
 
-    if (!is_array($a_mailbox_cache[$mailbox]))
-      $a_mailbox_cache[$mailbox] = array();
-      
     $a_mailbox_cache[$mailbox][$mode] = (int)$count;
 
     // write back to cache
@@ -603,21 +602,25 @@
       {
         if ($this->skip_deleted) {
           // @TODO: this could be cached
-	  $msg_index = $this->_search_index($mailbox, 'ALL UNDELETED');
-          $max = max($msg_index);
-          list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
-          $msg_index = array_slice($msg_index, $begin, $end-$begin);
-	} else if ($max = iil_C_CountMessages($this->conn, $mailbox)) {
+          if ($msg_index = $this->_search_index($mailbox, 'ALL UNDELETED')) {
+            $max = max($msg_index);
+            list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
+            $msg_index = array_slice($msg_index, $begin, $end-$begin);
+          }
+        }
+        else if ($max = iil_C_CountMessages($this->conn, $mailbox)) {
           list($begin, $end) = $this->_get_message_range($max, $page);
-	  $msg_index = range($begin+1, $end);
-	} else
-	  return array();
+          $msg_index = range($begin+1, $end);
+        }
+        else
+          $msg_index = array();
 
         if ($slice)
           $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice);
 
         // fetch reqested headers from server
-        $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key);
+        if ($msg_index)
+          $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key);
       }
     // use SORT command
     else if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, $this->skip_deleted ? 'UNDELETED' : '')))
@@ -633,13 +636,8 @@
       $this->_fetch_headers($mailbox, join(',', $msg_index), $a_msg_headers, $cache_key);
       }
     // fetch specified header for all messages and sort
-    else
+    else if ($a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", $this->sort_field, $this->skip_deleted))
       {
-      $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", $this->sort_field, $this->skip_deleted);
-
-      if (empty($a_index))
-        return array();
-
       asort($a_index); // ASC
       $msg_index = array_keys($a_index);
       $max = max($msg_index);
@@ -756,12 +754,12 @@
       // 300: experimantal value for best result
       if (($cnt > 300 && $cnt > $this->page_size) || ($this->index_sort && $this->sort_field == 'date')) {
         // use memory less expensive (and quick) method for big result set
-	$a_index = $this->message_index('', $this->sort_field, $this->sort_order);
+        $a_index = $this->message_index('', $this->sort_field, $this->sort_order);
         // get messages uids for one page...
         $msgs = array_slice($a_index, $start_msg, min($cnt-$start_msg, $this->page_size));
         if ($slice)
           $msgs = array_slice($msgs, -$slice, $slice);
-	// ...and fetch headers
+        // ...and fetch headers
         $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL);
 
         // return empty array if no messages found
@@ -773,7 +771,7 @@
         $sorter->sort_headers($a_msg_headers);
 
         return array_values($a_msg_headers);
-        }
+      }
       else {
         // for small result set we can fetch all messages headers
         $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL);
@@ -784,9 +782,9 @@
 
         // if not already sorted
         $a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order);
-      
+
         // only return the requested part of the set
-	$a_msg_headers = array_slice(array_values($a_msg_headers), $start_msg, min($cnt-$start_msg, $this->page_size));
+        $a_msg_headers = array_slice(array_values($a_msg_headers), $start_msg, min($cnt-$start_msg, $this->page_size));
         if ($slice)
           $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice);
 
@@ -855,15 +853,15 @@
 
       foreach ($a_header_index as $i => $headers) {
         if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) {
-	  // prevent index duplicates
-	  if ($cache_index[$headers->id]) {
-	    $this->remove_message_cache($cache_key, $headers->id, true);
-	    unset($cache_index[$headers->id]);
-	    }
+          // prevent index duplicates
+          if ($cache_index[$headers->id]) {
+            $this->remove_message_cache($cache_key, $headers->id, true);
+            unset($cache_index[$headers->id]);
+          }
           // add message to cache
-	  $this->add_message_cache($cache_key, $headers->id, $headers, NULL,
-	    !in_array($headers->uid, $cache_index));
-	  }
+          $this->add_message_cache($cache_key, $headers->id, $headers, NULL,
+            !in_array($headers->uid, $cache_index));
+        }
 
         $a_msg_headers[$headers->uid] = $headers;
         }
@@ -871,7 +869,31 @@
 
     return count($a_msg_headers);
     }
+  
+  /**
+   * Fetches IDS of pseudo recent messages.
+   *
+   * We compare the maximum UID to determine the number of
+   * new messages because the RECENT flag is not reliable.
+   *
+   * @param string  Mailbox/folder name
+   * @return array  List of recent message UIDs
+   */
+  function recent_uids($mbox_name = null, $nofetch = false)
+  {
+    $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
+    $old_maxuid = intval($_SESSION['maxuid'][$mailbox]);
     
+    // refresh message count -> will update $_SESSION['maxuid'][$mailbox]
+    $this->_messagecount($mailbox, 'ALL', true);
+    
+    if ($_SESSION['maxuid'][$mailbox] > $old_maxuid) {
+      $maxuid = max(1, $old_maxuid+1);
+      return array_values((array)iil_C_FetchHeaderIndex($this->conn, $mailbox, "$maxuid:*", 'UID', $this->skip_deleted, true));
+    }
+    
+    return array();
+  }
   
   /**
    * Return sorted array of message IDs (not UIDs)
@@ -895,20 +917,20 @@
       
       // use message index sort for sorting by Date
       if ($this->index_sort && $this->sort_field == 'date')
-        {
-	$msgs = $this->search_set;
-	
-	if ($this->search_sort_field != 'date')
-	  sort($msgs);
-	
+      {
+        $msgs = $this->search_set;
+
+        if ($this->search_sort_field != 'date')
+          sort($msgs);
+
         if ($this->sort_order == 'DESC')
           $this->cache[$key] = array_reverse($msgs);
         else
           $this->cache[$key] = $msgs;
-        }
+      }
       // sort with SORT command
       else if ($this->get_capability('sort'))
-        {
+      {
         if ($this->sort_field && $this->search_sort_field != $this->sort_field)
           $this->search('', $this->search_string, $this->search_charset, $this->sort_field);
 
@@ -916,9 +938,9 @@
           $this->cache[$key] = array_reverse($this->search_set);
         else
           $this->cache[$key] = $this->search_set;
-        }
+      }
       else
-        {
+      {
         $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, join(',', $this->search_set), $this->sort_field, $this->skip_deleted);
 
         if ($this->sort_order=="ASC")
@@ -927,7 +949,7 @@
           arsort($a_index);
 
         $this->cache[$key] = array_keys($a_index);
-	}
+      }
     }
 
     // have stored it in RAM
@@ -1015,11 +1037,11 @@
       // other message at this position
       if (isset($cache_index[$id]))
         {
-	$for_remove[] = $cache_index[$id];
+        $for_remove[] = $cache_index[$id];
         unset($cache_index[$id]);
         }
         
-	$for_update[] = $id;
+        $for_update[] = $id;
       }
 
     // clear messages at wrong positions and those deleted that are still in cache_index      
@@ -1034,7 +1056,7 @@
       if ($headers = iil_C_FetchHeader($this->conn, $mailbox, join(',', $for_update), false, $this->fetch_add_headers))
         foreach ($headers as $header)
           $this->add_message_cache($cache_key, $header->id, $header, NULL,
-		in_array($header->uid, (array)$for_remove));
+            in_array($header->uid, (array)$for_remove));
       }
     }
 
@@ -1061,28 +1083,28 @@
     // try search with US-ASCII charset (should be supported by server)
     // only if UTF-8 search is not supported
     if (empty($results) && !is_array($results) && !empty($charset) && $charset != 'US-ASCII')
+    {
+      // convert strings to US_ASCII
+      if(preg_match_all('/\{([0-9]+)\}\r\n/', $str, $matches, PREG_OFFSET_CAPTURE))
       {
-	// convert strings to US_ASCII
-        if(preg_match_all('/\{([0-9]+)\}\r\n/', $str, $matches, PREG_OFFSET_CAPTURE))
-	  {
-	  $last = 0; $res = '';
-	  foreach($matches[1] as $m)
-	    {
-	    $string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
-	    $string = substr($str, $string_offset - 1, $m[0]);
-	    $string = rcube_charset_convert($string, $charset, 'US-ASCII');
-	    if (!$string) continue;
-	    $res .= sprintf("%s{%d}\r\n%s", substr($str, $last, $m[1] - $last - 1), strlen($string), $string);
-	    $last = $m[0] + $string_offset - 1;
-	    }
-	    if ($last < strlen($str))
-	      $res .= substr($str, $last, strlen($str)-$last);
-	  }
-	else // strings for conversion not found
-	  $res = $str;
-	  
-	$results = $this->search($mbox_name, $res, NULL, $sort_field);
+        $last = 0; $res = '';
+        foreach($matches[1] as $m)
+        {
+          $string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
+          $string = substr($str, $string_offset - 1, $m[0]);
+          $string = rcube_charset_convert($string, $charset, 'US-ASCII');
+          if (!$string) continue;
+          $res .= sprintf("%s{%d}\r\n%s", substr($str, $last, $m[1] - $last - 1), strlen($string), $string);
+          $last = $m[0] + $string_offset - 1;
+        }
+        if ($last < strlen($str))
+          $res .= substr($str, $last, strlen($str)-$last);
       }
+      else // strings for conversion not found
+      $res = $str;
+
+      $results = $this->search($mbox_name, $res, NULL, $sort_field);
+    }
 
     $this->set_search_set($str, $results, $charset, $sort_field);
 
@@ -1226,17 +1248,15 @@
       else
         $this->struct_charset = $this->_structure_charset($structure);
 
-      /*
-        @TODO: here we can recognize malformed BODYSTRUCTURE and parse
-	the message in other way to create our own message structure.
-	Example of structure for malformed MIME message:
-	("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 2154 70 NIL NIL NIL)
-
-	if ($headers->ctype != 'text/plain'
-	  && !is_array($structure[0]) && $structure[0] == 'text' 
-	  && !is_array($structure[1]) && $structure[1] == 'plain') 
-	  { }
-      */
+      // Here we can recognize malformed BODYSTRUCTURE and 
+      // 1. [@TODO] parse the message in other way to create our own message structure
+      // 2. or just show the raw message body.
+      // Example of structure for malformed MIME message:
+      // ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 2154 70 NIL NIL NIL)
+      if ($headers->ctype && $headers->ctype != 'text/plain'
+          && $structure[0] == 'text' && $structure[1] == 'plain') {
+        return false;
+      }
 
       $struct = &$this->_structure_part($structure);
       $struct->headers = get_object_vars($headers);
@@ -1263,7 +1283,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";
@@ -1285,28 +1305,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]);
@@ -1367,18 +1402,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;
     }
@@ -1410,7 +1457,7 @@
       // some servers (eg. dovecot-1.x) have no support for parameter value continuations
       // we must fetch and parse headers "manually"
       if ($i<2) {
-	if (!$headers)
+        if (!$headers)
           $headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $part->mime_id);
         $filename_mime = '';
         $i = 0;
@@ -1427,7 +1474,7 @@
         $i++;
       }
       if ($i<2) {
-	if (!$headers)
+        if (!$headers)
           $headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $part->mime_id);
         $filename_encoded = '';
         $i = 0; $matches = array();
@@ -1444,7 +1491,7 @@
         $i++;
       }
       if ($i<2) {
-	if (!$headers)
+        if (!$headers)
           $headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $part->mime_id);
         $filename_mime = '';
         $i = 0; $matches = array();
@@ -1461,7 +1508,7 @@
         $i++;
       }
       if ($i<2) {
-	if (!$headers)
+        if (!$headers)
           $headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $part->mime_id);
         $filename_encoded = '';
         $i = 0; $matches = array();
@@ -1483,8 +1530,8 @@
     // decode filename
     if (!empty($filename_mime)) {
       $part->filename = rcube_imap::decode_mime_string($filename_mime, 
-        $part->charset ? $part->charset : $this->struct_charset ? $this->struct_charset :
-	    rc_detect_encoding($filename_mime, $this->default_charset));
+        $part->charset ? $part->charset : ($this->struct_charset ? $this->struct_charset :
+          rc_detect_encoding($filename_mime, $this->default_charset)));
       } 
     else if (!empty($filename_encoded)) {
       // decode filename according to RFC 2231, Section 4
@@ -1507,10 +1554,10 @@
   function _structure_charset($structure)
     {
       while (is_array($structure)) {
-	if (is_array($structure[2]) && $structure[2][0] == 'charset')
-	  return $structure[2][1];
-	$structure = $structure[0];
-	}
+        if (is_array($structure[2]) && $structure[2][0] == 'charset')
+          return $structure[2][1];
+        $structure = $structure[0];
+      }
     } 
 
 
@@ -1676,17 +1723,27 @@
   /**
    * Append a mail message (source) to a specific mailbox
    *
-   * @param string Target mailbox
-   * @param string Message source
+   * @param string   Target mailbox
+   * @param string   The message source string or filename
+   * @param string   Headers string if $message contains only the body
+   * @param boolean  True if $message is a filename
+   *
    * @return boolean True on success, False on error
    */
-  function save_message($mbox_name, &$message)
+  function save_message($mbox_name, &$message, $headers='', $is_file=false)
     {
     $mailbox = $this->mod_mailbox($mbox_name);
 
     // make sure mailbox exists
-    if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes()))
-      $saved = iil_C_Append($this->conn, $mailbox, $message);
+    if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes())) {
+      if ($is_file) {
+        $separator = rcmail::get_instance()->config->header_delimiter();
+        $saved = iil_C_AppendFromFile($this->conn, $mailbox, $message,
+          $headers, $separator.$separator);
+        }
+      else
+        $saved = iil_C_Append($this->conn, $mailbox, $message);
+      }
 
     if ($saved)
       {
@@ -1716,8 +1773,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;
       }
@@ -1739,7 +1796,7 @@
     // move messages
     $iil_move = iil_C_Move($this->conn, join(',', $a_uids), $from_mbox, $to_mbox);
     $moved = !($iil_move === false || $iil_move < 0);
-    
+
     // send expunge command in order to have the moved message
     // really deleted from the source mailbox
     if ($moved) {
@@ -1748,8 +1805,8 @@
       $this->_clear_messagecount($to_mbox);
     }
     // moving failed
-    else if (rcmail::get_instance()->config->get('delete_always', false)) {
-      return iil_C_Delete($this->conn, $from_mbox, join(',', $a_uids));
+    else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) {
+      return $this->delete_message($a_uids, $fbox);
     }
 
     // remove message ids from search set
@@ -2123,9 +2180,9 @@
     foreach ($this->default_folders as $folder)
       {
       $abs_name = $this->mod_mailbox($folder);
-      if (!in_array_nocase($abs_name, $a_folders))
+      if (!in_array($abs_name, $a_folders))
         $this->create_mailbox($folder, TRUE);
-      else if (!in_array_nocase($abs_name, $a_subscribed))
+      else if (!in_array($abs_name, $a_subscribed))
         $this->subscribe($folder);
       }
     }
@@ -2871,11 +2928,13 @@
     if ((!empty($this->root_ns) && $this->root_ns == $mbox_name) || $mbox_name == 'INBOX')
       return $mbox_name;
 
-    if (!empty($this->root_dir) && $mode=='in') 
-      $mbox_name = $this->root_dir.$this->delimiter.$mbox_name;
-    else if (strlen($this->root_dir) && $mode=='out') 
-      $mbox_name = substr($mbox_name, strlen($this->root_dir)+1);
-
+    if (!empty($this->root_dir)) {
+      if ($mode=='in')
+        $mbox_name = $this->root_dir.$this->delimiter.$mbox_name;
+      else if (!empty($mbox_name)) // $mode=='out'
+        $mbox_name = substr($mbox_name, strlen($this->root_dir)+1);
+      }
+    
     return $mbox_name;
     }
 
@@ -2912,7 +2971,7 @@
       if ($folder{0}=='.')
         continue;
 
-      if (($p = array_search(strtolower($folder), $this->default_folders_lc)) !== false && !$a_defaults[$p])
+      if (($p = array_search($folder, $this->default_folders)) !== false && !$a_defaults[$p])
         $a_defaults[$p] = $folder;
       else
         $folders[$folder] = mb_strtolower(rcube_charset_convert($folder, 'UTF7-IMAP'));
@@ -2976,15 +3035,12 @@
     {
     if (!$mbox_name)
       $mbox_name = $this->mailbox;
-      
-    $index = array_flip((array)$this->uid_id_map[$mbox_name]);
-    if (isset($index[$id]))
-      $uid = $index[$id];
-    else
-      {
-      $uid = iil_C_ID2UID($this->conn, $mbox_name, $id);
-      $this->uid_id_map[$mbox_name][$uid] = $id;
-      }
+
+    if ($uid = array_search($id, (array)$this->uid_id_map[$mbox_name]))
+      return $uid;
+
+    $uid = iil_C_ID2UID($this->conn, $mbox_name, $id);
+    $this->uid_id_map[$mbox_name][$uid] = $id;
     
     return $uid;
     }
@@ -3086,6 +3142,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