From bb8012cfcde4ee598c2281373252a84ce0c96cc2 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 13 May 2010 05:13:25 -0400
Subject: [PATCH] - Extend contact groups support (#1486682) 

---
 program/include/rcube_imap.php |  209 +++++++++++++++++++++++++++++++++++----------------
 1 files changed, 143 insertions(+), 66 deletions(-)

diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 26d0ef4..1a66576 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -21,16 +21,13 @@
 */
 
 
-require_once('lib/mime.inc');
-require_once('lib/tnef_decoder.inc');
-
-
 /**
  * Interface class for accessing an IMAP server
  *
  * @package    Mail
  * @author     Thomas Bruederli <roundcube@gmail.com>
- * @version    1.6
+ * @author     Aleksander Machniak <alec@alec.pl> 
+ * @version    2.0
  */
 class rcube_imap
 {
@@ -95,7 +92,7 @@
      */
     function connect($host, $user, $pass, $port=143, $use_ssl=null)
     {
-        // check for Open-SSL support in PHP build
+        // check for OpenSSL support in PHP build
         if ($use_ssl && extension_loaded('openssl'))
             $this->options['ssl_mode'] = $use_ssl == 'imaps' ? 'ssl' : $use_ssl;
         else if ($use_ssl) {
@@ -412,16 +409,18 @@
     /**
      * Get message count for a specific mailbox
      *
-     * @param   string   Mailbox/folder name
-     * @param   string   Mode for count [ALL|THREADS|UNSEEN|RECENT]
-     * @param   boolean  Force reading from server and update cache
-     * @return  int      Number of messages
-     * @access  public
+     * @param  string  Mailbox/folder name
+     * @param  string  Mode for count [ALL|THREADS|UNSEEN|RECENT]
+     * @param  boolean Force reading from server and update cache
+     * @param  boolean Enables storing folder status info (max UID/count),
+     *                 required for mailbox_status()
+     * @return int     Number of messages
+     * @access public
      */
-    function messagecount($mbox_name='', $mode='ALL', $force=false)
+    function messagecount($mbox_name='', $mode='ALL', $force=false, $status=true)
     {
         $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
-        return $this->_messagecount($mailbox, $mode, $force);
+        return $this->_messagecount($mailbox, $mode, $force, $status);
     }
 
 
@@ -431,7 +430,7 @@
      * @access  private
      * @see     rcube_imap::messagecount()
      */
-    private function _messagecount($mailbox='', $mode='ALL', $force=false)
+    private function _messagecount($mailbox='', $mode='ALL', $force=false, $status=true)
     {
         $mode = strtoupper($mode);
 
@@ -457,7 +456,10 @@
 
         if ($mode == 'THREADS') {
             $count = $this->_threadcount($mailbox, $msg_count);
-            $_SESSION['maxuid'][$mailbox] = $msg_count ? $this->_id2uid($msg_count) : 0;
+            if ($status) {
+                $this->set_folder_stats($mailbox, 'cnt', $msg_count);
+                $this->set_folder_stats($mailbox, 'maxuid', $msg_count ? $this->_id2uid($msg_count, $mailbox) : 0);
+            }
         }
         // RECENT count is fetched a bit different
         else if ($mode == 'RECENT') {
@@ -481,15 +483,20 @@
       
             $count = is_array($index) ? count($index) : 0;
 
-            if ($mode == 'ALL')
-                $_SESSION['maxuid'][$mailbox] = $index ? $this->_id2uid(max($index)) : 0;
+            if ($mode == 'ALL' && $status) {
+                $this->set_folder_stats($mailbox, 'cnt', $count);
+                $this->set_folder_stats($mailbox, 'maxuid', $index ? $this->_id2uid(max($index), $mailbox) : 0);
+            }
         }
         else {
             if ($mode == 'UNSEEN')
                 $count = $this->conn->countUnseen($mailbox);
             else {
                 $count = $this->conn->countMessages($mailbox);
-                $_SESSION['maxuid'][$mailbox] = $count ? $this->_id2uid($count) : 0;
+                if ($status) {
+                    $this->set_folder_stats($mailbox,'cnt', $count);
+                    $this->set_folder_stats($mailbox, 'maxuid', $count ? $this->_id2uid($count, $mailbox) : 0);
+                }
             }
         }
 
@@ -1033,32 +1040,70 @@
         return count($a_msg_headers);
     }
   
+
     /**
-     * Fetches IDS of pseudo recent messages.
+     * Returns current status of mailbox
      *
      * 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
+     * @param string Mailbox/folder name
+     * @return int   Folder status
      */
-    function recent_uids($mbox_name = null, $nofetch = false)
+    function mailbox_status($mbox_name = null)
     {
         $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
-        $old_maxuid = intval($_SESSION['maxuid'][$mailbox]);
-    
-        // refresh message count -> will update $_SESSION['maxuid'][$mailbox]
+        $old = $this->get_folder_stats($mailbox);
+
+        // refresh message count -> will update 
         $this->_messagecount($mailbox, 'ALL', true);
-    
-        if ($_SESSION['maxuid'][$mailbox] > $old_maxuid) {
-            $maxuid = max(1, $old_maxuid+1);
-            return array_values((array)$this->conn->fetchHeaderIndex(
-                $mailbox, "$maxuid:*", 'UID', $this->skip_deleted, true));
-        }
-    
-        return array();
+
+        $result = 0;
+        $new = $this->get_folder_stats($mailbox);
+
+        // got new messages
+        if ($new['maxuid'] > $old['maxuid'])
+            $result += 1;
+        // some messages has been deleted
+        if ($new['cnt'] < $old['cnt'])
+            $result += 2;
+
+        // @TODO: optional checking for messages flags changes (?)
+        // @TODO: UIDVALIDITY checking
+
+        return $result;
     }
-  
+
+
+    /**
+     * Stores folder statistic data in session
+     * @TODO: move to separate DB table (cache?)
+     *
+     * @param string Mailbox name
+     * @param string Data name
+     * @param mixed  Data value
+     */
+    private function set_folder_stats($mbox_name, $name, $data)
+    {
+        $_SESSION['folders'][$mbox_name][$name] = $data;
+    }
+
+
+    /**
+     * Gets folder statistic data
+     *
+     * @param string Mailbox name
+     * @return array Stats data
+     */
+    private function get_folder_stats($mbox_name)
+    {
+        if ($_SESSION['folders'][$mbox_name])
+            return (array) $_SESSION['folders'][$mbox_name];
+        else
+            return array();
+    }
+
+
     /**
      * Return sorted array of message IDs (not UIDs)
      *
@@ -1414,6 +1459,27 @@
         return $a_messages;
     }
     
+
+    /**
+     * Direct (real and simple) SEARCH request to IMAP server,
+     * without result sorting and caching
+     *
+     * @param  string  Mailbox name to search in
+     * @param  string  Search string
+     * @param  boolean True if UIDs should be returned
+     * @return array   Search results as list of message IDs or UIDs
+     * @access public
+     */
+    function search_once($mbox_name='', $str=NULL, $ret_uid=false)
+    {
+        if (!$str)
+            return false;
+    
+        $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
+
+        return $this->conn->search($mailbox, $str, $ret_uid);
+    }
+
   
     /**
      * Sort thread
@@ -1517,9 +1583,8 @@
     {
         if (!empty($this->search_string))
             $this->search_set = $this->search('', $this->search_string, $this->search_charset,
+    	        $this->search_sort_field, $this->search_threads);
 
-    	$this->search_sort_field, $this->search_threads);
-      
         return $this->get_search_set();
     }
   
@@ -1554,7 +1619,7 @@
     function get_headers($id, $mbox_name=NULL, $is_uid=true, $bodystr=false)
     {
         $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
-        $uid = $is_uid ? $id : $this->_id2uid($id);
+        $uid = $is_uid ? $id : $this->_id2uid($id, $mailbox);
 
         // get cached headers
         if ($uid && ($headers = &$this->get_cached_message($mailbox.'.msg', $uid)))
@@ -1568,7 +1633,7 @@
             if ($headers->uid && $headers->id)
                 $this->uid_id_map[$mailbox][$headers->uid] = $headers->id;
 
-            $this->add_message_cache($mailbox.'.msg', $headers->id, $headers, NULL, true);
+            $this->add_message_cache($mailbox.'.msg', $headers->id, $headers, NULL);
         }
 
         return $headers;
@@ -1593,9 +1658,10 @@
             return $headers->structure;
         }
 
-        if (!$structure_str)
+        if (!$structure_str) {
             $structure_str = $this->conn->fetchStructureString($this->mailbox, $uid, true);
-        $structure = iml_GetRawStructureArray($structure_str);
+        }
+        $structure = rcube_mime_struct::parseStructure($structure_str);
         $struct = false;
 
         // parse structure and add headers
@@ -1945,16 +2011,16 @@
         // get part encoding if not provided
         if (!is_object($o_part)) {
             $structure_str = $this->conn->fetchStructureString($this->mailbox, $uid, true); 
-            $structure = iml_GetRawStructureArray($structure_str);
+            $structure = new rcube_mime_struct();
             // error or message not found
-            if (empty($structure))
+            if (!$structure->loadStructure($structure_str)) {
                 return false;
+            }
 
-            $part_type = iml_GetPartTypeCode($structure, $part);
             $o_part = new rcube_message_part;
-            $o_part->ctype_primary = $part_type==0 ? 'text' : ($part_type==2 ? 'message' : 'other');
-            $o_part->encoding = strtolower(iml_GetPartEncodingString($structure, $part));
-            $o_part->charset = iml_GetPartCharset($structure, $part);
+            $o_part->ctype_primary = strtolower($structure->getPartType($part));
+            $o_part->encoding      = strtolower($structure->getPartEncoding($part));
+            $o_part->charset       = $structure->getPartCharset($part);
         }
       
         // TODO: Add caching for message parts
@@ -2460,10 +2526,10 @@
         $a_out = array();
         $a_mboxes = $this->_list_mailboxes($root, $filter);
 
-        foreach ($a_mboxes as $mbox_row) {
-            $name = $this->mod_mailbox($mbox_row, 'out');
-            if (strlen($name))
+        foreach ($a_mboxes as $idx => $mbox_row) {
+            if ($name = $this->mod_mailbox($mbox_row, 'out'))
                 $a_out[] = $name;
+            unset($a_mboxes[$idx]);
         }
 
         // INBOX should always be available
@@ -2523,24 +2589,28 @@
      */
     function list_unsubscribed($root='')
     {
-        static $sa_unsubscribed;
+        static $a_folders;
     
-        if (is_array($sa_unsubscribed))
-            return $sa_unsubscribed;
+        if (is_array($a_folders))
+            return $a_folders;
       
         // retrieve list of folders from IMAP server
         $a_mboxes = $this->conn->listMailboxes($this->mod_mailbox($root), '*');
 
         // modify names with root dir
-        foreach ($a_mboxes as $mbox_name) {
-            $name = $this->mod_mailbox($mbox_name, 'out');
-            if (strlen($name))
+        foreach ($a_mboxes as $idx => $mbox_name) {
+            if ($name = $this->mod_mailbox($mbox_name, 'out'))
                 $a_folders[] = $name;
+            unset($a_mboxes[$idx]);
         }
 
+        // INBOX should always be available
+        if (!in_array('INBOX', $a_folders))
+            array_unshift($a_folders, 'INBOX');
+
         // filter folders and sort them
-        $sa_unsubscribed = $this->_sort_mailbox_list($a_folders);
-        return $sa_unsubscribed;
+        $a_folders = $this->_sort_mailbox_list($a_folders);
+        return $a_folders;
     }
 
 
@@ -2687,7 +2757,7 @@
             foreach ($a_mboxes as $mbox_name) {
                 $mailbox = $this->mod_mailbox($mbox_name);
                 $sub_mboxes = $this->conn->listMailboxes($this->mod_mailbox(''),
-	            $mbox_name . $this->delimiter . '*');
+	                $mbox_name . $this->delimiter . '*');
 
                 // unsubscribe mailbox before deleting
                 $this->conn->unsubscribe($mailbox);
@@ -2698,7 +2768,7 @@
                     $deleted = true;
                     $this->clear_message_cache($mailbox.'.msg');
 	            }
-	  
+
                 foreach ($sub_mboxes as $c_mbox) {
                     if ($c_mbox != 'INBOX') {
                         $this->conn->unsubscribe($c_mbox);
@@ -2748,14 +2818,19 @@
             if ($mbox_name == 'INBOX')
                 return true;
 
+            $key = $subscription ? 'subscribed' : 'existing';
+            if (is_array($this->icache[$key]) && in_array($mbox_name, $this->icache[$key]))
+                return true;
+
             if ($subscription) {
-                if ($a_folders = $this->conn->listSubscribed($this->mod_mailbox(''), $mbox_name))
-                    return true;
+                $a_folders = $this->conn->listSubscribed($this->mod_mailbox(''), $mbox_name);
             }
             else {
-                $a_folders = $this->conn->listMailboxes($this->mod_mailbox(''), $mbox_mbox);
-	
-	        if (is_array($a_folders) && in_array($this->mod_mailbox($mbox_name), $a_folders))
+                $a_folders = $this->conn->listMailboxes($this->mod_mailbox(''), $mbox_name);
+	        }
+	        
+            if (is_array($a_folders) && in_array($this->mod_mailbox($mbox_name), $a_folders)) {
+                $this->icache[$key][] = $mbox_name;
                 return true;
             }
         }
@@ -3129,7 +3204,7 @@
         if (!$this->caching_enabled)
             return;
     
-        // check for an existing record (probly headers are cached but structure not)
+        // check for an existing record (probably headers are cached but structure not)
         if (!$force) {
             $sql_result = $this->db->query(
                 "SELECT message_id".
@@ -3309,6 +3384,8 @@
     {
         if (!isset($part->body))
             $part->body = $this->get_message_part($uid, $part->mime_id, $part);
+
+        require_once('lib/tnef_decoder.inc');
 
         $pid = 0;
         $tnef_parts = array();
@@ -3513,7 +3590,7 @@
             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'));
+                $folders[$folder] = rcube_charset_convert($folder, 'UTF7-IMAP');
         }
 
         // sort folders and place defaults on the top

--
Gitblit v1.9.1