From 4a63f1efaff83dd03e663ed1a432a15dc0100be3 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Mon, 07 Sep 2009 03:53:01 -0400
Subject: [PATCH] - Fix roundcube hangs on empty inbox with bincimapd (#1486093)

---
 program/include/rcube_imap.php |   87 ++++++++++++++++++++++++-------------------
 1 files changed, 49 insertions(+), 38 deletions(-)

diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index c823834..f172931 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -36,7 +36,7 @@
  *
  * @package    Mail
  * @author     Thomas Bruederli <roundcube@gmail.com>
- * @version    1.40
+ * @version    1.5
  * @link       http://ilohamail.org
  */
 class rcube_imap
@@ -70,6 +70,8 @@
   var $debug_level = 1;
   var $error_code = 0;
   var $options = array('imap' => 'check');
+  
+  private $host, $user, $pass, $port, $ssl;
 
 
   /**
@@ -101,19 +103,26 @@
     // check for Open-SSL support in PHP build
     if ($use_ssl && extension_loaded('openssl'))
       $ICL_SSL = $use_ssl == 'imaps' ? 'ssl' : $use_ssl;
-    else if ($use_ssl)
-      {
+    else if ($use_ssl) {
       raise_error(array('code' => 403, 'type' => 'imap', 'file' => __FILE__,
                         '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));
+      if (!empty($data['pass']))
+        $pass = $data['pass'];
 
-    $this->conn = iil_Connect($host, $user, $pass, $this->options);
-    $this->host = $host;
-    $this->user = $user;
+      $this->conn = iil_Connect($data['host'], $data['user'], $pass, $this->options);
+    } while(!$this->conn && $data['retry']);
+
+    $this->host = $data['host'];
+    $this->user = $data['user'];
     $this->pass = $pass;
     $this->port = $port;
     $this->ssl = $use_ssl;
@@ -604,7 +613,7 @@
     else
       {
       $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", $this->sort_field, $this->skip_deleted);
-    
+
       if (empty($a_index))
         return array();
 
@@ -1035,14 +1044,6 @@
       }
     else
       $a_messages = iil_C_Search($this->conn, $mailbox, ($charset ? "CHARSET $charset " : '') . $criteria);
-
-    // clean message list (there might be some empty entries)
-    if (is_array($a_messages))
-      {
-      foreach ($a_messages as $i => $val)
-        if (empty($val))
-          unset($a_messages[$i]);
-      }
     
     // update messagecount cache ?
 //    $a_mailbox_cache = get_cache('messagecount');
@@ -1542,12 +1543,8 @@
     if (!is_array($uids))
       $uids = explode(',',$uids);
       
-    if ($flag=='UNDELETED')
-      $result = iil_C_Undelete($this->conn, $mailbox, join(',', $uids));
-    else if ($flag=='UNSEEN')
-      $result = iil_C_Unseen($this->conn, $mailbox, join(',', $uids));
-    else if ($flag=='UNFLAGGED')
-      $result = iil_C_UnFlag($this->conn, $mailbox, join(',', $uids), 'FLAGGED');
+    if (strpos($flag, 'UN') === 0)
+      $result = iil_C_UnFlag($this->conn, $mailbox, join(',', $uids), substr($flag, 2));
     else
       $result = iil_C_Flag($this->conn, $mailbox, join(',', $uids), $flag);
 
@@ -1574,6 +1571,21 @@
       $this->_set_messagecount($mailbox, 'ALL', $count*(-1));
 
     return $result;
+    }
+
+
+  /**
+   * Remove message flag for one or several messages
+   *
+   * @param mixed  Message UIDs as array or as comma-separated string
+   * @param string Flag to unset: SEEN, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT
+   * @param string Folder name
+   * @return boolean True on success, False on failure
+   * @see set_flag
+   */
+  function unset_flag($uids, $flag, $mbox_name=NULL)
+    {
+    return $this->set_flag($uids, 'UN'.$flag, $mbox_name);
     }
 
 
@@ -2216,8 +2228,10 @@
     $msg_count = $this->_messagecount($mailbox);
     $cache_count = count($cache_index);
 
-    // console("Cache check: $msg_count !== ".count($cache_index));
-
+    // empty mailbox
+    if (!$msg_count)
+      return $cache_count ? -2 : 1;
+    
     if ($cache_count==$msg_count) {
       if ($this->skip_deleted) {
 	$h_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", 'UID', $this->skip_deleted);
@@ -2405,10 +2419,10 @@
         $key,
         $index,
         $headers->uid,
-        (string)rc_substr($this->db->encode($this->decode_header($headers->subject, TRUE)), 0, 128),
-        (string)rc_substr($this->db->encode($this->decode_header($headers->from, TRUE)), 0, 128),
-        (string)rc_substr($this->db->encode($this->decode_header($headers->to, TRUE)), 0, 128),
-        (string)rc_substr($this->db->encode($this->decode_header($headers->cc, TRUE)), 0, 128),
+        (string)mb_substr($this->db->encode($this->decode_header($headers->subject, TRUE)), 0, 128),
+        (string)mb_substr($this->db->encode($this->decode_header($headers->from, TRUE)), 0, 128),
+        (string)mb_substr($this->db->encode($this->decode_header($headers->to, TRUE)), 0, 128),
+        (string)mb_substr($this->db->encode($this->decode_header($headers->cc, TRUE)), 0, 128),
         (int)$headers->size,
         serialize($this->db->encode(clone $headers)),
         is_object($struct) ? serialize($this->db->encode(clone $struct)) : NULL
@@ -2796,7 +2810,7 @@
       if (($p = array_search(strtolower($folder), $this->default_folders_lc)) !== false && !$a_defaults[$p])
         $a_defaults[$p] = $folder;
       else
-        $folders[$folder] = rc_strtolower(rcube_charset_convert($folder, 'UTF7-IMAP'));
+        $folders[$folder] = mb_strtolower(rcube_charset_convert($folder, 'UTF7-IMAP'));
       }
 
     // sort folders and place defaults on the top
@@ -2878,7 +2892,7 @@
   private function _change_subscription($a_mboxes, $mode)
     {
     $updated = FALSE;
-    
+
     if (is_array($a_mboxes))
       foreach ($a_mboxes as $i => $mbox_name)
         {
@@ -2886,15 +2900,12 @@
         $a_mboxes[$i] = $mailbox;
 
         if ($mode=='subscribe')
-          $result = iil_C_Subscribe($this->conn, $mailbox);
+          $updated = iil_C_Subscribe($this->conn, $mailbox);
         else if ($mode=='unsubscribe')
-          $result = iil_C_UnSubscribe($this->conn, $mailbox);
-
-        if ($result>=0)
-          $updated = TRUE;
+          $updated = iil_C_UnSubscribe($this->conn, $mailbox);
         }
-        
-    // get cached mailbox list    
+
+    // get cached mailbox list
     if ($updated)
       {
       $a_mailbox_cache = $this->get_cache('mailboxes');
@@ -2906,7 +2917,7 @@
         $a_mailbox_cache = array_merge($a_mailbox_cache, $a_mboxes);
       else if ($mode=='unsubscribe')
         $a_mailbox_cache = array_diff($a_mailbox_cache, $a_mboxes);
-        
+
       // write mailboxlist to cache
       $this->update_cache('mailboxes', $this->_sort_mailbox_list($a_mailbox_cache));
       }

--
Gitblit v1.9.1