Rewrite of internal message caching
authorstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 31 May 2004 20:07:44 +0000 (20:07 +0000)
committerstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 31 May 2004 20:07:44 +0000 (20:07 +0000)
Added paginator support for asearch
Added next/prev links in read_body to walk through search results
Added individual sort settings / mailbox
Added what I forgot to mention

git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@7577 7612ce4b-ef26-0410-bec9-ea0150e637f0

14 files changed:
functions/file_prefs.php
functions/forms.php
functions/imap_asearch.php
functions/imap_mailbox.php
functions/imap_messages.php
functions/mailbox_display.php
functions/rfc822address.php
include/load_prefs.php
src/download.php
src/left_main.php
src/move_messages.php
src/read_body.php
src/right_main.php
src/search.php

index 224e9890bbbe311cf6637dbfa53d682cf3feaf04..d8a5cc97d82a9422d62f2d14071a26837e7101b9 100644 (file)
@@ -20,14 +20,14 @@ include_once(SM_PATH . 'functions/display_messages.php');
  */
 function cachePrefValues($data_dir, $username) {
     global $prefs_are_cached, $prefs_cache;
-       
+
     if ( isset($prefs_are_cached) && $prefs_are_cached) {
         return;
     }
-    
+
     sqsession_unregister('prefs_cache');
     sqsession_unregister('prefs_are_cached');
-    
+
     /* Calculate the filename for the user's preference file */
     $filename = getHashedFile($username, $data_dir, "$username.pref");
 
@@ -82,7 +82,7 @@ function cachePrefValues($data_dir, $username) {
     sqsession_register($prefs_cache, 'prefs_cache');
     sqsession_register($prefs_are_cached, 'prefs_are_cached');
 }
-   
+
 /**
  * Return the value for the preference given by $string.
  */
@@ -91,15 +91,15 @@ function getPref($data_dir, $username, $string, $default = '') {
 
     $result = do_hook_function('get_pref_override',array($username,$string));
     if (!$result) {
-       cachePrefValues($data_dir, $username);
-       if (isset($prefs_cache[$string])) {
-           $result = $prefs_cache[$string];
-       } else {
-           $result = do_hook_function('get_pref', array($username,$string));
-           if (!$result) {         
-               $result = $default;
-           }
-       }
+        cachePrefValues($data_dir, $username);
+        if (isset($prefs_cache[$string])) {
+                $result = $prefs_cache[$string];
+        } else {
+            $result = do_hook_function('get_pref', array($username,$string));
+            if (!$result) {
+                $result = $default;
+            }
+        }
     }
     return ($result);
 }
@@ -109,7 +109,7 @@ function getPref($data_dir, $username, $string, $default = '') {
  */
 function savePrefValues($data_dir, $username) {
     global $prefs_cache;
-   
+
     $filename = getHashedFile($username, $data_dir, "$username.pref");
 
     /* Open the file for writing, or else display an error to the user. */
@@ -143,11 +143,11 @@ function removePref($data_dir, $username, $string) {
     global $prefs_cache;
 
     cachePrefValues($data_dir, $username);
+
     if (isset($prefs_cache[$string])) {
         unset($prefs_cache[$string]);
     }
+
     savePrefValues($data_dir, $username);
 }
 
index 97fb746ffe03041ee19f19d273932f852098a945..6acf361d00d2e58fce53f6e0187878c4e24616d1 100644 (file)
@@ -44,7 +44,7 @@ function addCheckBox($name, $checked = false, $value = null) {
  * Form radio box
  */
 function addRadioBox($name, $checked = false, $value = null) {
-    return addInputField('radio', $name, $value, 
+    return addInputField('radio', $name, $value,
         ($checked ? ' checked="checked"' : ''));
 }
 
index 0c2c21c6960fe6c9136cde9b39197b930f9e59e2..667e96149fa2c839564db57df6d454f3b2f94cab 100644 (file)
@@ -194,10 +194,10 @@ function s_debug_dump($var_name, $var_var)
 
 /** Encode a string to quoted or literal as defined in rfc 3501
  *
- * - § 4.3 String:
+ * -  4.3 String:
  *     A quoted string is a sequence of zero or more 7-bit characters,
  *      excluding CR and LF, with double quote (<">) characters at each end.
- * - § 9. Formal Syntax:
+ * -  9. Formal Syntax:
  *     quoted-specials = DQUOTE / "\"
  * @param string $what string to encode
  * @param string $charset search charset used
@@ -207,7 +207,6 @@ function sqimap_asearch_encode_string($what, $charset)
 {
        if (strtoupper($charset) == 'ISO-2022-JP')      // This should be now handled in imap_utf7_local?
                $what = mb_convert_encoding($what, 'JIS', 'auto');
-//if (ereg("[\"\\\r\n\x80-\xff]", $what))
        if (preg_match('/["\\\\\r\n\x80-\xff]/', $what))
                return '{' . strlen($what) . "}\r\n" . $what;   // 4.3 literal form
        return '"' . $what . '"';       // 4.3 quoted string form
@@ -293,7 +292,7 @@ function sqimap_asearch_build_criteria($opcode, $what, $charset)
                case 'afield':  /* HEADER field-name: field-body */
                        preg_match('/^([^:]+):(.*)$/', $what, $what_parts);
                        if (count($what_parts) == 3)
-                               $criteria = $opcode . ' ' . 
+                               $criteria = $opcode . ' ' .
                                        sqimap_asearch_encode_string($what_parts[1], $charset) . ' ' .
                                        sqimap_asearch_encode_string($what_parts[2], $charset) . ' ';
                break;
@@ -348,15 +347,15 @@ function sqimap_run_search($imapConnection, $search_string, $search_charset)
                $search_charset = '';
        /* 6.4.4 try OPTIONAL [CHARSET] specification first */
        if ($search_charset != '')
-               $query = 'SEARCH CHARSET "' . strtoupper($search_charset) . '" ALL ' . $search_string;
+               $query = 'SEARCH CHARSET "' . strtoupper($search_charset) . '" ' . $search_string;
        else
-               $query = 'SEARCH ALL ' . $search_string;
+               $query = 'SEARCH ' . $search_string;
        s_debug_dump('C:', $query);
        $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
 
        /* 6.4.4 try US-ASCII charset if we tried an OPTIONAL [CHARSET] and received a tagged NO response (SHOULD be [BADCHARSET]) */
        if (($search_charset != '')  && (strtoupper($response) == 'NO')) {
-               $query = 'SEARCH CHARSET US-ASCII ALL ' . $search_string;
+               $query = 'SEARCH CHARSET US-ASCII ' . $search_string;
                s_debug_dump('C:', $query);
                $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
        }
@@ -364,15 +363,7 @@ function sqimap_run_search($imapConnection, $search_string, $search_charset)
                sqimap_asearch_error_box($response, $query, $message);
                return array();
        }
-
-       // Keep going till we find the * SEARCH response
-       foreach ($readin as $readin_part) {
-               s_debug_dump('S:', $readin_part);
-               if (substr($readin_part, 0, 9) == '* SEARCH ') {
-                       //EIMS returns multiple SEARCH responses, and this allowed according to Mark Crispin
-                       $messagelist = sqimap_array_merge_unique($messagelist, preg_split("/ /", substr($readin_part, 9)));
-               }
-       }
+    $messagelist = parseUidList($readin,'SEARCH');
 
        if (empty($messagelist))        //Empty search response, ie '* SEARCH'
                return array();
@@ -383,168 +374,6 @@ function sqimap_run_search($imapConnection, $search_string, $search_charset)
        return $id;
 }
 
-/**
- * Run the imap SORT command as defined in 
- * @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
- * @param resource $imapConnection the current imap stream
- * @param string $search_string the full search expression as defined in rfc 3501
- * @param string $search_charset mandatory charset
- * @param string $sort_criteria the full sort criteria expression eg "SUBJECT REVERSE DATE"
- * @return array an IDs or UIDs array of matching messages or an empty array
- */
-function sqimap_run_sort($imapConnection, $search_string, $search_charset, $sort_criteria)
-{
-       if ($search_charset == '')
-               $search_charset = 'US-ASCII';
-       $query = 'SORT (' . $sort_criteria . ') "' . strtoupper($search_charset) . '" ALL ' . $search_string;
-       s_debug_dump('C:', $query);
-       $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
-       s_debug_dump('S:', $response);
-
-       /* 6.4 try US-ASCII charset if we received a tagged NO response (SHOULD be [BADCHARSET]) */
-       if (($search_charset != 'US-ASCII')  && (strtoupper($response) == 'NO')) {
-               s_debug_dump('S:', $readin);
-               $query = 'SORT (' . $sort_criteria . ') US-ASCII ALL ' . $search_string;
-               s_debug_dump('C:', $query);
-               $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
-               s_debug_dump('S:', $response);
-       }
-
-       if (strtoupper($response) != 'OK') {
-               s_debug_dump('S:', $readin);
-//     sqimap_asearch_error_box($response, $query, $message);
-//     return array();
-               return sqimap_run_search($imapConnection, $search_string, $search_charset);     // Fell back to standard search
-       }
-
-       /* Keep going till we find the * SORT response */
-       foreach ($readin as $readin_part) {
-               s_debug_dump('S:', $readin_part);
-               if (substr($readin_part, 0, 7) == '* SORT ') {
-                       //SORT returns untagged responses
-                       $messagelist = sqimap_array_merge_unique($messagelist, preg_split("/ /", substr($readin_part, 7)));
-               }
-       }
-
-       if (empty($messagelist))        //Empty search response, ie '* SORT'
-               return array();
-
-       $cnt = count($messagelist);
-       for ($q = 0; $q < $cnt; $q++)
-               $id[$q] = trim($messagelist[$q]);
-       return $id;
-}
-
-/**
- * Run the imap THREAD command as defined in 
- * @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
- * @param resource $imapConnection the current imap stream
- * @param string $search_string the full search expression as defined in rfc 3501
- * @param string $search_charset mandatory charset
- * @param string $thread_algorithm the threading algorithm "ORDEREDSUBJECT" or "REFERENCES"
- * @return array an IDs or UIDs array of matching messages or an empty array
- * @global array thread_new will be used by thread view in mailbox_display
- * @global array server_sort_array will be used by thread view in mailbox_display
- */
-function sqimap_run_thread($imapConnection, $search_string, $search_charset, $thread_algorithm)
-{
-       global $thread_new, $server_sort_array;
-
-       if (sqsession_is_registered('thread_new'))
-               sqsession_unregister('thread_new');
-       if (sqsession_is_registered('server_sort_array'))
-               sqsession_unregister('server_sort_array');
-
-       $thread_new = array();
-       $thread_new[0] = "";
-
-       $server_sort_array = array();
-
-       if ($search_charset == '')
-               $search_charset = 'US-ASCII';
-       $query = 'THREAD ' . $thread_algorithm . ' "' . strtoupper($search_charset) . '" ALL ' . $search_string;
-       s_debug_dump('C:', $query);
-       $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
-       s_debug_dump('S:', $response);
-
-       /* 6.4 try US-ASCII charset if we received a tagged NO response (SHOULD be [BADCHARSET]) */
-       if (($search_charset != 'US-ASCII')  && (strtoupper($response) == 'NO')) {
-               s_debug_dump('S:', $readin);
-               $query = 'THREAD ' . $thread_algorithm . ' US-ASCII ALL ' . $search_string;
-               s_debug_dump('C:', $query);
-               $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
-               s_debug_dump('S:', $response);
-       }
-
-       if (strtoupper($response) != 'OK') {
-               s_debug_dump('S:', $readin);
-               if (empty($response)) { //imap server closed connection. We can't go further.
-/* we should at this point:
-       - warn the user that the THREAD call has failed
-       - (offer him a way to) disconnect it permanently in the prefs
-       - perform the regular search instead or provide a way to do it in one click
-*/
-                       global $sort, $mailbox, $php_self;
-                       $message = _("The imap server failed to handle threading.");
-                       $unthread = _("Click here to unset thread view for this mailbox and start again.");
-                       if (preg_match('/^(.+)\?.+$/', $php_self, $regs))
-                               $source_url = $regs[1];
-       else
-                               $source_url = $php_self;
-                       $link = '<a href=' . $source_url . '?sort=' . $sort . '&start_messages=1&set_thread=0&mailbox=' . urlencode($mailbox) . '>' . $unthread . '</a>';
-                       sqimap_asearch_error_box($response, $query, $message, $link);
-                       return array();
-               }
-               return sqimap_run_search($imapConnection, $search_string, $search_charset);     // Fell back to standard search
-       }
-
-       /* Keep going till we find the * THREAD response */
-       foreach ($readin as $readin_part) {
-               s_debug_dump('S:', $readin_part);
-               if (substr($readin_part, 0, 9) == '* THREAD ') {
-                       $thread_temp = preg_split("//", substr($readin_part, 9), -1, PREG_SPLIT_NO_EMPTY);
-                       break;  // Should be the last anyway
-               }
-       }
-
-       if (empty($thread_temp))        //Empty search response, ie '* THREAD'
-               return array();
-
-       $char_count = count($thread_temp);
-       $counter = 0;
-       $k = 0;
-       for ($i=0;$i<$char_count;$i++) {
-        if ($thread_temp[$i] != ')' && $thread_temp[$i] != '(') {
-                $thread_new[$k] = $thread_new[$k] . $thread_temp[$i];
-        }
-        elseif ($thread_temp[$i] == '(') {
-                $thread_new[$k] .= $thread_temp[$i];
-                $counter++;
-        }
-        elseif ($thread_temp[$i] == ')') {
-                if ($counter > 1) {
-                        $thread_new[$k] .= $thread_temp[$i];
-                        $counter = $counter - 1;
-                }
-                else {
-                        $thread_new[$k] .= $thread_temp[$i];
-                        $k++;
-                        $thread_new[$k] = "";
-                        $counter = $counter - 1;
-                }
-        }
-       }
-       sqsession_register($thread_new, 'thread_new');
-       $thread_new = array_reverse($thread_new);
-       $thread_list = implode(" ", $thread_new);
-       $thread_list = str_replace("(", " ", $thread_list);
-       $thread_list = str_replace(")", " ", $thread_list);
-       $thread_list = preg_split("/\s/", $thread_list, -1, PREG_SPLIT_NO_EMPTY);
-       $server_sort_array = $thread_list;
-       sqsession_register($server_sort_array, 'server_sort_array');
-       return $thread_list;
-}
-
 /**
  * @global bool allow_charset_search user setting
  * @global array languages sm languages array
@@ -602,7 +431,7 @@ function sqimap_asearch_get_sub_mailboxes($cur_mailbox, &$mboxes_array)
 }
 
 /**
- * Performs the search, given all the criteria, merging results for every mailbox
+ * Create the search query strings for all given criteria and merge results for every mailbox
  * @param resource $imapConnection
  * @param array $mailbox_array (reference)
  * @param array $biop_array (reference)
@@ -612,27 +441,19 @@ function sqimap_asearch_get_sub_mailboxes($cur_mailbox, &$mboxes_array)
  * @param array $exclude_array (reference)
  * @param array $sub_array (reference)
  * @param array $mboxes_array selectable unformatted mailboxes names (reference)
- * @global bool allow_server_sort comes from config.php
- * @global integer sort sm internal sort order
- * @global bool allow_thread_sort comes from config.php
- * @global bool thread_sort_messages does it really need to global?
- * @global integer sort_by_ref thread by references
- * @global string data_dir
- * @global string username
  * @return array array(mailbox => array(UIDs))
  */
 function sqimap_asearch($imapConnection, &$mailbox_array, &$biop_array, &$unop_array, &$where_array, &$what_array, &$exclude_array, &$sub_array, &$mboxes_array)
 {
-       global $allow_server_sort, $sort, $allow_thread_sort, $thread_sort_messages, $sort_by_ref;
-       global $data_dir, $username;
 
        $search_charset = sqimap_asearch_get_charset();
        $mbox_msgs = array();
+    $mbox_search = array();
        $search_string = '';
        $cur_mailbox = $mailbox_array[0];
        $cur_biop = ''; /* Start with ALL */
        /* We loop one more time than the real array count, so the last search gets fired */
-       for ($cur_crit = 0; $cur_crit <= count($where_array); $cur_crit++) {
+       for ($cur_crit=0,$iCnt=count($where_array); $cur_crit <= $iCnt; ++$cur_crit) {
                if (empty($exclude_array[$cur_crit])) {
                        $next_mailbox = $mailbox_array[$cur_crit];
                        if ($next_mailbox != $cur_mailbox) {
@@ -644,61 +465,52 @@ function sqimap_asearch($imapConnection, &$mailbox_array, &$biop_array, &$unop_a
                                else
                                        $search_mboxes = array($cur_mailbox);
                                foreach ($search_mboxes as $cur_mailbox) {
-                                       s_debug_dump('C:SELECT:', $cur_mailbox);
-                                       sqimap_mailbox_select($imapConnection, $cur_mailbox);
-                                       $thread_sort_messages = $allow_thread_sort && getPref($data_dir, $username, 'thread_' . $cur_mailbox);
-                                       if ($thread_sort_messages) {
-                                               if ($sort_by_ref == 1)
-                                                       $thread_algorithm = 'REFERENCES';
-                                               else
-                                                       $thread_algorithm = 'ORDEREDSUBJECT';
-                                               $found_msgs = sqimap_run_thread($imapConnection, $search_string, $search_charset, $thread_algorithm);
-                                       }
-                                       else
-                                       if (($allow_server_sort) && ($sort < 6)) {
-                                               $sort_criteria = sqimap_asearch_get_sort_criteria($cur_mailbox, $sort);
-                                               $found_msgs = sqimap_run_sort($imapConnection, $search_string, $search_charset, $sort_criteria);
-                                       }
-                                       else
-                                               $found_msgs = sqimap_run_search($imapConnection, $search_string, $search_charset);
-                                       if (isset($mbox_msgs[$cur_mailbox])) {
-                                               if ($cur_biop == 'OR')  /* Merge with previous results */
-                                                       $mbox_msgs[$cur_mailbox] = sqimap_array_merge_unique($mbox_msgs[$cur_mailbox], $found_msgs);
-                                               else    /* Intersect previous results */
-                                                       $mbox_msgs[$cur_mailbox] = array_values(array_intersect($found_msgs, $mbox_msgs[$cur_mailbox]));
-                                       }
-                                       else /* No previous results */
-                                               $mbox_msgs[$cur_mailbox] = $found_msgs;
-                                       if (empty($mbox_msgs[$cur_mailbox]))    /* Can happen with intersect, and we need at the end a contiguous array */
-                                               unset($mbox_msgs[$cur_mailbox]);
-                               }
-                               $cur_mailbox = $next_mailbox;
+                    if (isset($mbox_search[$cur_mailbox])) {
+                        $mbox_search[$cur_mailbox]['search'] .= ' ' . $search_string;
+                    } else {
+                        $mbox_search[$cur_mailbox]['search'] = $search_string;
+                    }
+                    $mbox_search[$cur_mailbox]['charset'] = $search_charset;
+                }
+                               $cur_mailbox = $next_mailbox;
                                $search_string = '';
+
                        }
-                       if (isset($where_array[$cur_crit])) {
+                       if (isset($where_array[$cur_crit]) && empty($exclude_array[$cur_crit])) {
                                $criteria = sqimap_asearch_build_criteria($where_array[$cur_crit], $what_array[$cur_crit], $search_charset);
                                if (!empty($criteria)) {
+                    //$criteria = 'ALL '. $criteria;
                                        $unop = $unop_array[$cur_crit];
-                                       if (!empty($unop))
+                                       if (!empty($unop)) {
                                                $criteria = $unop . ' ' . $criteria;
+                    } else {
+                        $criteria = 'ALL ' . $criteria;
+                    }
                                        /* We need to infix the next non-excluded criteria's biop if it's the same mailbox */
                                        $next_biop = '';
                                        for ($next_crit = $cur_crit+1; $next_crit <= count($where_array); $next_crit++) {
                                                if (empty($exclude_array[$next_crit])) {
-                                                       if (asearch_nz($mailbox_array[$next_crit]) == $cur_mailbox)
+                                                       if (asearch_nz($mailbox_array[$next_crit]) == $cur_mailbox) {
                                                                $next_biop = asearch_nz($biop_array[$next_crit]);
-                                                       break;
+                                if ($next_biop == 'OR' || $next_biop == 'ALL') {
+                                    $next_criterium =  sqimap_asearch_build_criteria($where_array[$next_crit], $what_array[$next_crit], $search_charset);
+                                    // unset something
+                                    $exclude_array[$next_crit] = true;
+                                    $criteria .= $next_biop . ' '. $next_criterium;
+                                }
+                                                   }
                                                }
                                        }
-                                       if ($next_biop == 'OR')
-                                               $criteria = $next_biop . ' ' . $criteria;
+                                       //if ($next_biop == 'OR')
+                                       //      $criteria = $next_biop . ' ' . $criteria;
                                        $search_string .= $criteria;
-                                       $cur_biop = asearch_nz($biop_array[$cur_crit]);
+                                       //$cur_biop = asearch_nz($biop_array[$cur_crit]);
                                }
                        }
+
                }
        }
-       return $mbox_msgs;
+    return ($mbox_search);
 }
 
 ?>
index e2198947a7629fdfa923d45494c76eec7f4c194c..e85f6fdeccf02bb9c51e563ba0407ef090f468a7 100755 (executable)
@@ -247,44 +247,6 @@ function sqimap_mailbox_expunge ($imap_stream, $mailbox, $handle_errors = true,
     return $cnt;
 }
 
-
-/**
- * Expunge specified message
- *
- * We'll use this wrapper function to
- * remove the message with the matching UID .. the order
- * won't be changed - the array element for the message
- * will just be removed.
- */
-
-function sqimap_mailbox_expunge_dmn($imapConnection, &$aMailbox, $message_id) {
-    $cnt = 0;
-
-    if ($aMailbox['AUTO_EXPUNGE']) {
-         $cnt = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true);
-    } else {
-         return $cnt;
-    }
-    $error = '';
-    $message_id = (int) $message_id; // we use strickt array_search
-    if (is_array($aMailbox['UIDSET'])) {
-        $key = array_search($message_id,$aMailbox['UIDSET'],true);
-        if ($key !== false && !is_null($key)) {
-            unset($aMailbox['UIDSET'][$key]);
-            $aMailbox['UIDSET'] = array_values($aMailbox['UIDSET']);
-            // adapt the exists count to avoid triggering of a new sort
-            $aMailbox['EXISTS'] -= 1;
-        } else {
-            $aMailbox['UIDSET'] = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
-        }
-    } else {
-        $aMailbox['UIDSET'] = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
-    }
-    sqsession_register($aMailbox,'aLastSelectedMailbox');
-    sqsession_register($aMailbox['UIDSET'],'server_sort_array'); //fix me, use aMailbox instead
-    return $cnt;
-}
-
 /**
  * Checks whether or not the specified mailbox exists
  */
index 2edf381cbba2ea9501b851a887263d6ccb1e0326..f8cc0792fdc390729803afc8170fa8eaae31a8ad 100755 (executable)
@@ -36,6 +36,11 @@ function sqimap_messages_copy ($imap_stream, $start, $end, $mailbox) {
 function sqimap_msgs_list_copy ($imap_stream, $id, $mailbox) {
     $msgs_id = sqimap_message_list_squisher($id);
     $read = sqimap_run_command ($imap_stream, "COPY $msgs_id " . sqimap_encode_mailbox_name($mailbox), true, $response, $message, TRUE);
+    if ($response == 'OK') {
+        return true;
+    } else {
+        return false;
+    }
 }
 
 /**
@@ -47,8 +52,11 @@ function sqimap_msgs_list_copy ($imap_stream, $id, $mailbox) {
 */
 function sqimap_msgs_list_move ($imap_stream, $id, $mailbox) {
     $msgs_id = sqimap_message_list_squisher($id);
-    $read = sqimap_run_command ($imap_stream, "COPY $msgs_id " . sqimap_encode_mailbox_name($mailbox), true, $response, $message, TRUE);
-    $read = sqimap_run_command ($imap_stream, "STORE $msgs_id +FLAGS (\\Deleted)", true, $response,$message, TRUE);
+    if (sqimap_msgs_list_copy ($imap_stream, $id, $mailbox)) {
+        return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true);
+    } else {
+        return false;
+    }
 }
 
 
@@ -72,13 +80,19 @@ function sqimap_messages_delete ($imap_stream, $start, $end, $mailbox, $bypass_t
 }
 
 function sqimap_msgs_list_delete ($imap_stream, $mailbox, $id, $bypass_trash=false) {
+    // FIX ME, remove globals by introducing an associative array with properties
+    // as 4th argument as replacement for the bypass_trash var
     global $move_to_trash, $trash_folder;
-    $msgs_id = sqimap_message_list_squisher($id);
+    $bRes = true;
     if (($move_to_trash == true) && ($bypass_trash != true) &&
         (sqimap_mailbox_exists($imap_stream, $trash_folder) &&  ($mailbox != $trash_folder)) ) {
-        $read = sqimap_run_command ($imap_stream, "COPY $msgs_id " . sqimap_encode_mailbox_name($trash_folder), true, $response, $message, TRUE);
+        $bRes = sqimap_msgs_list_copy ($imap_stream, $id, $trash_folder);
+    }
+    if ($bRes) {
+        return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true);
+    } else {
+        return false;
     }
-    $read = sqimap_run_command ($imap_stream, "STORE $msgs_id +FLAGS (\\Deleted)", true, $response, $message, TRUE);
 }
 
 
@@ -92,7 +106,9 @@ function sqimap_messages_flag ($imap_stream, $start, $end, $flag, $handle_errors
 function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) {
     $msgs_id = sqimap_message_list_squisher($id);
     $set_string = ($set ? '+' : '-');
-    $read = sqimap_run_command ($imap_stream, "STORE $msgs_id ".$set_string."FLAGS ($flag)", $handle_errors, $response, $message, TRUE);
+    $aResponse = sqimap_run_command_list($imap_stream, "STORE $msgs_id ".$set_string."FLAGS ($flag)", $handle_errors, $response, $message, TRUE);
+    // parse the fetch response
+    return parseFetch($aResponse);
 }
 
 /** @deprecated */
@@ -131,13 +147,13 @@ function sqimap_message_list_squisher($messages_array) {
 
 /**
 * Retrieves an array with a sorted uid list. Sorting is done on the imap server
-*
+* @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
 * @param resource $imap_stream IMAP socket connection
 * @param string $sSortField Field to sort on
 * @param bool $reverse Reverse order search
 * @return array $id sorted uid list
 */
-function sqimap_get_sort_order ($imap_stream, $sSortField,$reverse) {
+function sqimap_get_sort_order ($imap_stream, $sSortField, $reverse, $search='ALL') {
     global  $default_charset,
             $sent_folder;
 
@@ -149,22 +165,33 @@ function sqimap_get_sort_order ($imap_stream, $sSortField,$reverse) {
         if ($reverse) {
             $sSortField = 'REVERSE '.$sSortField;
         }
-        $query = "SORT ($sSortField) ".strtoupper($default_charset).' ALL';
-        $sort_test = sqimap_run_command ($imap_stream, $query, true, $response, $message, TRUE);
-    }
-    if (isset($sort_test[0])) {
-        for ($i=0,$iCnt=count($sort_test);$i<$iCnt;++$i) {
-            if (preg_match("/^\* SORT (.+)$/", $sort_test[$i], $regs)) {
-                $id = preg_split("/ /", trim($regs[1]));
-            break;
-            }
+        $query = "SORT ($sSortField) ".strtoupper($default_charset)." $search";
+        // FIX ME sqimap_run_command should return the parsed data accessible by $aDATA['SORT']
+        $aData = sqimap_run_command ($imap_stream, $query, false, $response, $message, TRUE);
+        /* fallback to default charset */
+        if ($response == 'NO' && strpos($message,'[BADCHARSET]') !== false) {
+            $query = "SORT ($sSortField) US-ASCII $search";
+            $aData = sqimap_run_command ($imap_stream, $query, true, $response, $message, TRUE);
         }
     }
-    if (!preg_match("/OK/", $response)) {
-        return false;
+
+    if ($response == 'OK') {
+        return parseUidList($aData,'SORT');
     } else {
-        return $id;
+        return false;
+    }
+}
+
+function parseUidList($aData,$sCommand) {
+    $aUid = array();
+    if (isset($aData) && count($aData)) {
+        for ($i=0,$iCnt=count($aData);$i<$iCnt;++$i) {
+            if (preg_match("/^\* $sCommand (.+)$/", $aData[$i], $aMatch)) {
+                $aUid += preg_split("/ /", trim($aMatch[1]));
+            }
+        }
     }
+    return array_unique($aUid);
 }
 
 /**
@@ -175,12 +202,15 @@ function sqimap_get_sort_order ($imap_stream, $sSortField,$reverse) {
 * @param bool $reverse Reverse order search
 * @return array $aUid sorted uid list
 */
-function get_squirrel_sort ($imap_stream, $sSortField, $reverse = false) {
+function get_squirrel_sort ($imap_stream, $sSortField, $reverse = false, $aUid = NULL) {
+    if ($aUID === NULL) {
+
+    }
     if ($sSortField != 'RFC822.SIZE' && $sSortField != 'INTERNALDATE') {
-        $msgs = sqimap_get_small_header_list($imap_stream, false, '*',
+        $msgs = sqimap_get_small_header_list($imap_stream, $aUid,
                                       array($sSortField), array());
     } else {
-        $msgs = sqimap_get_small_header_list($imap_stream, false, '*',
+        $msgs = sqimap_get_small_header_list($imap_stream, $aUid,
                                       array(), array($sSortField));
     }
     $aUid = array();
@@ -213,7 +243,7 @@ function get_squirrel_sort ($imap_stream, $sSortField, $reverse = false) {
             $walk = true;
         }
         foreach ($msgs as $item) {
-            $aUid[$item['ID']] = $item[$sSortField];
+            $aUid[$item['UID']] = $item[$sSortField];
         }
         natcasesort($aUid);
         $aUid = array_keys($aUid);
@@ -239,7 +269,7 @@ function get_squirrel_sort ($imap_stream, $sSortField, $reverse = false) {
             $sSortField = 'SIZE';
         }
         foreach ($msgs as $item) {
-            $aUid[$item['ID']] = (isset($item[$sSortField])) ? $item[$sSortField] : 0;
+            $aUid[$item['UID']] = (isset($item[$sSortField])) ? $item[$sSortField] : 0;
         }
         if ($reverse) {
             arsort($aUid,SORT_NUMERIC);
@@ -380,26 +410,25 @@ function get_parent_level ($thread_new) {
 /**
 * Returns an array with each element as a string representing one
 * message-thread as returned by the IMAP server.
+* @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
 */
-function get_thread_sort ($imap_stream) {
+function get_thread_sort ($imap_stream, $search='ALL') {
     global $thread_new, $sort_by_ref, $default_charset, $server_sort_array, $indent_array;
-    if (sqsession_is_registered('thread_new')) {
-        sqsession_unregister('thread_new');
-    }
-    if (sqsession_is_registered('indent_array')) {
-        sqsession_unregister('indent_array');
-    }
-    if (sqsession_is_registered('server_sort_array')) {
-        sqsession_unregister('server_sort_array');
-    }
+
     $thread_temp = array ();
     if ($sort_by_ref == 1) {
         $sort_type = 'REFERENCES';
     } else {
         $sort_type = 'ORDEREDSUBJECT';
     }
-    $query = "THREAD $sort_type ".strtoupper($default_charset)." ALL";
-    $thread_test = sqimap_run_command ($imap_stream, $query, true, $response, $message, TRUE);
+    $query = "THREAD $sort_type ".strtoupper($default_charset)." $search";
+
+    $thread_test = sqimap_run_command ($imap_stream, $query, false, $response, $message, TRUE);
+    /* fallback to default charset */
+    if ($response == 'NO' && strpos($message,'[BADCHARSET]') !== false) {
+        $query = "THREAD $sort_type US-ASCII $search";
+        $thread_test = sqimap_run_command ($imap_stream, $query, true, $response, $message, TRUE);
+    }
     if (isset($thread_test[0])) {
         for ($i=0,$iCnt=count($thread_test);$i<$iCnt;++$i) {
             if (preg_match("/^\* THREAD (.+)$/", $thread_test[$i], $regs)) {
@@ -452,7 +481,7 @@ function get_thread_sort ($imap_stream) {
             }
         }
     }
-    sqsession_register($thread_new, 'thread_new');
+
     $thread_new = array_reverse($thread_new);
     /* place the threads after each other in one string */
     $thread_list = implode(" ", $thread_new);
@@ -462,10 +491,7 @@ function get_thread_sort ($imap_stream) {
     $server_sort_array = $thread_list;
 
     $indent_array = get_parent_level ($thread_new);
-    sqsession_register($indent_array, 'indent_array');
-
-    sqsession_register($server_sort_array, 'server_sort_array');
-    return $thread_list;
+    return array($thread_list,$indent_array);
 }
 
 
@@ -532,17 +558,17 @@ function parseArray($read,&$i) {
     }
 }
 
-function sqimap_get_small_header_list ($imap_stream, $msg_list, $show_num=false,
+function sqimap_get_small_header_list ($imap_stream, $msg_list,
     $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type'),
     $aFetchItems = array('FLAGS', 'RFC822.SIZE', 'INTERNALDATE')) {
 
-    $messages = array();
+    $aMessageList = array();
     $read_list = array();
 
     $bUidFetch = ! in_array('UID', $aFetchItems, true);
 
     /* Get the small headers for each message in $msg_list */
-    if ($show_num != '999999' && $show_num != '*' ) {
+    if ($msg_list !== NULL) {//$show_num != -1 && $show_num != '*' ) {
         $msgs_str = sqimap_message_list_squisher($msg_list);
         /*
         * We need to return the data in the same order as the caller supplied
@@ -551,15 +577,14 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list, $show_num=false,
         */
         if ($bUidFetch) {
             for ($i = 0; $i < sizeof($msg_list); $i++) {
-                $messages["$msg_list[$i]"] = array();
+                $aMessageList["$msg_list[$i]"] = array();
             }
         }
     } else {
         $msgs_str = '1:*';
+        $aId = array();
     }
 
-
-
     /*
      * Create the query
      */
@@ -574,11 +599,14 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list, $show_num=false,
         $sFetchItems .= ' BODY.PEEK[HEADER.FIELDS ('.$sHeaderFields.')]';
     }
     $query .= trim($sFetchItems) . ')';
+    $aResponse = sqimap_run_command_list ($imap_stream, $query, true, $response, $message, $bUidFetch);
+    $aMessages = parseFetch($aResponse,$aMessageList);
+    array_reverse($aMessages);
+    return $aMessages;
+}
 
-    $read_list = sqimap_run_command_list ($imap_stream, $query, true, $response, $message, $bUidFetch);
-    $i = 0;
-
-    foreach ($read_list as $r) {
+function parseFetch($aResponse,$aMessageList = array()) {
+    foreach ($aResponse as $r) {
         $msg = array();
         // use unset because we do isset below
         $read = implode('',$r);
@@ -590,6 +618,7 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list, $show_num=false,
         /* extract the message id */
         $i_space = strpos($read,' ',2);
         $id = substr($read,2,$i_space-2);
+        $msg['ID'] = $id;
         $fetch = substr($read,$i_space+1,5);
         if (!is_numeric($id) && $fetch !== 'FETCH') {
             $msg['ERROR'] = $read; // htmlspecialchars should be done just before display. this is backend code
@@ -711,15 +740,15 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list, $show_num=false,
             }
         }
         $msgi ="$unique_id";
-        $msg['ID'] = $unique_id;
+        $msg['UID'] = $unique_id;
 
-        $messages[$msgi] = $msg;
+        $aMessageList[$msgi] = $msg;
         ++$msgi;
     }
-    array_reverse($messages);
-    return $messages;
+    return $aMessageList;
 }
 
+
 function sqimap_parse_envelope($read, &$i, &$msg) {
     $arg_no = 0;
     $arg_a = array();
index b256a43ec3e1e8e49597fe03d4a3361e9fbd0987..165c6d63f34e9f05cf440cb87dd112e443a3ffb9 100644 (file)
@@ -19,6 +19,7 @@ require_once(SM_PATH . 'functions/html.php');
 require_once(SM_PATH . 'class/html.class.php');
 require_once(SM_PATH . 'functions/imap_mailbox.php');
 require_once(SM_PATH . 'functions/imap_messages.php');
+require_once(SM_PATH . 'functions/imap_asearch.php');
 require_once(SM_PATH . 'functions/mime.php');
 require_once(SM_PATH . 'functions/forms.php');
 
@@ -27,6 +28,11 @@ require_once(SM_PATH . 'functions/forms.php');
 */
 define('PG_SEL_MAX', 10);
 
+/**
+* The number of pages to cache msg headers
+*/
+define('SQM_MAX_PAGES_IN_CACHE',5);
+
 /**
 * Sort constants used for sorting of messages
 */
@@ -45,7 +51,17 @@ define('SQSORT_CC_ASC',11);
 define('SQSORT_CC_DEC',12);
 define('SQSORT_INT_DATE_ASC',13);
 define('SQSORT_INT_DATE_DEC',14);
-define('SQSORT_THREAD',42);
+
+define('SQSORT_THREAD',32);
+
+
+define('MBX_PREF_SORT',0);
+define('MBX_PREF_LIMIT',1);
+define('MBX_PREF_AUTO_EXPUNGE',2);
+define('MBX_PREF_INTERNALDATE',3);
+define('SQM_MAX_MBX_IN_CACHE',3);
+// define('MBX_PREF_FUTURE',unique integer key);
+
 /**
 * @param mixed $start UNDOCUMENTED
 */
@@ -115,7 +131,7 @@ function printMessageInfo($aMsg) {
     } else {
        $sDate = (isset($msg['DATE'])) ? getDateString(getTimeStamp(explode(' ',$msg['DATE']))) : '';
     }
-    $iId      = (isset($msg['ID'])) ? $msg['ID'] : false;
+    $iId      = (isset($msg['UID'])) ? $msg['UID'] : false;
 
     if (!$iId) {
         return;
@@ -325,7 +341,7 @@ function printMessageInfo($aMsg) {
                     $td_str .= str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;",$iIndent);
                 }
                 $td_str .= '<a href="read_body.php?mailbox='.$urlMailbox
-                        .  '&amp;passed_id='. $msg["ID"]
+                        .  '&amp;passed_id='. $iId
                         .  '&amp;startMessage='.$start_msg.$searchstr.'"';
                 $td_str .= ' ' .concat_hook_function('subject_link', array($start_msg, $searchstr));
                 if ($subject != $sSubject) {
@@ -449,13 +465,256 @@ function printMessageInfo($aMsg) {
     }
 }
 
+
+function setUserPref($username, $pref, $value) {
+    global $data_dir;
+    setPref($data_dir,$username,$pref,$value);
+}
+
+/**
+ * Selects a mailbox for header retrieval.
+ * Cache control for message headers is embedded.
+ *
+ * @param resource $imapConnection imap socket handle
+ * @param string   $mailbox mailbox to select and retrieve message headers from
+ * @param array    $aConfig array with system config settings and incoming vars
+ * @param array    $aProps mailbox specific properties
+ * @return array   $aMailbox mailbox array with all relevant information
+ * @author Marc Groot Koerkamp
+ */
+function sqm_api_mailbox_select($imapConnection,$mailbox,$aConfig,$aProps) {
+    /**
+     * NB: retrieve this from the session before accessing this function
+     * and make sure you write it back at the end of the script after
+     * the aMailbox var is added so that the headers are added to the cache
+     */
+    global $mailbox_cache;
+    /**
+     * In case the properties arrays are empty set the defaults.
+     */
+    $aDefaultMbxPref = array ();
+//                          MBX_PREF_SORT => 0,
+//                          MBX_PREF_LIMIT => 15,
+//                          MBX_PREF_AUTO_EXPUNGE => 0,
+//                          MBX_PREF_INTERNALDATE => 0
+//                           );
+    /* array_merge doesn't work with integers as keys */
+//    foreach ($aDefaultMbxPref as $key => $value) {
+//        if (!isset($aProps[$key])) {
+//            $aProps[$key] = $value;
+//        }
+//    }
+    $aDefaultConfigProps = array(
+//                'allow_thread_sort' => 0,
+                'allow_server_sort' => sqimap_capability($imapConnection,'SORT'),
+//                'charset'           => 'US-ASCII',
+                'user'              => false, /* no pref storage if false */
+                'setindex'          => 0,
+//                'search'            => 'ALL',
+                'max_cache_size'    => SQM_MAX_MBX_IN_CACHE
+                );
+
+    $aConfig = array_merge($aDefaultConfigProps,$aConfig);
+    $iSetIndx = $aConfig['setindex'];
+
+    $aMbxResponse = sqimap_mailbox_select($imapConnection, $mailbox);
+
+    if ($mailbox_cache) {
+        if (isset($mailbox_cache[$mailbox])) {
+            $aCachedMailbox = $mailbox_cache[$mailbox];
+        } else {
+            $aCachedMailbox = false;
+        }
+            /* cleanup cache */
+        if (count($mailbox_cache) > $aConfig['max_cache_size'] -1) {
+            $aTime = array();
+            foreach($mailbox_cache as $cachedmailbox => $aVal) {
+                $aTime[$aVal['TIMESTAMP']] = $cachedmailbox;
+            }
+            if (ksort($aTime,SORT_NUMERIC)) {
+                for ($i=0,$iCnt=count($mailbox_cache);$i<($iCnt-$aConfig['max_cache_size']);++$i) {
+                    $sOldestMbx = array_shift($aTime);
+                    /**
+                     * Remove only the UIDSET and MSG_HEADERS from cache because those can
+                     * contain large amounts of data.
+                     */
+                    if (isset($mailbox_cache[$sOldestMbx]['UIDSET'])) {
+                        $mailbox_cache[$sOldestMbx]['UIDSET']= false;
+                    }
+                    if (isset($mailbox_cache[$sOldestMbx]['MSG_HEADERS'])) {
+                        $mailbox_cache[$sOldestMbx]['MSG_HEADERS'] = false;
+                    }
+                }
+            }
+        }
+
+    } else {
+        $aCachedMailbox = false;
+    }
+
+    /**
+     * Deal with imap servers that do not return the required UIDNEXT or
+     * UIDVALIDITY response
+     * from a SELECT call (since rfc 3501 it's required).
+     */
+    if (!isset($aMbxResponse['UIDNEXT']) || !isset($aMbxResponse['UIDVALIDITY'])) {
+        $aStatus = sqimap_status_messages($imapConnection,$mailbox,
+                                        array('UIDNEXT','UIDVALIDITY'));
+        $aMbxResponse['UIDNEXT'] = $aStatus['UIDNEXT'];
+        $aMbxResponse['UIDVALIDTY'] = $aStatus['UIDVALIDITY'];
+    }
+
+    $aMailbox['UIDSET'][$iSetIndx] = false;
+    $aMailbox['ID'] = false;
+    $aMailbox['SETINDEX'] = $iSetIndx;
+
+    if ($aCachedMailbox) {
+        /**
+         * Validate integrity of cached data
+         */
+        if ($aCachedMailbox['EXISTS'] == $aMbxResponse['EXISTS'] &&
+            $aMbxResponse['EXISTS'] &&
+            $aCachedMailbox['UIDVALIDITY'] == $aMbxResponse['UIDVALIDITY'] &&
+            $aCachedMailbox['UIDNEXT']  == $aMbxResponse['UIDNEXT'] &&
+            isset($aCachedMailbox['SEARCH'][$iSetIndx]) &&
+            (!isset($aConfig['search']) || /* always set search from the searchpage */
+             $aCachedMailbox['SEARCH'][$iSetIndx] == $aConfig['search'])) {
+            if (isset($aCachedMailbox['MSG_HEADERS'])) {
+                $aMailbox['MSG_HEADERS'] = $aCachedMailbox['MSG_HEADERS'];
+            }
+            $aMailbox['ID'] =  $aCachedMailbox['ID'];
+            if (isset($aCachedMailbox['UIDSET'][$iSetIndx]) && $aCachedMailbox['UIDSET'][$iSetIndx]) {
+                if (isset($aProps[MBX_PREF_SORT]) &&  $aProps[MBX_PREF_SORT] != $aCachedMailbox['SORT'] ) {
+                    $newsort = $aProps[MBX_PREF_SORT];
+                    $oldsort = $aCachedMailbox['SORT'];
+                    /**
+                     * If it concerns a reverse sort we do not need to invalidate
+                     * the cached sorted UIDSET, a reverse is sufficient.
+                     */
+                    if ((($newsort % 2) && ($newsort + 1 == $oldsort)) ||
+                        (!($newsort % 2) && ($newsort - 1 == $oldsort))) {
+                        $aMailbox['UIDSET'][$iSetIndx] = array_reverse($aCachedMailbox['UIDSET'][$iSetIndx]);
+                    } else {
+                        $server_sort_array = false;
+                        $aMailbox['MSG_HEADERS'] = false;
+                        $aMailbox['ID'] = false;
+                    }
+                    // store the new sort value in the mailbox pref
+                    if ($aConfig['user']) {
+                        // FIXME, in ideal situation, we write back the
+                        // prefs at the end of the script
+                        setUserPref($aConfig['user'],"pref_$mailbox",serialize($aProps));
+                    }
+                } else {
+                    $aMailbox['UIDSET'][$iSetIndx] = $aCachedMailbox['UIDSET'][$iSetIndx];
+                }
+            }
+        }
+    }
+    /**
+     * Restore the offset in the paginator if no new offset is provided.
+     */
+    if (isset($aMailbox['UIDSET'][$iSetIndx]) && !isset($aConfig['offset']) && $aCachedMailbox['OFFSET']) {
+        $aMailbox['OFFSET'] =  $aCachedMailbox['OFFSET'];
+        $aMailbox['PAGEOFFSET'] =  $aCachedMailbox['PAGEOFFSET'];
+    } else {
+        $aMailbox['OFFSET'] = (isset($aConfig['offset']) && $aConfig['offset']) ? $aConfig['offset'] -1 : 0;
+        $aMailbox['PAGEOFFSET'] = (isset($aConfig['offset']) && $aConfig['offset']) ? $aConfig['offset'] : 1;
+    }
+
+    /**
+     * Restore the showall value no new showall value is provided.
+     */
+    if (isset($aMailbox['UIDSET'][$iSetIndx]) && !isset($aConfig['showall']) &&
+        isset($aCachedMailbox['SHOWALL'][$iSetIndx]) && $aCachedMailbox['SHOWALL'][$iSetIndx]) {
+        $aMailbox['SHOWALL'][$iSetIndx] =  $aCachedMailbox['SHOWALL'][$iSetIndx];
+    } else {
+        $aMailbox['SHOWALL'][$iSetIndx] = (isset($aConfig['showall']) && $aConfig['showall']) ? 1 : 0;
+    }
+
+    if (!isset($aProps[MBX_PREF_SORT]) && isset($aCachedMailbox['SORT'])) {
+        $aMailbox['SORT'] = $aCachedMailbox['SORT'];
+    } else {
+        $aMailbox['SORT'] =  (isset($aProps[MBX_PREF_SORT])) ? $aProps[MBX_PREF_SORT] : 0;
+    }
+
+    if (!isset($aProps[MBX_PREF_LIMIT]) && isset($aCachedMailbox['LIMIT'])) {
+        $aMailbox['LIMIT'] = $aCachedMailbox['LIMIT'];
+    } else {
+        $aMailbox['LIMIT'] =  (isset($aProps[MBX_PREF_LIMIT])) ? $aProps[MBX_PREF_LIMIT] : 15;
+    }
+
+    if (!isset($aProps[MBX_PREF_INTERNALDATE]) && isset($aCachedMailbox['INTERNALDATE'])) {
+        $aMailbox['INTERNALDATE'] = $aCachedMailbox['INTERNALDATE'];
+    } else {
+        $aMailbox['INTERNALDATE'] =  (isset($aProps[MBX_PREF_INTERNALDATE])) ? $aProps[MBX_PREF_INTERNALDATE] : false;
+    }
+
+    if (!isset($aProps[MBX_PREF_AUTO_EXPUNGE]) && isset($aCachedMailbox['AUTO_EXPUNGE'])) {
+        $aMailbox['AUTO_EXPUNGE'] = $aCachedMailbox['AUTO_EXPUNGE'];
+    } else {
+        $aMailbox['AUTO_EXPUNGE'] =  (isset($aProps[MBX_PREF_AUTO_EXPUNGE])) ? $aProps[MBX_PREF_AUTO_EXPUNGE] : false;
+    }
+
+    if (!isset($aConfig['allow_thread_sort']) && isset($aCachedMailbox['ALLOW_THREAD'])) {
+        $aMailbox['ALLOW_THREAD'] = $aCachedMailbox['ALLOW_THREAD'];
+    } else {
+        $aMailbox['ALLOW_THREAD'] =  (isset($aConfig['allow_thread_sort'])) ? $aConfig['allow_thread_sort'] : false;
+    }
+
+    if (!isset($aConfig['search']) && isset($aCachedMailbox['SEARCH'][$iSetIndx])) {
+        $aMailbox['SEARCH'][$iSetIndx] = $aCachedMailbox['SEARCH'][$iSetIndx];
+    } else {
+        $aMailbox['SEARCH'][$iSetIndx] =  (isset($aConfig['search'])) ? $aConfig['search'] : 'ALL';
+    }
+
+    if (!isset($aConfig['charset']) && isset($aCachedMailbox['CHARSET'][$iSetIndx])) {
+        $aMailbox['CHARSET'][$iSetIndx] = $aCachedMailbox['CHARSET'][$iSetIndx];
+    } else {
+        $aMailbox['CHARSET'][$iSetIndx] =  (isset($aConfig['charset'])) ? $aConfig['charset'] : 'US-ASCII';
+    }
+
+    $aMailbox['NAME'] = $mailbox;
+    $aMailbox['EXISTS'] = $aMbxResponse['EXISTS'];
+    $aMailbox['SEEN'] = (isset($aMbxResponse['SEEN'])) ? $aMbxResponse['SEEN'] : $aMbxResponse['EXISTS'];
+    $aMailbox['RECENT'] = (isset($aMbxResponse['RECENT'])) ? $aMbxResponse['RECENT'] : 0;
+    $aMailbox['UIDVALIDITY'] = $aMbxResponse['UIDVALIDITY'];
+    $aMailbox['UIDNEXT'] = $aMbxResponse['UIDNEXT'];
+    $aMailbox['PERMANENTFLAGS'] = $aMbxResponse['PERMANENTFLAGS'];
+    $aMailbox['RIGHTS'] = $aMbxResponse['RIGHTS'];
+
+
+
+    /* decide if we are thread sorting or not */
+    if (!$aMailbox['ALLOW_THREAD']) {
+        if ($aMailbox['SORT'] & SQSORT_THREAD) {
+            $aMailbox['SORT'] -= SQSORT_THREAD;
+        }
+    }
+    if ($aMailbox['SORT'] & SQSORT_THREAD) {
+        $aMailbox['SORT_METHOD'] = 'THREAD';
+        $aMailbox['THREAD_INDENT'] = $aCachedMailbox['THREAD_INDENT'];
+    } else if (isset($aConfig['allow_server_sort']) && $aConfig['allow_server_sort']) {
+        $aMailbox['SORT_METHOD'] = 'SERVER';
+        $aMailbox['THREAD_INDENT'] = false;
+    } else {
+        $aMailbox['SORT_METHOD'] = 'SQUIRREL';
+        $aMailbox['THREAD_INDENT'] = false;
+    }
+
+    /* set a timestamp for cachecontrol */
+    $aMailbox['TIMESTAMP'] = time();
+    return $aMailbox;
+}
+
+
+
 /**
-* Does the $sort $_GET var to field mapping
+* Does the $srt $_GET var to field mapping
 *
-* @param int $sort Field to sort on
+* @param int $srt Field to sort on
 * @param bool $bServerSort Server sorting is true
-* @param mixed $key UNDOCUMENTED
-* @return string $sSortField Field tosort on
+* @return string $sSortField Field to sort on
 */
 function getSortField($sort,$bServerSort) {
     switch($sort) {
@@ -499,169 +758,270 @@ function getSortField($sort,$bServerSort) {
     return $sSortField;
 }
 
-function get_sorted_msgs_list($imapConnection,$aMailbox,&$error) {
+function get_sorted_msgs_list($imapConnection,&$aMailbox,&$error) {
+    $iSetIndx = (isset($aMailbox['SETINDEX'])) ? $aMailbox['SETINDEX'] : 0;
     $bDirection = ($aMailbox['SORT'] % 2);
     $error = false;
+    if (!$aMailbox['SEARCH'][$iSetIndx]) {
+        $aMailbox['SEARCH'][$iSetIndx] = 'ALL';
+    }
     switch ($aMailbox['SORT_METHOD']) {
       case 'THREAD':
-        $id = get_thread_sort($imapConnection);
-        if ($id === false) {
+        $aRes = get_thread_sort($imapConnection,$aMailbox['SEARCH'][$iSetIndx]);
+        if ($aRes === false) {
             $error = '<b><small><center><font color=red>' .
                     _("Thread sorting is not supported by your IMAP server.") . '<br />' .
                     _("Please report this to the system administrator.").
                     '</center></small></b>';
+            $aMailbox['SORT'] -= SQSORT_THREAD;
+        } else {
+            $aMailbox['UIDSET'][$iSetIndx] = $aRes[0];
+            $aMailbox['THREAD_INDENT'][$iSetIndx] = $aRes[1];
         }
         break;
       case 'SERVER':
         $sSortField = getSortField($aMailbox['SORT'],true);
-        $id = sqimap_get_sort_order($imapConnection, $sSortField, $bDirection);
+        $id = sqimap_get_sort_order($imapConnection, $sSortField, $bDirection, $aMailbox['SEARCH'][$iSetIndx]);
         if ($id === false) {
             $error =  '<b><small><center><font color=red>' .
                 _( "Server-side sorting is not supported by your IMAP server.") . '<br />' .
                 _("Please report this to the system administrator.").
                 '</center></small></b>';
+        } else {
+            $aMailbox['UIDSET'][$iSetIndx] = $id;
         }
         break;
       default:
+        $id = NULL;
+        if ($aMailbox['SEARCH'][$iSetIndx] != 'ALL') {
+            $id = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]);
+        }
         $sSortField = getSortField($aMailbox['SORT'],false);
-        $id = get_squirrel_sort($imapConnection, $sSortField, $bDirection);
+        $aMailbox['UIDSET'][$iSetIndx] = get_squirrel_sort($imapConnection, $sSortField, $bDirection, $id);
         break;
     }
-    return $id;
+    return $error;
 }
 
-/**
-* This function loops through a group of messages in the mailbox
-* and shows them to the user.
-*
-* @param mixed $imapConnection
-* @param array $aMailbox associative array with mailbox related vars
-*/
-function showMessagesForMailbox($imapConnection, $aMailbox) {
-    global $msgs, $server_sort_array, $indent_array, $color;
 
-    // to retrieve the internaldate pref: (I know this is not the right place to do that, move up in front
-    // and use a properties array as function argument to provide user preferences
-    global $data_dir, $username;
 
-    /* if there's no messages in this folder */
-    if ($aMailbox['EXISTS'] == 0) {
-        $string = '<b>' . _("THIS FOLDER IS EMPTY") . '</b>';
-        echo '    <table width="100%" cellpadding="1" cellspacing="0" align="center"'.' border="0" bgcolor="'.$color[9].'">';
-        echo '     <tr><td>';
-        echo '       <table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.$color[4].'">';
-        echo '        <tr><td><br />';
-        echo '            <table cellpadding="1" cellspacing="5" align="center" border="0">';
-        echo '              <tr>' . html_tag( 'td', $string."\n", 'left')
-                            . '</tr>';
-        echo '            </table>';
-        echo '        <br /></td></tr>';
-        echo '       </table></td></tr>';
-        echo '    </table>';
-        return;
+
+function fetchMessageHeaders($imapConnection, &$aMailbox) {
+
+    /**
+     * Retrieve the UIDSET.
+     * Setindex is used to be able to store multiple uid sets. That will make it
+     * possible to display the mailbox multiple times in different sort order
+     * or to store serach results separate from normal mailbox view.
+     */
+    $iSetIndx =  (isset($aMailbox['SETINDEX'])) ? $aMailbox['SETINDEX'] : 0;
+
+    $iLimit = ($aMailbox['SHOWALL'][$iSetIndx]) ? $aMailbox['EXISTS'] : $aMailbox['LIMIT'];
+    /**
+     * Adjust the start_msg
+     */
+    $start_msg = $aMailbox['PAGEOFFSET'];
+    if($aMailbox['PAGEOFFSET'] > $aMailbox['EXISTS']) {
+        $start_msg -= $aMailbox['LIMIT'];
+        if($start_msg < 1) {
+            $start_msg = 1;
+        }
+    }
+
+
+    if (is_array($aMailbox['UIDSET'])) {
+        $aUid =& $aMailbox['UIDSET'][$iSetIndx];
     } else {
-        /*
-        * Adjust the start_msg
-        */
-        $start_msg = $aMailbox['PAGEOFFSET'];
-        if($aMailbox['PAGEOFFSET'] > $aMailbox['EXISTS']) {
-            $start_msg -= $aMailbox['LIMIT'];
-            if($start_msg < 1) {
-                $start_msg = 1;
+        $aUid = false;
+    }
+
+    // initialize the fields we want to retrieve:
+    $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type');
+    $aFetchItems = array('FLAGS', 'RFC822.SIZE');
+
+    // Are we sorting on internaldate then retrieve the internaldate value as well
+    if ($aMailbox['INTERNALDATE']) {
+        $aFetchItems[] = 'INTERNALDATE';
+    }
+
+
+    /**
+     * A uidset with sorted uid's is available. We can use the cache
+     */
+    if (($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') &&
+         isset($aUid) && $aUid ) {
+
+        // limit the cache to SQM_MAX_PAGES_IN_CACHE
+        if (!$aMailbox['SHOWALL'][$iSetIndx]) {
+            $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE;
+            $iCacheSize = count($aMailbox['MSG_HEADERS']);
+            if ($iCacheSize > $iMaxMsgs) {
+                $iReduce = $iCacheSize - $iMaxMsgs;
+                foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) {
+                    if ($iReduce) {
+                        unset($aMailbox['MSG_HEADERS'][$iUid]);
+                    } else {
+                        break;
+                    }
+                    --$iReduce;
+                }
             }
         }
-        $aMailbox['SEARCH']     = array(); // Alex maybe you can change this so that you can use it from a search
-
-        // initialize the fields we want to retrieve:
-        $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type');
-        $aFetchItems = array('FLAGS', 'RFC822.SIZE');
-        // Are we sorting on internaldate then retrieve the internaldate value as well
-        $internaldate = getPref($data_dir, $username, 'internal_date_sort');
-        if ($internaldate) {
-            $aFetchItems[] = 'INTERNALDATE';
+
+        $id_slice = array_slice($aUid,$start_msg-1,$iLimit);
+        /* do some funky cache checks */
+        $aUidCached = array_keys($aMailbox['MSG_HEADERS']);
+        $aUidNotCached = array_values(array_diff($id_slice,$aUidCached));
+        /**
+         * $aUidNotCached contains an array with UID's which need to be fetched to
+         * complete the needed message headers.
+         */
+        if (count($aUidNotCached)) {
+            $aMsgs = sqimap_get_small_header_list($imapConnection,$aUidNotCached,
+                                                    $aHeaderFields,$aFetchItems);
+            // append the msgs to the existend headers
+            $aMailbox['MSG_HEADERS'] += $aMsgs;
         }
 
-        if ($aMailbox['SORT'] != SQSORT_NONE && isset($aMailbox['UIDSET']) &&
-                      $aMailbox['UIDSET'] ) {
-            $id = $aMailbox['UIDSET'];
-            if (sqsession_is_registered('msgs')) {
-                sqsession_unregister('msgs');
+    } else {
+        /**
+         * Initialize the sorted UID list and fetch the visible message headers
+         */
+        if ($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') {//  || $aMailbox['SORT_METHOD'] & SQSORT_THREAD 'THREAD') {
+
+            $error = false;
+            if ($aMailbox['SEARCH'][$iSetIndx] && $aMailbox['SORT'] == 0) {
+                $aUid = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]);
+            } else {
+                $error = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
+                $aUid = $aMailbox['UIDSET'][$iSetIndx];
             }
-            $id_slice = array_slice($id,$start_msg-1,$aMailbox['LIMIT']);
-            if (count($id_slice)) {
-                $msgs = sqimap_get_small_header_list($imapConnection,$id_slice,$aMailbox['LIMIT'],
-                                                     $aHeaderFields,$aFetchItems);
+            if ($error === false) {
+                $id_slice = array_slice($aUid,$aMailbox['OFFSET'], $iLimit);
+                if (count($id_slice)) {
+                    $aMailbox['MSG_HEADERS'] = sqimap_get_small_header_list($imapConnection,$id_slice,
+                        $aHeaderFields,$aFetchItems);
+                } else {
+                    return false;
+                }
 
             } else {
-                return false;
+                // FIX ME, format message and fallback to squirrel sort
+                if ($error) {
+                    echo $error;
+                }
             }
-            // FIX ME, move to msgs cache bound to a mailbox
-            sqsession_register($msgs, 'msgs');
         } else {
-            if (sqsession_is_registered('server_sort_array')) {
-                sqsession_unregister('server_sort_array');
+            // limit the cache to SQM_MAX_PAGES_IN_CACHE
+            if (!$aMailbox['SHOWALL'][$iSetIndx] && isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) {
+                $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE;
+                $iCacheSize = count($aMailbox['MSG_HEADERS']);
+                if ($iCacheSize > $iMaxMsgs) {
+                    $iReduce = $iCacheSize - $iMaxMsgs;
+                    foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) {
+                        if ($iReduce) {
+                            $iId = $aMailbox['MSG_HEADERS'][$iUid]['ID'];
+                            unset($aMailbox['MSG_HEADERS'][$iUid]);
+                            unset($aMailbox['ID'][$iId]);
+                        } else {
+                            break;
+                        }
+                        --$iReduce;
+                    }
+                }
             }
 
-            if ($aMailbox['SORT'] != SQSORT_NONE  || $aMailbox['SORT_METHOD'] == 'THREAD') {
-                $id = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
-                if ($id !== false) {
-                    $id_slice = array_slice($id,$aMailbox['OFFSET'], $aMailbox['LIMIT']);
-                    if (count($id_slice)) {
-                        $msgs = sqimap_get_small_header_list($imapConnection,$id_slice,$aMailbox['LIMIT'],
-                              $aHeaderFields,$aFetchItems);
-                    } else {
-                        // FIX ME do error handling
-                        return false;
-                    }
-                } else {
-                    // FIX ME, format message and fallback to squirrel sort
-                    if ($error) {
-                        echo $error;
+            /**
+            * retrieve messages by sequence id's and fetch the UID to retrieve
+            * the UID. for sorted lists this is not needed because a UID FETCH
+            * automaticly add the UID value in fetch results
+            **/
+            $aFetchItems[] = 'UID';
+
+            //create id range
+            $iRangeStart = $aMailbox['EXISTS'] - $aMailbox['OFFSET'];
+            $iRangeEnd   = ($iRangeStart > $iLimit) ?
+                            ($iRangeStart - $iLimit+1):1;
+
+            $id_slice = range($iRangeStart, $iRangeEnd);
+            /**
+             * Non sorted mailbox with cached message headers
+             */
+            if (isset($aMailbox['ID']) && is_array($aMailbox['ID'])) {
+                // the fetched id => uid relation
+                $aId = $aMailbox['ID'];
+                $aIdCached = array();
+                foreach ($aId as $iId => $iUid) {
+                    if (isset($aMailbox['MSG_HEADERS'][$iUid])) {
+                        if ($iId <= $iRangeStart && $iId >= $iRangeEnd) {
+                            $aIdCached[] = $iId;
+                        }
                     }
                 }
+                $aIdNotCached = array_diff($id_slice,$aIdCached);
             } else {
-                /**
-                * retrieve messages by sequence id's and fetch the UID to retrieve
-                * the UID. for sorted lists this is not needed because a UID FETCH
-                * automaticly add the UID value in fetch results
-                **/
-                $aFetchItems[] = 'UID';
-
-                //create id range
-                $iRangeStart = $aMailbox['EXISTS'] - $aMailbox['OFFSET'];
-
-                $iRangeEnd   = ($iRangeStart > $aMailbox['LIMIT']) ?
-                               ($iRangeStart - $aMailbox['LIMIT']+1):1;
-
-                $id_slice = range($iRangeStart, $iRangeEnd);
-                $msgs = sqimap_get_small_header_list($imapConnection,$id_slice,$aMailbox['LIMIT'],
-                     $aHeaderFields,$aFetchItems);
-                $msgs = array_reverse($msgs,true /* preserve key */);
-                // generate id array
-                $id = array_keys($msgs);
-                $aMailbox['OFFSET'] = 0;
+                $aIdNotCached = $id_slice;
             }
-            // FIX ME, use an id list bound to a mailbox
-            if ($id !== false) {
-                sqsession_register($id, 'server_sort_array');
+
+            if (count($aIdNotCached)) {
+                $aMsgs = sqimap_get_small_header_list($imapConnection,$aIdNotCached,
+                    $aHeaderFields,$aFetchItems);
+                // append the msgs to the existend headers
+                if (isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) {
+                    $aMailbox['MSG_HEADERS'] += $aMsgs;
+                } else {
+                    $aMailbox['MSG_HEADERS'] = $aMsgs;
+                }
+                // update the ID array
+                foreach ($aMsgs as $iUid => $aMsg) {
+                    if (isset($aMsg['ID'])) {
+                        $aMailbox['ID'][$aMsg['ID']] = $iUid;
+                    }
+                }
             }
 
-            sqsession_register($msgs, 'msgs');
-        }
-        $aMailbox['UIDSET'] =& $id;
-        $aMailbox['MSG_HEADERS'] =& $msgs;
-        if ($aMailbox['SORT_METHOD'] == 'THREAD') {
-            // retrieve indent array for thread sort
-            sqgetGlobalVar('indent_array',$indent_array,SQ_SESSION);
-            $aMailbox['THREAD_INDENT'] =& $indent_array;
+            /**
+             * In unsorted state we show newest messages first which means
+             * that the UIDSET which represents the order of the messages
+             * should contain a high to low ordered UID list
+             */
+            $aSortedUidList = array();
+            foreach ($id_slice as $iId) {
+                if (isset($aMailbox['ID'][$iId])) {
+                    $aSortedUidList[] = $aMailbox['ID'][$iId];
+                }
+            }
+            $aMailbox['UIDSET'][$iSetIndx] = $aSortedUidList;
+            $aMailbox['OFFSET'] = 0;
         }
-    } /* if exists > 0 */
+    }
+    return true;
+}
 
-    $iEnd = ($aMailbox['PAGEOFFSET'] + ($aMailbox['LIMIT'] - 1) < $aMailbox['EXISTS']) ?
-             $aMailbox['PAGEOFFSET'] + $aMailbox['LIMIT'] - 1 : $aMailbox['EXISTS'];
+/**
+* This function loops through a group of messages in the mailbox
+* and shows them to the user.
+*
+* @param mixed $imapConnection
+* @param array $aMailbox associative array with mailbox related vars
+*/
+function showMessagesForMailbox($imapConnection, &$aMailbox) {
+    global $color;
+
+    // to retrieve the internaldate pref: (I know this is not the right place to do that, move up in front
+    // and use a properties array as function argument to provide user preferences
+    global $data_dir, $username;
+
+    if (!fetchMessageHeaders($imapConnection, $aMailbox)) {
+        return false;
+    }
+    $iSetIndx = $aMailbox['SETINDEX'];
+    $iLimit = ($aMailbox['SHOWALL'][$iSetIndx]) ? $aMailbox['EXISTS'] : $aMailbox['LIMIT'];
+    $iEnd = ($aMailbox['PAGEOFFSET'] + ($iLimit - 1) < $aMailbox['EXISTS']) ?
+             $aMailbox['PAGEOFFSET'] + $iLimit - 1 : $aMailbox['EXISTS'];
 
-    $paginator_str = get_paginator_str($aMailbox['NAME'], $aMailbox['PAGEOFFSET'], $iEnd,
-                                    $aMailbox['EXISTS'], $aMailbox['LIMIT'], $aMailbox['SORT']);
+    $paginator_str = get_paginator_str($aMailbox['NAME'], $aMailbox['PAGEOFFSET'],
+                                    $aMailbox['EXISTS'], $aMailbox['LIMIT'], $aMailbox['SHOWALL'][$iSetIndx]);
 
     $msg_cnt_str = get_msgcnt_str($aMailbox['PAGEOFFSET'], $iEnd,$aMailbox['EXISTS']);
 
@@ -699,8 +1059,7 @@ function showMessagesForMailbox($imapConnection, $aMailbox) {
 </tr>
 </table>
 <?php
-    //$t = elapsed($start);
-    //echo("elapsed time = $t seconds\n");
+
 }
 
 /**
@@ -714,16 +1073,18 @@ function showMessagesForMailbox($imapConnection, $aMailbox) {
 * @return void
 **/
 function displayMessageArray($imapConnection, $aMailbox) {
-
-    $aId         = $aMailbox['UIDSET'];
+    $iSetIndx    = $aMailbox['SETINDEX'];
+    $aId         = $aMailbox['UIDSET'][$iSetIndx];
     $aHeaders    = $aMailbox['MSG_HEADERS'];
     $iOffset     = $aMailbox['OFFSET'];
     $sort        = $aMailbox['SORT'];
     $iPageOffset = $aMailbox['PAGEOFFSET'];
     $sMailbox    = $aMailbox['NAME'];
-    $aSearch     = (isset($aMailbox['SEARCH'])) ? $aMailbox['SEARCH'] : false;
-    if ($aMailbox['SORT_METHOD'] == 'THREAD') {
-        $aIndentArray =& $aMailbox['THREAD_INDENT'];
+    $sSearch     = (isset($aMailbox['SEARCH'][$aMailbox['SETINDEX']])) ? $aMailbox['SEARCH'][$aMailbox['SETINDEX']] : false;
+    $aSearch     = ($sSearch) ? array('search.php',$aMailbox['SETINDEX']) : null;
+
+    if ($aMailbox['SORT'] & SQSORT_THREAD) {
+        $aIndentArray =& $aMailbox['THREAD_INDENT'][$aMailbox['SETINDEX']];
         $bThread = true;
     } else {
         $bThread = false;
@@ -732,7 +1093,7 @@ function displayMessageArray($imapConnection, $aMailbox) {
     * Loop through and display the info for each message.
     * ($t is used for the checkbox number)
     */
-    $iEnd = ($aMailbox['LIMIT']) ? $iOffset + $aMailbox['LIMIT']  : 99999999 /* no limit */;
+    $iEnd = ($aMailbox['SHOWALL'][$iSetIndx]) ? $aMailbox['EXISTS'] : $iOffset + $aMailbox['LIMIT'];
     for ($i=$iOffset,$t=0;$i<$iEnd;++$i) {
         if (isset($aId[$i])) {
             $bLast = ((isset($aId[$i+1]) && isset($aHeaders[$aId[$i+1]]))
@@ -753,7 +1114,7 @@ function displayMessageArray($imapConnection, $aMailbox) {
                       'INDENT'     => $indent,
                       'LAST'       => $bLast
                     );
-            printMessageInfo($aMsg);
+             printMessageInfo($aMsg);
             ++$t;
         } else {
             break;
@@ -776,15 +1137,11 @@ function mail_message_listing_beginning ($imapConnection,
                                          $msg_cnt_str = '',
                                          $paginator = '&nbsp;'
                                         ) {
-    global $color, $base_uri, $show_flag_buttons, $PHP_SELF;
-
-
+    global $color, $show_flag_buttons, $PHP_SELF;
+    global $lastTargetMailbox;
 
     $php_self = $PHP_SELF;
-    /* fix for incorrect $PHP_SELF */
-    if (strpos($php_self, 'move_messages.php')) {
-        $php_self = str_replace('move_messages.php', 'right_main.php', $php_self);
-    }
+
     $urlMailbox = urlencode($aMailbox['NAME']);
 
     if (preg_match('/^(.+)\?.+$/',$php_self,$regs)) {
@@ -797,29 +1154,22 @@ function mail_message_listing_beginning ($imapConnection,
         $msg = '';
     }
 
-    if (!strpos($php_self,'?')) {
-        $location = $php_self.'?mailbox=INBOX&amp;startMessage=1';
-    } else {
-        $location = $php_self;
-    }
-
     $moveFields = addHidden('msg', $msg).
                   addHidden('mailbox', $aMailbox['NAME']).
-                  addHidden('startMessage', $aMailbox['PAGEOFFSET']).
-                  addHidden('location', $location);
+                  addHidden('startMessage', $aMailbox['PAGEOFFSET']);
 
     /* build thread sorting links */
-
+    $sort = $aMailbox['SORT'];
     if ($aMailbox['ALLOW_THREAD']) {
-        if ($aMailbox['SORT_METHOD'] == 'THREAD') {
-            $set_thread = 2;
+        if ($aMailbox['SORT'] & SQSORT_THREAD) {
+            $sort -= SQSORT_THREAD;
             $thread_name = _("Unthread View");
         } else {
-            $set_thread = 1;
             $thread_name = _("Thread View");
+            $sort = $aMailbox['SORT'] + SQSORT_THREAD;
         }
-        $thread_link_str = '<small>[<a href="' . $source_url . '?sort='
-            . $aMailbox['SORT'] . '&start_messages=1&set_thread=' . $set_thread
+        $thread_link_str = '<small>[<a href="' . $source_url . '?srt='
+            . $sort . '&start_messages=1'
             . '&mailbox=' . urlencode($aMailbox['NAME']) . '">' . $thread_name
             . '</a>]</small>';
     } else {
@@ -832,8 +1182,10 @@ function mail_message_listing_beginning ($imapConnection,
     $safe_name = preg_replace("/[^0-9A-Za-z_]/", '_', $aMailbox['NAME']);
     $form_name = "FormMsgs" . $safe_name;
 
-    echo '<form name="' . $form_name . '" method="post" action="move_messages.php">' ."\n"
+    echo '<form name="' . $form_name . '" method="post" action="'.$php_self.'">' ."\n"
         . $moveFields;
+
+
 ?>
     <table width="100%" cellpadding="1"  cellspacing="0" style="border: 1px solid <?php echo $color[0]; ?>">
         <tr>
@@ -885,8 +1237,9 @@ function mail_message_listing_beginning ($imapConnection,
                 if (in_array('\\deleted',$aMailbox['PERMANENTFLAGS'], true)) {
                     echo '<td align="right">
                 <small>';
-                    //echo $thread_link_str;   //previous behaviour
-                    getMbxList($imapConnection);
+                    echo  '         <small>&nbsp;<tt><select name="targetMailbox">';
+                    echo sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)), 0, $boxes);
+                    echo '         </select></tt>&nbsp;';
                     echo getButton('SUBMIT', 'moveButton',_("Move")) . "\n
                 </small>";
                 }
@@ -1051,7 +1404,7 @@ function ShowSortButton($aMailbox, $Down, $Up ) {
     }
 
     /* Now that we have everything figured out, show the actual button. */
-    echo ' <a href="' . $source_url .'?newsort=' . $which
+    echo ' <a href="' . $source_url .'?srt=' . $which
         . '&amp;startMessage=1&amp;mailbox=' . urlencode($aMailbox['NAME'])
         . '"><img src="../images/' . $img
         . '" border="0" width="12" height="10" alt="sort" title="'
@@ -1065,7 +1418,7 @@ function ShowSortButton($aMailbox, $Down, $Up ) {
 */
 function get_selectall_link($aMailbox) {
     global $checkall, $javascript_on;
-    global $PHP_SELF, $PG_SHOWNUM;
+    global $PHP_SELF;
 
     $result = '';
     if ($javascript_on) {
@@ -1091,10 +1444,10 @@ function get_selectall_link($aMailbox) {
     } else {
         if (strpos($PHP_SELF, "?")) {
             $result .= "<a href=\"$PHP_SELF&amp;mailbox=" . urlencode($aMailbox['NAME'])
-                    .  "&amp;startMessage=$aMailbox[PAGEOFFSET]&amp;sort=$aMailbox[SORT]&amp;checkall=";
+                    .  "&amp;startMessage=$aMailbox[PAGEOFFSET]&amp;srt=$aMailbox[SORT]&amp;checkall=";
         } else {
             $result .= "<a href=\"$PHP_SELF?mailbox=" . urlencode($mailbox)
-                    .  "&amp;startMessage=$aMailbox[PAGEOFFSET]&amp;sort=$aMailbox[SORT]&amp;checkall=";
+                    .  "&amp;startMessage=$aMailbox[PAGEOFFSET]&amp;srt=$aMailbox[SORT]&amp;checkall=";
         }
         if (isset($checkall) && $checkall == '1') {
             $result .= '0';
@@ -1147,10 +1500,9 @@ function get_msgcnt_str($start_msg, $end_msg, $num_msgs) {
 * @param string $text text used for paginator link
 * @return string
 */
-function get_paginator_link($box, $start_msg, $use, $text) {
-
-    $result = "<a href=\"right_main.php?use_mailbox_cache=$use"
-            . "&amp;startMessage=$start_msg&amp;mailbox=$box\" "
+function get_paginator_link($box, $start_msg, $text) {
+    sqgetGlobalVar('PHP_SELF',$php_self,SQ_SERVER);
+    $result = "<a href=\"$php_self?startMessage=$start_msg&amp;mailbox=$box\" "
             . ">$text</a>";
 
     return ($result);
@@ -1162,13 +1514,16 @@ function get_paginator_link($box, $start_msg, $use, $text) {
 * @param string $box
 * @param integer $start_msg
 * @param integer $end_msg
-* @param integer $num_msgs
-* @param integer $show_num
+* @param integer $num_msgs // total number of messages
+* @param integer $limit // number of messages to show on one page
 * @param integer $sort
 */
-function get_paginator_str($box, $start_msg, $end_msg, $num_msgs,
-                        $show_num, $sort) {
-    global $username, $data_dir, $use_mailbox_cache, $color, $PG_SHOWNUM;
+//function get_paginator_str($box, $start_msg, $end_msg, $num_msgs,
+//                        $show_num, $sort) {
+function get_paginator_str($box, $iOffset, $iTotal, $iLimit, $bShowAll) {
+
+    global $username, $data_dir, $color;
+    sqgetGlobalVar('PHP_SELF',$php_self,SQ_SERVER);
 
     /* Initialize paginator string chunks. */
     $prv_str = '';
@@ -1177,7 +1532,7 @@ function get_paginator_str($box, $start_msg, $end_msg, $num_msgs,
     $all_str = '';
 
     $box = urlencode($box);
-    $use = 0;
+
     /* Create simple strings that will be creating the paginator. */
     $spc = '&nbsp;';     /* This will be used as a space. */
     $sep = '|';          /* This will be used as a seperator. */
@@ -1187,140 +1542,142 @@ function get_paginator_str($box, $start_msg, $end_msg, $num_msgs,
     $pg_max = getPref($data_dir, $username, 'page_selector_max', PG_SEL_MAX);
 
     /* Make sure that our start message number is not too big. */
-    $start_msg = min($start_msg, $num_msgs);
+    $iOffset = min($iOffset, $iTotal);
 
     /* Compute the starting message of the previous and next page group. */
-    $next_grp = $start_msg + $show_num;
-    $prev_grp = $start_msg - $show_num;
-
-    /* Compute the basic previous and next strings. */
-    if (($next_grp <= $num_msgs) && ($prev_grp >= 0)) {
-        $prv_str = get_paginator_link($box, $prev_grp, $use, _("Previous"));
-        $nxt_str = get_paginator_link($box, $next_grp, $use, _("Next"));
-    } else if (($next_grp > $num_msgs) && ($prev_grp >= 0)) {
-        $prv_str = get_paginator_link($box, $prev_grp, $use, _("Previous"));
-        $nxt_str = _("Next");
-    } else if (($next_grp <= $num_msgs) && ($prev_grp < 0)) {
-        $prv_str = _("Previous");
-        $nxt_str = get_paginator_link($box, $next_grp, $use, _("Next"));
-    }
-
-    /* Page selector block. Following code computes page links. */
-    if ($show_num != 0 && $pg_sel && ($num_msgs > $show_num)) {
-        /* Most importantly, what is the current page!!! */
-        $cur_pg = intval($start_msg / $show_num) + 1;
+    $next_grp = $iOffset + $iLimit;
+    $prev_grp = $iOffset - $iLimit;
+
+    if (!$bShowAll) {
+        /* Compute the basic previous and next strings. */
+        if (($next_grp <= $iTotal) && ($prev_grp >= 0)) {
+            $prv_str = get_paginator_link($box, $prev_grp, _("Previous"));
+            $nxt_str = get_paginator_link($box, $next_grp, _("Next"));
+        } else if (($next_grp > $iTotal) && ($prev_grp >= 0)) {
+            $prv_str = get_paginator_link($box, $prev_grp, _("Previous"));
+            $nxt_str = _("Next");
+        } else if (($next_grp <= $iTotal) && ($prev_grp < 0)) {
+            $prv_str = _("Previous");
+            $nxt_str = get_paginator_link($box, $next_grp, _("Next"));
+        }
 
-        /* Compute total # of pages and # of paginator page links. */
-        $tot_pgs = ceil($num_msgs / $show_num);  /* Total number of Pages */
-        $vis_pgs = min($pg_max, $tot_pgs - 1);   /* Visible Pages    */
+        /* Page selector block. Following code computes page links. */
+        if ($iLimit != 0 && $pg_sel && ($iTotal > $iLimit)) {
+            /* Most importantly, what is the current page!!! */
+            $cur_pg = intval($iOffset / $iLimit) + 1;
 
-        /* Compute the size of the four quarters of the page links. */
+            /* Compute total # of pages and # of paginator page links. */
+            $tot_pgs = ceil($iTotal / $iLimit);  /* Total number of Pages */
+            $vis_pgs = min($pg_max, $tot_pgs - 1);   /* Visible Pages    */
 
-        /* If we can, just show all the pages. */
-        if (($tot_pgs - 1) <= $pg_max) {
-            $q1_pgs = $cur_pg - 1;
-            $q2_pgs = $q3_pgs = 0;
-            $q4_pgs = $tot_pgs - $cur_pg;
+            /* Compute the size of the four quarters of the page links. */
 
-        /* Otherwise, compute some magic to choose the four quarters. */
-        } else {
-            /*
-            * Compute the magic base values. Added together,
-            * these values will always equal to the $pag_pgs.
-            * NOTE: These are DEFAULT values and do not take
-            * the current page into account. That is below.
-            */
-            $q1_pgs = floor($vis_pgs/4);
-            $q2_pgs = round($vis_pgs/4, 0);
-            $q3_pgs = ceil($vis_pgs/4);
-            $q4_pgs = round(($vis_pgs - $q2_pgs)/3, 0);
-
-            /* Adjust if the first quarter contains the current page. */
-            if (($cur_pg - $q1_pgs) < 1) {
-                $extra_pgs = ($q1_pgs - ($cur_pg - 1)) + $q2_pgs;
+            /* If we can, just show all the pages. */
+            if (($tot_pgs - 1) <= $pg_max) {
                 $q1_pgs = $cur_pg - 1;
-                $q2_pgs = 0;
-                $q3_pgs += ceil($extra_pgs / 2);
-                $q4_pgs += floor($extra_pgs / 2);
-
-            /* Adjust if the first and second quarters intersect. */
-            } else if (($cur_pg - $q2_pgs - ceil($q2_pgs/3)) <= $q1_pgs) {
-                $extra_pgs = $q2_pgs;
-                $extra_pgs -= ceil(($cur_pg - $q1_pgs - 1) * 3/4);
-                $q2_pgs = ceil(($cur_pg - $q1_pgs - 1) * 3/4);
-                $q3_pgs += ceil($extra_pgs / 2);
-                $q4_pgs += floor($extra_pgs / 2);
-
-            /* Adjust if the fourth quarter contains the current page. */
-            } else if (($cur_pg + $q4_pgs) >= $tot_pgs) {
-                $extra_pgs = ($q4_pgs - ($tot_pgs - $cur_pg)) + $q3_pgs;
-                $q3_pgs = 0;
+                $q2_pgs = $q3_pgs = 0;
                 $q4_pgs = $tot_pgs - $cur_pg;
-                $q1_pgs += floor($extra_pgs / 2);
-                $q2_pgs += ceil($extra_pgs / 2);
-
-            /* Adjust if the third and fourth quarter intersect. */
-            } else if (($cur_pg + $q3_pgs + 1) >= ($tot_pgs - $q4_pgs + 1)) {
-                $extra_pgs = $q3_pgs;
-                $extra_pgs -= ceil(($tot_pgs - $cur_pg - $q4_pgs) * 3/4);
-                $q3_pgs = ceil(($tot_pgs - $cur_pg - $q4_pgs) * 3/4);
-                $q1_pgs += floor($extra_pgs / 2);
-                $q2_pgs += ceil($extra_pgs / 2);
+
+            /* Otherwise, compute some magic to choose the four quarters. */
+            } else {
+                /*
+                * Compute the magic base values. Added together,
+                * these values will always equal to the $pag_pgs.
+                * NOTE: These are DEFAULT values and do not take
+                * the current page into account. That is below.
+                */
+                $q1_pgs = floor($vis_pgs/4);
+                $q2_pgs = round($vis_pgs/4, 0);
+                $q3_pgs = ceil($vis_pgs/4);
+                $q4_pgs = round(($vis_pgs - $q2_pgs)/3, 0);
+
+                /* Adjust if the first quarter contains the current page. */
+                if (($cur_pg - $q1_pgs) < 1) {
+                    $extra_pgs = ($q1_pgs - ($cur_pg - 1)) + $q2_pgs;
+                    $q1_pgs = $cur_pg - 1;
+                    $q2_pgs = 0;
+                    $q3_pgs += ceil($extra_pgs / 2);
+                    $q4_pgs += floor($extra_pgs / 2);
+
+                /* Adjust if the first and second quarters intersect. */
+                } else if (($cur_pg - $q2_pgs - ceil($q2_pgs/3)) <= $q1_pgs) {
+                    $extra_pgs = $q2_pgs;
+                    $extra_pgs -= ceil(($cur_pg - $q1_pgs - 1) * 3/4);
+                    $q2_pgs = ceil(($cur_pg - $q1_pgs - 1) * 3/4);
+                    $q3_pgs += ceil($extra_pgs / 2);
+                    $q4_pgs += floor($extra_pgs / 2);
+
+                /* Adjust if the fourth quarter contains the current page. */
+                } else if (($cur_pg + $q4_pgs) >= $tot_pgs) {
+                    $extra_pgs = ($q4_pgs - ($tot_pgs - $cur_pg)) + $q3_pgs;
+                    $q3_pgs = 0;
+                    $q4_pgs = $tot_pgs - $cur_pg;
+                    $q1_pgs += floor($extra_pgs / 2);
+                    $q2_pgs += ceil($extra_pgs / 2);
+
+                /* Adjust if the third and fourth quarter intersect. */
+                } else if (($cur_pg + $q3_pgs + 1) >= ($tot_pgs - $q4_pgs + 1)) {
+                    $extra_pgs = $q3_pgs;
+                    $extra_pgs -= ceil(($tot_pgs - $cur_pg - $q4_pgs) * 3/4);
+                    $q3_pgs = ceil(($tot_pgs - $cur_pg - $q4_pgs) * 3/4);
+                    $q1_pgs += floor($extra_pgs / 2);
+                    $q2_pgs += ceil($extra_pgs / 2);
+                }
             }
-        }
 
-        /*
-        * I am leaving this debug code here, commented out, because
-        * it is a really nice way to see what the above code is doing.
-        * echo "qts =  $q1_pgs/$q2_pgs/$q3_pgs/$q4_pgs = "
-        *    . ($q1_pgs + $q2_pgs + $q3_pgs + $q4_pgs) . '<br />';
-        */
+            /*
+            * I am leaving this debug code here, commented out, because
+            * it is a really nice way to see what the above code is doing.
+            * echo "qts =  $q1_pgs/$q2_pgs/$q3_pgs/$q4_pgs = "
+            *    . ($q1_pgs + $q2_pgs + $q3_pgs + $q4_pgs) . '<br />';
+            */
 
-        /* Print out the page links from the compute page quarters. */
+            /* Print out the page links from the compute page quarters. */
 
-        /* Start with the first quarter. */
-        if (($q1_pgs == 0) && ($cur_pg > 1)) {
-            $pg_str .= "...$spc";
-        } else {
-            for ($pg = 1; $pg <= $q1_pgs; ++$pg) {
-                $start = (($pg-1) * $show_num) + 1;
-                $pg_str .= get_paginator_link($box, $start, $use, $pg) . $spc;
-            }
-            if ($cur_pg - $q2_pgs - $q1_pgs > 1) {
+            /* Start with the first quarter. */
+            if (($q1_pgs == 0) && ($cur_pg > 1)) {
                 $pg_str .= "...$spc";
+            } else {
+                for ($pg = 1; $pg <= $q1_pgs; ++$pg) {
+                    $start = (($pg-1) * $iLimit) + 1;
+                    $pg_str .= get_paginator_link($box, $start, $pg) . $spc;
+                }
+                if ($cur_pg - $q2_pgs - $q1_pgs > 1) {
+                    $pg_str .= "...$spc";
+                }
             }
-        }
 
-        /* Continue with the second quarter. */
-        for ($pg = $cur_pg - $q2_pgs; $pg < $cur_pg; ++$pg) {
-            $start = (($pg-1) * $show_num) + 1;
-            $pg_str .= get_paginator_link($box, $start, $use, $pg) . $spc;
-        }
+            /* Continue with the second quarter. */
+            for ($pg = $cur_pg - $q2_pgs; $pg < $cur_pg; ++$pg) {
+                $start = (($pg-1) * $iLimit) + 1;
+                $pg_str .= get_paginator_link($box, $start, $pg) . $spc;
+            }
 
-        /* Now print the current page. */
-        $pg_str .= $cur_pg . $spc;
+            /* Now print the current page. */
+            $pg_str .= $cur_pg . $spc;
 
-        /* Next comes the third quarter. */
-        for ($pg = $cur_pg + 1; $pg <= $cur_pg + $q3_pgs; ++$pg) {
-            $start = (($pg-1) * $show_num) + 1;
-            $pg_str .= get_paginator_link($box, $start, $use, $pg) . $spc;
-        }
+            /* Next comes the third quarter. */
+            for ($pg = $cur_pg + 1; $pg <= $cur_pg + $q3_pgs; ++$pg) {
+                $start = (($pg-1) * $iLimit) + 1;
+                $pg_str .= get_paginator_link($box, $start, $pg) . $spc;
+            }
 
-        /* And last, print the forth quarter page links. */
-        if (($q4_pgs == 0) && ($cur_pg < $tot_pgs)) {
-            $pg_str .= "...$spc";
-        } else {
-            if (($tot_pgs - $q4_pgs) > ($cur_pg + $q3_pgs)) {
+            /* And last, print the forth quarter page links. */
+            if (($q4_pgs == 0) && ($cur_pg < $tot_pgs)) {
                 $pg_str .= "...$spc";
-            }
-            for ($pg = $tot_pgs - $q4_pgs + 1; $pg <= $tot_pgs; ++$pg) {
-                $start = (($pg-1) * $show_num) + 1;
-                $pg_str .= get_paginator_link($box, $start, $use, $pg) . $spc;
+            } else {
+                if (($tot_pgs - $q4_pgs) > ($cur_pg + $q3_pgs)) {
+                    $pg_str .= "...$spc";
+                }
+                for ($pg = $tot_pgs - $q4_pgs + 1; $pg <= $tot_pgs; ++$pg) {
+                    $start = (($pg-1) * $iLimit) + 1;
+                    $pg_str .= get_paginator_link($box, $start,$pg) . $spc;
+                }
             }
         }
-    } else if ($PG_SHOWNUM == 999999) {
-        $pg_str = "<a href=\"right_main.php?PG_SHOWALL=0"
-                . "&amp;use_mailbox_cache=$use&amp;startMessage=1&amp;mailbox=$box\" "
+    } else {
+        $pg_str = "<a href=\"$php_self?showall=0"
+                . "&amp;startMessage=1&amp;mailbox=$box\" "
                 . ">" ._("Paginate") . '</a>';
     }
 
@@ -1330,17 +1687,17 @@ function get_paginator_str($box, $start_msg, $end_msg, $num_msgs,
     * a different approach would be any easier to read. ;)
     */
     $result = '';
-    if ( $prv_str != '' || $nxt_str != '' )
-    {
-    $result .= '[';
-    $result .= ($prv_str != '' ? $prv_str . $spc . $sep . $spc : '');
-    $result .= ($nxt_str != '' ? $nxt_str : '');
-    $result .= ']' . $spc ;
-
-    /* Compute the 'show all' string. */
-    $all_str = "<a href=\"right_main.php?PG_SHOWALL=1"
-                . "&amp;use_mailbox_cache=$use&amp;startMessage=1&amp;mailbox=$box\" "
+    if ( $prv_str || $nxt_str ) {
+
+        /* Compute the 'show all' string. */
+        $all_str = "<a href=\"$php_self?showall=1"
+                . "&amp;startMessage=1&amp;mailbox=$box\" "
                 . ">" . _("Show All") . '</a>';
+        $result .= '[';
+        $result .= ($prv_str != '' ? $prv_str . $spc . $sep . $spc : '');
+        $result .= ($nxt_str != '' ? $nxt_str : '');
+        $result .= ']' . $spc ;
+
     }
 
     $result .= ($pg_str  != '' ? $spc . '['.$spc.$pg_str.']' .  $spc : '');
@@ -1417,18 +1774,6 @@ function processSubject($subject, $threadlevel = 0) {
     return truncateWithEntities($subject, $trim_at);
 }
 
-/**
-* FIXME: Undocumented function
-*
-* @param mixed $imapConnection
-* @param mixed $boxes
-*/
-function getMbxList($imapConnection, $boxes = 0) {
-    global $lastTargetMailbox;
-    echo  '         <small>&nbsp;<tt><select name="targetMailbox">';
-    echo sqimap_mailbox_option_list($imapConnection, array(strtolower($lastTargetMailbox)), 0, $boxes);
-    echo '         </select></tt>&nbsp;';
-}
 
 /**
 * Creates button
@@ -1481,4 +1826,219 @@ function handleAsSent($mailbox) {
     return $handleAsSent_result;
 }
 
+/**
+ * Process messages list form and handle the cache gracefully. If $sButton and
+ * $aUid are provided as argument then you can fake a message list submit and
+ * use it i.e. in read_body.php for del move next and update the cache
+ *
+ * @param  resource $imapConnection imap connection
+ * @param  array $aMailbox (reference) cached mailbox
+ * @param  string $sButton fake a submit button
+ * @param  array  $aUid    fake the $msg array
+ * @return string $sError error string in case of an error
+ * @author Marc Groot Koerkamp
+ */
+function handleMessageListForm($imapConnection,&$aMailbox,$sButton='',$aUid = array()) {
+
+    /* incoming formdata */
+    $sButton = (sqgetGlobalVar('moveButton',      $sTmp, SQ_POST)) ? 'move'         : $sButton;
+    $sButton = (sqgetGlobalVar('expungeButton',   $sTmp, SQ_POST)) ? 'expunge'      : $sButton;
+    $sButton = (sqgetGlobalVar('attache',         $sTmp, SQ_POST)) ? 'attache'      : $sButton;
+    $sButton = (sqgetGlobalVar('delete',          $sTmp, SQ_POST)) ? 'setDeleted'   : $sButton;
+    $sButton = (sqgetGlobalVar('undeleteButton',  $sTmp, SQ_POST)) ? 'setDeleted'   : $sButton;
+    $sButton = (sqgetGlobalVar('markRead',        $sTmp, SQ_POST)) ? 'setSeen'      : $sButton;
+    $sButton = (sqgetGlobalVar('markUnread',      $sTmp, SQ_POST)) ? 'unsetSeen'    : $sButton;
+    $sButton = (sqgetGlobalVar('markFlagged',     $sTmp, SQ_POST)) ? 'setFlagged'   : $sButton;
+    $sButton = (sqgetGlobalVar('markUnflagged',   $sTmp, SQ_POST)) ? 'unsetFlagged' : $sButton;
+    sqgetGlobalVar('targetMailbox', $targetMailbox,   SQ_POST);
+    sqgetGlobalVar('bypass_trash',  $bypass_trash,    SQ_POST);
+    sqgetGlobalVar('msg',           $msg,             SQ_POST);
+
+    $sError = '';
+    $mailbox = $aMailbox['NAME'];
+
+    /* retrieve the check boxes */
+    $aUid = (isset($msg) && is_array($msg)) ? array_values($msg) : $aUid;
+
+    if (count($aUid) && $sButton != 'expunge') {
+        $aUpdatedMsgs = false;
+        $bExpunge = false;
+        switch ($sButton) {
+          case 'setDeleted':
+            // check if id exists in case we come from read_body
+            if (count($aUid) == 1 && is_array($aMailbox['UIDSET'][$aMailbox['SETINDEX']]) &&
+                !in_array($aUid[0],$aMailbox['UIDSET'][$aMailbox['SETINDEX']])) {
+                break;
+            }
+            // What kind of hook is this, can it be removed? Disabled for now because it can invalidate the cache
+            //if (!boolean_hook_function('move_messages_button_action', NULL, 1)) {
+                $aUpdatedMsgs = sqimap_msgs_list_delete($imapConnection, $mailbox, $aUid,$bypass_trash);
+                $bExpunge = true;
+            //}
+            break;
+          case 'unsetDeleted':
+          case 'setSeen':
+          case 'unsetSeen':
+          case 'setFlagged':
+          case 'unsetFlagged':
+            // get flag
+            $sFlag = (substr($sButton,0,3) == 'set') ? '\\'.substr($sButton,3) : '\\'.substr($sButton,5);
+            $bSet  = (substr($sButton,0,3) == 'set') ? true : false;
+            $aUpdatedMsgs = sqimap_toggle_flag($imapConnection, $aUid, $sFlag, $bSet, true);
+            break;
+          case 'move':
+            $aUpdatedMsgs = sqimap_msgs_list_move($imapConnection,$aUid,$targetMailbox);
+            sqsession_register($targetMailbox,'lastTargetMailbox');
+            $bExpunge = true;
+            break;
+          case 'attache':
+            $aMsgHeaders = array();
+            foreach ($aUid as $iUid) {
+                $aMsgHeaders[$iUid] = $aMailbox['MSG_HEADERS'][$iUid];
+            }
+            if (count($aMsgHeaders)) {
+                $composesession = attachSelectedMessages($imapConnection,$aMsgHeaders);
+                // dirty hack, add info to $aMailbox
+                $aMailbox['FORWARD_SESSION'] = $composesession;
+            }
+            break;
+        }
+        /**
+         * Updates messages is an array containing the result of the untagged
+         * fetch responses send by the imap server due to a flag change. That
+         * response is parsed in a array with msg arrays by the parseFetch function
+         */
+        if ($aUpdatedMsgs) {
+            // Update the message headers cache
+            $aDeleted = array();
+            foreach ($aUpdatedMsgs as $iUid => $aMsg) {
+                if (isset($aMsg['FLAGS'])) {
+                    $aMailbox['MSG_HEADERS'][$iUid]['FLAGS'] = $aMsg['FLAGS'];
+                    /**
+                     * Count the messages with the \Delete flag set so we can determine
+                     * if the number of expunged messages equals the number of flagged
+                     * messages for deletion.
+                     */
+                    if (isset($aMsg['FLAGS']['\\deleted']) && $aMsg['FLAGS']['\\deleted']) {
+                        $aDeleted[] = $iUid;
+                    }
+                }
+            }
+            if ($bExpunge && $aMailbox['AUTO_EXPUNGE'] &&
+                $iExpungedMessages = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true))
+                {
+                if (count($aDeleted) != $iExpungedMessages) {
+                    // there are more messages deleted permanently then we expected
+                    // invalidate the cache
+                    $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = false;
+                    $aMailbox['MSG_HEADERS'] = false;
+                } else {
+                    // remove expunged messages from cache
+                    $aUidSet = $aMailbox['UIDSET'][$aMailbox['SETINDEX']];
+                    if (is_array($aUidSet)) {
+                        // create a UID => array index temp array
+                        $aUidSetDummy = array_flip($aUidSet);
+                        foreach ($aDeleted as $iUid) {
+                            // get the id as well in case of SQM_SORT_NONE
+                            if ($aMailbox['SORT'] == SQSORT_NONE) {
+                                $aMailbox['ID'] = false;
+                                //$iId = $aMailbox['MSG_HEADERS'][$iUid]['ID'];
+                                //unset($aMailbox['ID'][$iId]);
+                            }
+                            // unset the UID and message header
+                            unset($aUidSetDummy[$iUid]);
+                            unset($aMailbox['MSG_HEADERS'][$iUid]);
+                        }
+                        $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = array_keys($aUidSetDummy);
+                        // update EXISTS info
+                        $aMailbox['EXISTS'] -= $iExpungedMessages;
+                    }
+                }
+                // Change the startMessage number if the mailbox was changed
+                if (($aMailbox['PAGEOFFSET']+$iExpungedMessages-1) >= $aMailbox['EXISTS']) {
+                    $aMailbox['PAGEOFFSET'] = ($aMailbox['PAGEOFFSET'] > $aMailbox['LIMIT']) ?
+                        $aMailbox['PAGEOFFSET'] - $aMailbox['LIMIT'] : 1;
+                }
+            }
+        }
+    } else {
+        if ($sButton == 'expunge') {
+            /**
+             * on expunge we do not know which messages will be deleted
+             * so it's useless to try to sync the cache
+
+             * Close the mailbox so we do not need to parse the untagged expunge
+             * responses which do not contain uid info.
+             * NB: Closing a mailbox is faster then expunge because the imap
+             * server does not need to generate the untagged expunge responses
+             */
+            sqimap_run_command($imapConnection,'CLOSE',false,$result,$message);
+            $aMbxResponse = sqimap_mailbox_select($imapConnection,$aMailbox['NAME']);
+            // update the $aMailbox array
+            $aMailbox['EXISTS'] = $aMbxResponse['EXISTS'];
+            $aMailbox['UIDSET'] = false;
+        } else {
+            if ($sButton) {
+                $sError = _("No messages were selected.");
+            }
+        }
+    }
+    return $sError;
+}
+
+function attachSelectedMessages($imapConnection,$aMsgHeaders) {
+    global $username, $attachment_dir,
+           $data_dir, $composesession,
+           $compose_messages;
+
+    if (!isset($compose_messages)) {
+        $compose_messages = array();
+        sqsession_register($compose_messages,'compose_messages');
+    }
+
+    if (!$composesession) {
+        $composesession = 1;
+        sqsession_register($composesession,'composesession');
+    } else {
+        $composesession++;
+        sqsession_register($composesession,'composesession');
+    }
+
+    $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
+
+    $composeMessage = new Message();
+    $rfc822_header = new Rfc822Header();
+    $composeMessage->rfc822_header = $rfc822_header;
+    $composeMessage->reply_rfc822_header = '';
+
+    foreach($aMsgHeaders as $iUid => $aMsgHeader) {
+        /**
+         * Retrieve the full message
+         */
+        $body_a = sqimap_run_command($imapConnection, "FETCH $iUid RFC822", true, $response, $readmessage, TRUE);
+
+        if ($response == 'OK') {
+            $subject = (isset($aMsgHeader['SUBJECT'])) ? $aMsgHeader['SUBJECT'] : $iUid;
+
+            array_shift($body_a);
+            array_pop($body_a);
+            $body = implode('', $body_a);
+            $body .= "\r\n";
+
+            $localfilename = GenerateRandomString(32, 'FILE', 7);
+            $full_localfilename = "$hashed_attachment_dir/$localfilename";
+
+            $fp = fopen( $full_localfilename, 'wb');
+            fwrite ($fp, $body);
+            fclose($fp);
+            $composeMessage->initAttachment('message/rfc822',$subject.'.msg',
+                 $full_localfilename);
+        }
+    }
+
+    $compose_messages[$composesession] = $composeMessage;
+    sqsession_register($compose_messages,'compose_messages');
+    return $composesession;
+}
+
 ?>
index c57af132fbe98d83f016b49bc775d8a277727500..86b141ff8056b4aee0c788b295dc8c618dcc5d20 100644 (file)
@@ -29,15 +29,15 @@ if (!defined('SQM_ADDR_HOST'))     define('SQM_ADDR_HOST',     3);
  **/
 
 function parseRFC822Address($sAddress,$aProps) {
-    $aPropsDefault = array (
-                            'domain' => '',         //
-                            'limit'  => 0,          // limits returned addresses
-                            'abooklookup' => false); // callback function for addressbook lookup
-
-    $aProps = is_array($aProps) ? array_merge($aPropsDefault,$aProps) : $aPropsDefault;
+//    $aPropsDefault = array (
+//                            'domain' => '',         //
+//                            'limit'  => 0,          // limits returned addresses
+//                            'abooklookup' => false); // callback function for addressbook lookup
+//
+//    $aProps = is_array($aProps) ? array_merge($aPropsDefault,$aProps) : $aPropsDefault;
 
-    $cbLookup = $aProps['abooklookup'];
-    $sDomain  = $aProps['domain'];
+//    $cbLookup = $aProps['abooklookup'];
+//    $sDomain  = $aProps['domain'];
     $iLimit   = $aProps['limit'];
 
     $aTokens = _getAddressTokens($sAddress);
index 618c64fa90c6e22000d2d6292683e9a25634cb92..1f91c82e436afc15b455fec217208ab489c1e6a6 100644 (file)
@@ -73,8 +73,8 @@ if (isset($chosen_theme) && $found_theme && (file_exists($chosen_theme))) {
 }
 
 
-if (!defined('download_php')) { 
-    sqsession_register($theme_css, 'theme_css'); 
+if (!defined('download_php')) {
+    sqsession_register($theme_css, 'theme_css');
 }
 
 // user's icon theme, if using icons
@@ -91,11 +91,11 @@ $move_to_trash =
 $save_as_draft =
     getPref($data_dir, $username, 'save_as_draft', $default_save_as_draft);
 
-if ($default_unseen_type == '') { 
-    $default_unseen_type = 1; 
+if ($default_unseen_type == '') {
+    $default_unseen_type = 1;
 }
-if ($default_unseen_notify == '') { 
-    $default_unseen_notify = 2; 
+if ($default_unseen_notify == '') {
+    $default_unseen_notify = 2;
 }
 $unseen_type =
     getPref($data_dir, $username, 'unseen_type', $default_unseen_type);
@@ -174,8 +174,6 @@ $reply_focus = getPref($data_dir, $username, 'reply_focus', '');
 $left_refresh = getPref($data_dir, $username, 'left_refresh', SMPREF_NONE );
 $left_refresh = strtolower($left_refresh);
 
-$sort = getPref($data_dir, $username, 'sort', 6 );
-
 /** Load up the Signature file **/
 $signature_abs = $signature = getSig($data_dir, $username, 'g');
 
index bdd2a23c3b45448b5bebc8d64ef4735eceb0715a..fa966ed4106a5058c913d059658e3ac5a0a28d82 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 /**
- * Path for SquirrelMail required files. 
+ * Path for SquirrelMail required files.
  * @ignore
  */
 define('SM_PATH','../');
@@ -31,23 +31,34 @@ header('Cache-Control: cache');
 sqgetGlobalVar('key',        $key,          SQ_COOKIE);
 sqgetGlobalVar('username',   $username,     SQ_SESSION);
 sqgetGlobalVar('onetimepad', $onetimepad,   SQ_SESSION);
+sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
 sqgetGlobalVar('messages',   $messages,     SQ_SESSION);
 sqgetGlobalVar('mailbox',    $mailbox,      SQ_GET);
 sqgetGlobalVar('ent_id',     $ent_id,       SQ_GET);
 sqgetGlobalVar('absolute_dl',$absolute_dl,  SQ_GET);
 if ( sqgetGlobalVar('passed_id', $temp, SQ_GET) ) {
-  $passed_id = (int) $temp;
+    $passed_id = (int) $temp;
 }
 
 /* end globals */
 
 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
-$mbx_response =  sqimap_mailbox_select($imapConnection, $mailbox);
+$aMailbox = sqm_api_mailbox_select($imapConnection, $mailbox,array(),array());
 
-$message = &$messages[$mbx_response['UIDVALIDITY']]["$passed_id"];
-if (!is_object($message)) {
-    $message = sqimap_get_message($imapConnection,$passed_id, $mailbox);
+if (isset($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT']) &&
+    is_object($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT']) ) {
+    $message = $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'];
+} else {
+   $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
+   $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
 }
+
+//$mbx_response =  sqimap_mailbox_select($imapConnection, $mailbox);
+
+//$message = &$messages[$mbx_response['UIDVALIDITY']]["$passed_id"];
+//if (!is_object($message)) {
+//    $message = sqimap_get_message($imapConnection,$passed_id, $mailbox);
+//}
 $subject = $message->rfc822_header->subject;
 if ($ent_id) {
     $message = &$message->getEntity($ent_id);
@@ -138,5 +149,6 @@ if (isset($absolute_dl) && $absolute_dl) {
 /* be aware that any warning caused by download.php will corrupt the
  * attachment in case of ERROR reporting = E_ALL and the output is the screen */
 mime_print_body_lines ($imapConnection, $passed_id, $ent_id, $encoding);
-
+$mailbox_cache[$aMailbox['NAME']] = $aMailbox;
+sqsession_register($mailbox_cache,'mailbox_cache');
 ?>
index 39c3b9d89143d8e83205053d587be3f19c4fcc2b..2863f5572ed20665b68415a23dbaed623abdcb59 100644 (file)
@@ -68,7 +68,7 @@ function formatMailboxName($imapConnection, $box_array) {
 
     /* Create the link for this folder. */
     if ($status !== false) {
-    $line .= '<a href="right_main.php?PG_SHOWALL=0&amp;sort=0&amp;startMessage=1&amp;mailbox='.
+    $line .= '<a href="right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox='.
                 $mailboxURL.'" TARGET="right" STYLE="text-decoration:none">';
     }
     if ($special_color) {
@@ -297,7 +297,7 @@ function is_parent_box($curbox_name, $parbox_name) {
 
 function ListBoxes ($boxes, $j=0 ) {
     global $data_dir, $username, $startmessage, $color, $unseen_notify, $unseen_type,
-           $move_to_trash, $trash_folder, $collapse_folders, $imapConnection, 
+           $move_to_trash, $trash_folder, $collapse_folders, $imapConnection,
            $use_icons, $icon_theme, $use_special_folder_color;
 
     if (!isset($boxes) || empty($boxes))
@@ -380,7 +380,7 @@ function ListBoxes ($boxes, $j=0 ) {
         if ($unseen > 0) {
             $pre .= '<b>';
         }
-        $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;sort=0;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
+        $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
         if ($unseen > 0) {
             $end .= '</b>';
         }
@@ -389,7 +389,7 @@ function ListBoxes ($boxes, $j=0 ) {
             if ($unseen > 0) {
                 $pre .= '<b>';
             }
-            $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;sort=0;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
+            $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
             if ($unseen > 0) {
                 $end .= '</b>';
             }
@@ -406,7 +406,7 @@ function ListBoxes ($boxes, $j=0 ) {
             if ($unseen > 0) {
                 $pre .= '<b>';
             }
-            $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;sort=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
+            $pre .= "<a href=\"right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\" style=\"text-decoration:none\">";
             if ($unseen > 0) {
                 $end .= '</b>';
             }
@@ -428,7 +428,7 @@ function ListBoxes ($boxes, $j=0 ) {
 
     // let plugins fiddle with end of line
     $end .= concat_hook_function('left_main_after_each_folder',
-        array(isset($numMessages) ? $numMessages : '', 
+        array(isset($numMessages) ? $numMessages : '',
               $boxes->mailboxname_full, $imapConnection));
 
     $end .= '</nobr>';
@@ -519,7 +519,7 @@ function ListAdvancedBoxes ($boxes, $mbx, $j='ID.0000' ) {
         if (! isset($numMessages)) {
             $numMessages = $boxes->total;
         }
-        $pre = "<a class=\"mbx_link\" href=\"right_main.php?PG_SHOWALL=0&amp;sort=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\">" . $pre;
+        $pre = "<a class=\"mbx_link\" href=\"right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\">" . $pre;
         $end .= '</a>';
         if ($numMessages > 0) {
             $urlMailbox = urlencode($mailbox);
@@ -529,7 +529,7 @@ function ListAdvancedBoxes ($boxes, $mbx, $j='ID.0000' ) {
         }
     } else {
         if (!$boxes->is_noselect) { /* \Noselect boxes can't be selected */
-            $pre = "<a class=\"mbx_link\" href=\"right_main.php?PG_SHOWALL=0&amp;sort=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\">" . $pre;
+            $pre = "<a class=\"mbx_link\" href=\"right_main.php?PG_SHOWALL=0&amp;startMessage=1&amp;mailbox=$mailboxURL\" target=\"right\">" . $pre;
             $end .= '</a>';
         }
     }
@@ -537,7 +537,7 @@ function ListAdvancedBoxes ($boxes, $mbx, $j='ID.0000' ) {
     // let plugins fiddle with end of line
     global $imapConnection;
     $end .= concat_hook_function('left_main_after_each_folder',
-        array(isset($numMessages) ? $numMessages : '', 
+        array(isset($numMessages) ? $numMessages : '',
               $boxes->mailboxname_full, $imapConnection));
 
     if (!$boxes->is_root) {
@@ -934,7 +934,7 @@ if ($auto_create_special && !isset($auto_create_done)) {
                 sqimap_mailbox_create($imapConnection, $folder, '');
             } else {
                 //if (!sqimap_mailbox_is_subscribed($imapConnection, $folder)) {
-                // check for subscription is useless and expensive  just 
+                // check for subscription is useless and expensive  just
                 // surpress the NO response
                 sqimap_subscribe($imapConnection, $folder, false);
             }
@@ -1112,7 +1112,7 @@ for ($i = 0; $i < count($boxes); $i++) {
         echo '</small>';
         echo '</form>'."\n";
     } else {
-        //sqimap_get_status_mbx_tree($imap_stream,$boxes)    
+        //sqimap_get_status_mbx_tree($imap_stream,$boxes)
         ListBoxes($boxes);
     }
 } /* if ($oldway) else ... */
index b3d757dff70b8ed903d5cb763c5df819a7e52434..d142747de2d3b05a8198f7ebc11857b6fcb5efe1 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-
+exit;
 /**
  * move_messages.php
  *
@@ -265,5 +265,136 @@ if ($exception) {
     header("Location: $location");
     exit;
 }
+
+function handleMessageListForm($imapConnection,&$aMailbox) {
+    /* incoming formdata */
+    sqgetGlobalVar('moveButton',      $moveButton,      SQ_POST);
+    sqgetGlobalVar('expungeButton',   $expungeButton,   SQ_POST);
+    sqgetGlobalVar('targetMailbox',   $targetMailbox,   SQ_POST);
+    sqgetGlobalVar('expungeButton',   $expungeButton,   SQ_POST);
+    sqgetGlobalVar('undeleteButton',  $undeleteButton,  SQ_POST);
+    sqgetGlobalVar('markRead',        $markRead,        SQ_POST);
+    sqgetGlobalVar('markUnread',      $markUnread,      SQ_POST);
+    sqgetGlobalVar('markFlagged',     $markFlagged,     SQ_POST);
+    sqgetGlobalVar('markUnflagged',   $markUnflagged,   SQ_POST);
+    sqgetGlobalVar('attache',         $attache,         SQ_POST);
+    sqgetGlobalVar('location',        $location,        SQ_POST);
+    sqgetGlobalVar('bypass_trash',    $bypass_trash,    SQ_POST);
+    sqgetGlobalVar('msg',             $msg,             SQ_POST);
+
+    $sError = '';
+    /* retrieve the check boxes */
+    $aUid = array();
+    if (isset($msg) && is_array($msg)) {
+        foreach( $msg as $key=>$iUid ) {
+            // using foreach removes the risk of infinite loops that was there //
+            $aUid[] = $iUid;
+        }
+    }
+    $num_ids = count($id);
+
+    if (count($num_ids) && !isset($expungeButton)) {
+        /* handle submit buttons */
+        $sButton = '';
+        $sButton = (isset($expungeButton)) ? 'expunge'      : $sButton;
+        $sButton = (isset($attache))       ? 'attache'      : $sButton;
+        $sButton = (isset($moveButton))    ? 'move'         : $sButton;
+        $sButton = (isset($copyButton))    ? 'copy'         : $sButton;
+        $sButton = (isset($markDelete))    ? 'setDeleted'   : $sButton;
+        $sButton = (isset($markUndelete))  ? 'unsetDeleted' : $sButton;
+        $sButton = (isset($markSeen))      ? 'setSeen'      : $sButton;
+        $sButton = (isset($markUnseen))    ? 'unsetSeen'    : $sButton;
+        $sButton = (isset($markFlagged))   ? 'setFlagged'   : $sButton;
+        $sButton = (isset($markUnflagged)) ? 'unsetFlagged' : $sButton;
+
+        $aUpdatedMsgs = false;
+        $bExpunge = false;
+        switch ($sButton) {
+          case 'setDeleted':
+            // What kind of hook is this, can it be removed?
+            if (!boolean_hook_function('move_messages_button_action', NULL, 1)) {
+                $aUpdatedMsgs = sqimap_msgs_list_delete($imapConnection, $mailbox, $aUid,$bypass_trash);
+                $bExpunge = true;
+            }
+            break;
+          case 'unsetDeleted':
+          case 'setSeen':
+          case 'unsetSeen':
+          case 'setFlagged':
+          case 'unsetFlagged':
+            // get flag
+            $sFlag = (substr($sButton,0,3) == 'set') ? '\\'.substr($sButton,3) : '\\'.substr($sButton,5);
+            $bSet  = (substr($sButton,0,3) == 'set') ? true : false;
+            $aUpdatedMsgs = sqimap_toggle_flag($imapConnection, $aUid, $sFlag, $bSet, true);
+            break;
+          case 'move':
+            $aUpdatedMsgs = sqimap_msgs_list_move($imapConnection,$aId,$targetMailbox);
+            $bExpunge = true;
+            break;
+          case 'attache':
+            $composesession = attachSelectedMessages($id, $imapConnection);
+            // dirty hack, add info to $aMailbox
+            $aMailbox['FORWARD_SESSION'] = $composesession;
+            break;
+        }
+
+        if ($aUpdatedMsgs) {
+            foreach ($aUpdatedMsgs as $iUid => $aMsg) {
+                if (isset($aMsg['FLAGS'])) {
+                    $aMailbox['MSG_HEADERS'][$iUid]['FLAGS'] = $aMsg['FLAGS'];
+                }
+            }
+            if ($bExpunge && $aMailbox['AUTO_EXPUNGE'] &&
+                $iExpungedMessages = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true))
+                {
+                if (count($aUpdateMsgs != $iExpungedMessages)) {
+                    // there are more messages deleted permanently then we expected
+                    // invalidate the cache
+                    $aMailbox['UIDSET'] = false;
+                    $aMailbox['MSG_HEADERS'] = false;
+                } else {
+                    // remove expunged messages from cache
+                    $aUidSet = $aMailbox['UIDSET'];
+                    $aDeleted = array();
+                    foreach ($aUpdatedMsgs as $iUid => $aValue) {
+                        if (isset($aValue['FLAGS']['\\deleted']) && $aValue['FLAGS']['\\deleted']) {
+                            $aDeleted[] = $iUid;
+                        }
+                    }
+                    if (count($aDeleted)) {
+                        // create a UID => array index temp array
+                        $aUidSetDummy = array_flip($aUidSet);
+                        foreach ($aDeleted as $iUid) {
+                            unset($aUidSetDummy[$iUid]);
+                        }
+                        $aUidSet = array_keys($aUidSetDummy);
+                        $aMailbox['UIDSET'] = $aUidSet;
+                        // update EXISTS info
+                        $aMailbox['EXISTS'] -= $iExpungedMessages;
+                    }
+                }
+                // Change the startMessage number if the mailbox was changed
+                if (($aMailbox['PAGEOFFSET']+$iExpungedMessages-1) >= $aMailbox['EXISTS']) {
+                    $aMailbox['PAGEOFFSET'] = ($aMailbox['PAGEOFFSET'] > $aMailbox['LIMIT']) ?
+                        $aMailbox['PAGEOFFSET'] - $aMailbox['LIMIT'] : 1;
+                }
+            }
+        }
+    } else {
+        if (isset($expungeButton)) {
+            // on expunge we do not know which messages will be deleted
+            // so it's useless to try to sync the cache
+
+            // Close the mailbox so we do not need to parse the untagged expunge responses
+            sqimap_run_command($imapConnection,'CLOSE',false,$result,$message);
+            $aMbxResponse = sqimap_select($imapConnection,$aMailbox['NAME'];
+            // update the $aMailbox array
+            $aMailbox['EXISTS'] = $aMbxResponse['EXISTS'];
+            $aMailbox['UIDSET'] = false;
+        } else {
+            $sError = _("No messages were selected.");
+        }
+    }
+}
 ?>
 </BODY></HTML>
index 7e12373efcb5c20c50b35f2441a3ecbf61c26708..43805d1531592f20e8fe2d2d37541a761739ef54 100644 (file)
@@ -38,10 +38,11 @@ require_once(SM_PATH . 'functions/mailbox_display.php');
  * @return the index of the next valid message from the array
  */
 function findNextMessage($uidset,$passed_id='backwards') {
+    if (!is_array($uidset)) {
+        return -1;
+    }
     if ($passed_id=='backwards' || !is_array($uidset)) { // check for backwards compattibilty gpg plugin
         $passed_id = $uidset;
-        sqgetGlobalVar('server_sort_array',$server_sort_array,SQ_SESSION);
-        $uidset = $server_sort_array;
     }
     $result = -1;
     $count = count($uidset) - 1;
@@ -66,9 +67,8 @@ function findNextMessage($uidset,$passed_id='backwards') {
  */
 
 function findPreviousMessage($uidset, $passed_id) {
-    if (!is_array($uidset)) { //obsolete check
-        sqgetGlobalVar('server_sort_array',$server_sort_array,SQ_SESSION);
-        $uidset = $server_sort_array;
+    if (!is_array($uidset)) {
+        return -1;
     }
     $result = -1;
     foreach($uidset as $key=>$value) {
@@ -298,16 +298,16 @@ function ClearAttachments() {
 
     $rem_attachments = array();
     if (isset($attachments)) {
-       foreach ($attachments as $info) {
-           if ($info['session'] == -1) {
-               $attached_file = "$hashed_attachment_dir/$info[localfilename]";
-               if (file_exists($attached_file)) {
-                   unlink($attached_file);
-               }
-           } else {
-               $rem_attachments[] = $info;
-           }
-       }
+        foreach ($attachments as $info) {
+            if ($info['session'] == -1) {
+                $attached_file = "$hashed_attachment_dir/$info[localfilename]";
+                if (file_exists($attached_file)) {
+                        unlink($attached_file);
+                }
+            } else {
+                $rem_attachments[] = $info;
+            }
+        }
     }
     $attachments = $rem_attachments;
 }
@@ -456,7 +456,7 @@ function formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message,
  * @param object $message Current message object
  * @param object $mbx_response
  */
-function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_response, $nav_on_top = TRUE) {
+function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $removedVar, $nav_on_top = TRUE) {
     global $base_uri, $draft_folder, $where, $what, $color, $sort,
            $startMessage, $PHP_SELF, $save_as_draft,
            $enable_forward_as_attachment, $imapConnection, $lastTargetMailbox,
@@ -523,14 +523,21 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
         $nav_row .= $double_delimiter . '[<a href="'.$url.'">'._("View Message").'</a>]';
 
     // Prev/Next links for regular messages
-    } else if ( !(isset($where) && isset($what)) ) {
-        $prev = findPreviousMessage($aMailbox['UIDSET'], $passed_id);
-        $next = findNextMessage($aMailbox['UIDSET'],$passed_id);
+    } else if ( true ) { //!(isset($where) && isset($what)) ) {
+        /**
+         * Check if cache is still valid
+         */
+        if (!is_array($aMailbox['UIDSET'][$what])) {
+            fetchMessageHeaders($imapConnection, $aMailbox);
+        }
+        $prev = findPreviousMessage($aMailbox['UIDSET'][$what], $passed_id);
+        $next = findNextMessage($aMailbox['UIDSET'][$what],$passed_id);
 
         $prev_link = _("Previous");
         if ($prev >= 0) {
             $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
                    '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
+                   "&amp;where=$where&amp;what=$what" .
                    '&amp;startMessage='.$startMessage.'&amp;show_more=0';
             $prev_link = '<a href="'.$uri.'">'.$prev_link.'</a>';
         }
@@ -539,6 +546,7 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
         if ($next >= 0) {
             $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
                    '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
+                   "&amp;where=$where&amp;what=$what" .
                    '&amp;startMessage='.$startMessage.'&amp;show_more=0';
             $next_link = '<a href="'.$uri.'">'.$next_link.'</a>';
         }
@@ -546,12 +554,13 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
         // Only bother with Delete & Prev and Delete & Next IF
         // top display is enabled.
         if ( $delete_prev_next_display == 1 &&
-               in_array('\\deleted', $mbx_response['PERMANENTFLAGS'],true) ) {
+               in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
             $del_prev_link = _("Delete & Prev");
             if ($prev >= 0) {
                 $uri = $base_uri . 'src/read_body.php?passed_id='.$prev.
                        '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                        '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
+                       "&amp;where=$where&amp;what=$what" .
                        '&amp;delete_id='.$passed_id;
                 $del_prev_link = '<a href="'.$uri.'">'.$del_prev_link.'</a>';
             }
@@ -561,6 +570,7 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
                 $uri = $base_uri . 'src/read_body.php?passed_id='.$next.
                        '&amp;mailbox='.$urlMailbox.'&amp;sort='.$sort.
                        '&amp;startMessage='.$startMessage.'&amp;show_more=0'.
+                       "&amp;where=$where&amp;what=$what" .
                        '&amp;delete_id='.$passed_id;
                 $del_next_link = '<a href="'.$uri.'">'.$del_next_link.'</a>';
             }
@@ -572,13 +582,11 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
     }
 
     // Start with Search Results or Message List link.
-    if (isset($where) && isset($what)) {
-        $msgs_url .= 'search.php?where=' . urlencode($where) .
-                     '&amp;what=' . urlencode($what) . '&amp;mailbox=' . $urlMailbox;
+    $msgs_url .= "$where?where=read_body.php&amp;what=$what&amp;mailbox=" . $urlMailbox.
+                 "&amp;startMessage=$startMessage";
+    if ($where == 'search.php') {
         $msgs_str  = _("Search Results");
     } else {
-        $msgs_url .= 'right_main.php?sort=' . $sort . '&amp;startMessage=' .
-                     $startMessage . '&amp;mailbox=' . $urlMailbox;
         $msgs_str  = _("Message List");
     }
     $nav_row .= $double_delimiter .
@@ -632,26 +640,19 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
 
     $menu_row .= '</form>&nbsp;';
 
-    if ( in_array('\\deleted', $mbx_response['PERMANENTFLAGS'],true) ) {
-    // Form for deletion
-        $delete_url = $base_uri . 'src/delete_message.php?mailbox=' . $urlMailbox;
+    if ( in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
+    // Form for deletion. Form is handled by the originating display in $where. This is right_main.php or search.php
+        $delete_url = $base_uri . "src/$where";
         $menu_row .= '<form action="'.$delete_url.'" method="post" style="display: inline">';
 
         if (!(isset($passed_ent_id) && $passed_ent_id)) {
-            $menu_row .= addHidden('message', $passed_id);
-
-            if ($where && $what) {
-            $menu_row .= addHidden('where', $where);
-            $menu_row .= addHidden('what',  $what);
-            } else {
-            $menu_row .= addHidden('sort',  $sort);
-            $menu_row .= addHidden('startMessage', $startMessage);
-            }
+            $menu_row .= addHidden('mailbox', $aMailbox['NAME']);
+            $menu_row .= addHidden('msg[0]', $passed_id);
             $menu_row .= getButton('SUBMIT', 'delete', _("Delete"));
             $menu_row .= '<input type="checkbox" name="bypass_trash">' . _("Bypass Trash");
+        } else {
+            $menu_row .= getButton('SUBMIT', 'delete', _("Delete"), '', FALSE) . "\n"; // delete button is disabled
         }
-        else
-        $menu_row .= getButton('SUBMIT', 'delete', _("Delete"), '', FALSE) . "\n"; // delete button is disabled
 
         $menu_row .= '</form>';
     }
@@ -659,25 +660,13 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res
     // Add top move link
     $menu_row .= '</small></td><td align="right">';
     if ( !(isset($passed_ent_id) && $passed_ent_id) &&
-        in_array('\\deleted', $mbx_response['PERMANENTFLAGS'],true) ) {
-
-        $current_box = 'mailbox='.$mailbox.'&sort='.$sort.'&startMessage='.$startMessage;
-
-        // Set subsequent location based on whether or not there is a 'next' message.
-        if ( isset($next) && $next >= 0 ) {
-            $location = $base_uri . 'src/read_body.php?passed_id='.$next.'&';
-        } elseif (isset($prev) && $prev >= 0) {
-            $location = $base_uri . 'src/read_body.php?passed_id='.$prev.'&';
-        } else {
-            $location = $base_uri . 'src/right_main.php?';
-        }
+        in_array('\\deleted', $aMailbox['PERMANENTFLAGS'],true) ) {
 
-        $menu_row .= '<form action="'.$base_uri.'src/move_messages.php?'.$current_box.'" method="post" style="display: inline">'.
+        $menu_row .= '<form action="'.$base_uri.'src/'.$where.'?'.'" method="post" style="display: inline">'.
               '<small>'.
-             addHidden('show_more', '0' ).
-             addHidden('dmn', '1').
-             addHidden('location', $location.$current_box).
-             addHidden('msg[0]', $passed_id) . _("Move to:") .
+
+          addHidden('mailbox',$aMailbox['NAME']) .
+          addHidden('msg[0]', $passed_id) . _("Move to:") .
               '<select name="targetMailbox" style="padding: 0px; margin: 0px">';
 
         if (isset($lastTargetMailbox) && !empty($lastTargetMailbox)) {
@@ -753,19 +742,19 @@ sqgetGlobalVar('username',  $username,      SQ_SESSION);
 sqgetGlobalVar('onetimepad',$onetimepad,    SQ_SESSION);
 sqgetGlobalVar('delimiter', $delimiter,     SQ_SESSION);
 sqgetGlobalVar('base_uri',  $base_uri,      SQ_SESSION);
-
-sqgetGlobalVar('msgs',      $msgs,          SQ_SESSION);
-sqgetGlobalVar('msort',     $msort,         SQ_SESSION);
 sqgetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
-sqgetGlobalVar('server_sort_array', $server_sort_array, SQ_SESSION);
 if (!sqgetGlobalVar('messages', $messages, SQ_SESSION) ) {
     $messages = array();
 }
 
 /** GET VARS */
 sqgetGlobalVar('sendreceipt',   $sendreceipt,   SQ_GET);
-sqgetGlobalVar('where',         $where,         SQ_GET);
-sqgetGlobalVar('what',          $what,          SQ_GET);
+if (!sqgetGlobalVar('where',         $where,         SQ_GET) ) {
+    $where = 'right_main.php';
+}
+if (!sqgetGlobalVar('what',          $what,          SQ_GET) ){
+    $what = 0;
+}
 if ( sqgetGlobalVar('show_more', $temp,  SQ_GET) ) {
     $show_more = (int) $temp;
 }
@@ -791,39 +780,36 @@ if ( sqgetGlobalVar('sort', $temp) ) {
 }
 if ( sqgetGlobalVar('startMessage', $temp) ) {
     $startMessage = (int) $temp;
+} else {
+    $startMessage = 1;
 }
+/**
+ * Retrieve mailbox cache
+ */
+sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
 
 /* end of get globals */
 global $sqimap_capabilities, $lastTargetMailbox;
 
 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
-$mbx_response   = sqimap_mailbox_select($imapConnection, $mailbox, false, false, true);
+$aMailbox = sqm_api_mailbox_select($imapConnection, $mailbox,array('setindex' => $what),array());
 
-global $allow_thread_sort, $auto_expunge;
-
-if ($allow_thread_sort && getPref($data_dir, $username, "thread_$mailbox",0)) {
-    $aMailbox['SORT_METHOD'] = 'THREAD';
-} else if ($allow_server_sort) {
-    $aMailbox['SORT_METHOD'] = 'SERVER';
-} else {
-    $aMailbox['SORT_METHOD'] = 'SQUIRREL';
+/**
+ * Update the seen state
+ * and ignore in_array('\\seen',$aMailbox['PERMANENTFLAGS'],true)
+ */
+if (isset($aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'])) {
+    $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS']['\\seen'] = true;
 }
-sqgetGlobalVar('aLastSelectedMailbox',$aMailbox,SQ_SESSION);
-$aMailbox['UIDSET'] = $server_sort_array;
-$aMailbox['SORT'] = $sort;
-$aMailbox['NAME'] = $mailbox;
-$aMailbox['EXISTS'] = $mbx_response['EXISTS'];
-$aMailbox['AUTO_EXPUNGE'] = $auto_expunge;
-$aMailbox['MSG_HEADERS'] = $msgs;
-
 
 /**
  * Process Delete from delete-move-next
  * but only if delete_id was set
  */
 if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
-    sqimap_messages_delete($imapConnection, $delete_id, $delete_id, $mailbox);
-    sqimap_mailbox_expunge_dmn($imapConnection,$aMailbox,$delete_id);
+    handleMessageListForm($imapConnection,$aMailbox,$sButton='setDeleted', array($delete_id));
+//    sqimap_messages_delete($imapConnection, $delete_id, $delete_id, $mailbox);
+//    sqimap_mailbox_expunge_dmn($imapConnection,$aMailbox,$delete_id);
 }
 
 /**
@@ -831,33 +817,27 @@ if ( sqgetGlobalVar('delete_id', $delete_id, SQ_GET) ) {
  * including header and body
  */
 
-$uidvalidity = $mbx_response['UIDVALIDITY'];
-
-if (!isset($messages[$uidvalidity])) {
-   $messages[$uidvalidity] = array();
-}
-if (!isset($messages[$uidvalidity][$passed_id]) || $delete_id) {
-   $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
-   $FirstTimeSee = !$message->is_seen;
-   $message->is_seen = true;
-   $messages[$uidvalidity][$passed_id] = $message;
+if (isset($aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'])) {
+    $message = $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'];
+    $FirstTimeSee = !$message->is_seen;
 } else {
-//   $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
-   $message = $messages[$uidvalidity][$passed_id];
-   $FirstTimeSee = !$message->is_seen;
+    $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
+    $FirstTimeSee = !$message->is_seen;
+    $message->is_seen = true;
+    $aMailbox['MSG_HEADERS'][$passed_id]['MESSAGE_OBJECT'] = $message;
 }
 
 if (isset($passed_ent_id) && $passed_ent_id) {
-   $message = $message->getEntity($passed_ent_id);
-   if ($message->type0 != 'message'  && $message->type1 != 'rfc822') {
-      $message = $message->parent;
-   }
-   $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[$passed_ent_id.HEADER]", true, $response, $msg, TRUE);
-   $rfc822_header = new Rfc822Header();
-   $rfc822_header->parseHeader($read);
-   $message->rfc822_header = $rfc822_header;
+    $message = $message->getEntity($passed_ent_id);
+    if ($message->type0 != 'message'  && $message->type1 != 'rfc822') {
+        $message = $message->parent;
+    }
+    $read = sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[$passed_ent_id.HEADER]", true, $response, $msg, TRUE);
+    $rfc822_header = new Rfc822Header();
+    $rfc822_header->parseHeader($read);
+    $message->rfc822_header = $rfc822_header;
 } else {
-   $passed_ent_id = 0;
+    $passed_ent_id = 0;
 }
 $header = $message->header;
 
@@ -874,7 +854,7 @@ if (isset($sendreceipt)) {
          $final_recipient = trim(getPref($data_dir, $username, 'email_address' . $identity, '' ));
       if ($final_recipient == '' )
          $final_recipient = trim(getPref($data_dir, $username, 'email_address', '' ));
-      $supportMDN = ServerMDNSupport($mbx_response["PERMANENTFLAGS"]);
+      $supportMDN = ServerMDNSupport($aMailbox["PERMANENTFLAGS"]);
       if ( SendMDN( $mailbox, $passed_id, $final_recipient, $message, $imapConnection ) > 0 && $supportMDN ) {
          ToggleMDNflag( true, $imapConnection, $mailbox, $passed_id);
          $message->is_mdnsent = true;
@@ -887,7 +867,7 @@ if (isset($sendreceipt)) {
 /* End of block for handling incoming url vars */
 /***********************************************/
 
-$msgs[$passed_id]['FLAG_SEEN'] = true;
+
 
 $messagebody = '';
 do_hook('read_body_top');
@@ -905,7 +885,7 @@ for ($i = 0; $i < $cnt; $i++) {
 }
 
 displayPageHeader($color, $mailbox);
-formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_response);
+formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message,false);
 formatEnvheader($aMailbox, $passed_id, $passed_ent_id, $message, $color, $FirstTimeSee);
 echo '<table width="100%" cellpadding="0" cellspacing="0" align="center" border="0">';
 echo '  <tr><td>';
@@ -966,15 +946,16 @@ if (($attachment_common_show_images) &&
     }
 }
 
-formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_response, FALSE);
+formatMenuBar($aMailbox, $passed_id, $passed_ent_id, $message, false, FALSE);
 
 do_hook('read_body_bottom');
 do_hook('html_bottom');
 sqimap_logout($imapConnection);
 /* sessions are written at the end of the script. it's better to register
    them at the end so we avoid double session_register calls */
-sqsession_register($messages,'messages');
-
+/* add the mailbox to the cache */
+$mailbox_cache[$aMailbox['NAME']] = $aMailbox;
+sqsession_register($mailbox_cache,'mailbox_cache');
 ?>
 </body>
 </html>
index c8ec8ab5cf42d188b7e15414f9df046e6c0c4cf8..ac40bf2a7deafa0e4989d43034c49c73a9776f73 100644 (file)
@@ -54,32 +54,28 @@ sqgetGlobalVar('base_uri',  $base_uri,      SQ_SESSION);
 
 sqgetGlobalVar('mailbox',   $mailbox);
 sqgetGlobalVar('lastTargetMailbox', $lastTargetMailbox, SQ_SESSION);
-sqgetGlobalVar('sort'             , $sort,              SQ_SESSION);
-sqgetGlobalVar('session',           $session,           SQ_GET);
+sqgetGlobalVar('targetMailbox', $lastTargetMailbox, SQ_POST);
 sqgetGlobalVar('note',              $note,              SQ_GET);
 sqgetGlobalVar('mail_sent',         $mail_sent,         SQ_GET);
 
+
 if ( sqgetGlobalVar('startMessage', $temp) ) {
-  $startMessage = (int) $temp;
-}
-if ( sqgetGlobalVar('PG_SHOWNUM', $temp) ) {
-  $PG_SHOWNUM = (int) $temp;
+    $startMessage = (int) $temp;
+} else {
+    $startMessage = 1;
 }
-if ( sqgetGlobalVar('PG_SHOWALL', $temp, SQ_GET) ) {
-  $PG_SHOWALL = (int) $temp;
+// sort => srt because of the changed behaviour which can break new behaviour
+if ( sqgetGlobalVar('srt', $temp, SQ_GET) ) {
+    $srt = (int) $temp;
 }
-if ( sqgetGlobalVar('newsort', $temp, SQ_GET) ) {
-  $newsort = (int) $temp;
+
+if ( sqgetGlobalVar('showall', $temp, SQ_GET) ) {
+    $showall = (int) $temp;
 }
+
 if ( sqgetGlobalVar('checkall', $temp, SQ_GET) ) {
   $checkall = (int) $temp;
 }
-if ( sqgetGlobalVar('set_thread', $temp, SQ_GET) ) {
-  $set_thread = (int) $temp;
-}
-if ( !sqgetGlobalVar('composenew', $composenew, SQ_GET) ) {
-    $composenew = false;
-}
 /* end of get globals */
 
 
@@ -87,133 +83,120 @@ if ( !sqgetGlobalVar('composenew', $composenew, SQ_GET) ) {
 
 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
 
-if (isset($PG_SHOWALL)) {
-    if ($PG_SHOWALL) {
-       $PG_SHOWNUM=999999;
-       $show_num=$PG_SHOWNUM;
-       sqsession_register($PG_SHOWNUM, 'PG_SHOWNUM');
-    }
-    else {
-       sqsession_unregister('PG_SHOWNUM');
-       unset($PG_SHOWNUM);
-    }
-}
-else if( isset( $PG_SHOWNUM ) ) {
-    $show_num = $PG_SHOWNUM;
-}
 $mailbox = (isset($mailbox) && $mailbox) ? $mailbox : 'INBOX';
+
 /* compensate for the UW vulnerability. */
 if ($imap_server_type == 'uw' && (strstr($mailbox, '../') ||
                                   substr($mailbox, 0, 1) == '/')) {
    $mailbox = 'INBOX';
 }
+/**
+ * Set the global settings for a mailbox and merge them with the usersettings
+ * for the mailbox. In the future we can add more mailbox specific preferences
+ * preferences.
+ */
 
-if (isset($newsort) ) {
-    if ( $newsort != $sort ) {
-        setPref($data_dir, $username, 'sort', $newsort);
-    }
-    $oldsort = $sort;
-    $sort = $newsort;
-    sqsession_register($sort, 'sort');
-}
 
+$aMailboxGlobalPref = array(
+                       MBX_PREF_SORT         => 0,
+                       MBX_PREF_LIMIT        => (int)  $show_num,
+                       MBX_PREF_AUTO_EXPUNGE => (bool) $auto_expunge,
+                       MBX_PREF_INTERNALDATE => (bool) getPref($data_dir, $username, 'internal_date_sort')
+                    // MBX_PREF_FUTURE       => (var)  $future
+                     );
+
+/* not sure if this hook should be capable to alter the global pref array */
 do_hook ('generic_header');
 
-$aMbxResponse = sqimap_mailbox_select($imapConnection, $mailbox);
-$aMbxResponse['SORT_ARRAY'] = false;
+$aMailboxPrefSer=getPref($data_dir, $username, "pref_$mailbox");
+if ($aMailboxPrefSer) {
+    $aMailboxPref = unserialize($aMailboxPrefSer);
+} else {
+    setUserPref($username,"pref_$mailbox",serialize($aMailboxGlobalPref));
+    $aMailboxPref = $aMailboxGlobalPref;
+}
+if (isset($srt)) {
+    $aMailboxPref[MBX_PREF_SORT] = (int) $srt;
+}
+
+
+/**
+ * until there is no per mailbox option screen to set prefs we override
+ * the mailboxprefs by the default ones
+ */
+$aMailboxPref[MBX_PREF_LIMIT] = (int)  $show_num;
+$aMailboxPref[MBX_PREF_AUTO_EXPUNGE] = (bool) $auto_expunge;
+$aMailboxPref[MBX_PREF_INTERNALDATE] = (bool) getPref($data_dir, $username, 'internal_date_sort');
 
-sqgetGlobalVar('aLastSelectedMailbox',$aLastSelectedMailbox,SQ_SESSION);
 
-// deal with imap servers that do not return the required UIDNEXT or
-// UIDVALIDITY response
-// from a SELECT call (since rfc 3501 it's required)
-if (!isset($aMbxResponse['UIDNEXT']) || !isset($aMbxResponse['UIDVALIDITY'])) {
-    $aStatus = sqimap_status_messages($imapConnection,$mailbox,
-                                      array('UIDNEXT','UIDVALIDITY'));
-    $aMbxResponse['UIDNEXT'] = $aStatus['UIDNEXT'];
-    $aMbxResponse['UIDVALIDTY'] = $aStatus['UIDVALIDITY'];
+/**
+ * system wide admin settings and incoming vars.
+ */
+$aConfig = array(
+                'allow_thread_sort' => $allow_thread_sort,
+                'allow_server_sort' => $allow_server_sort,
+                'user'              => $username,
+                // incoming vars
+                'offset' => $startMessage
+                );
+/**
+ * The showall functionality is for the moment added to the config array
+ * to avoid storage of the showall link in the mailbox pref. We could change
+ * this behaviour later and add it to $aMailboxPref instead
+ */
+if (isset($showall)) {
+   $aConfig['showall'] = $showall;
 }
 
-if ($aLastSelectedMailbox) {
-    // check if we deal with the same mailbox
-    if ($aLastSelectedMailbox['NAME'] == $mailbox) {
-       if ($aLastSelectedMailbox['EXISTS'] == $aMbxResponse['EXISTS'] &&
-           $aLastSelectedMailbox['UIDVALIDITY'] == $aMbxResponse['UIDVALIDITY'] &&
-           $aLastSelectedMailbox['UIDNEXT']  == $aMbxResponse['UIDNEXT']) {
-           sqgetGlobalVar('server_sort_array',$server_sort_array,SQ_SESSION);
-           if ($server_sort_array && is_array($server_sort_array)) {
-               $aMbxResponse['SORT_ARRAY'] = $server_sort_array;
-               // check if oldsort can be used in case we changed the sort order of the same column
-               if (isset($newsort) && $newsort) {
-                    if ((($newsort % 2) && ($newsort + 1 == $oldsort)) ||
-                        (!($newsort % 2) && ($newsort - 1 == $oldsort))) {
-                        $server_sort_array = array_reverse($server_sort_array);
-                    } else {
-                        $server_sort_array = false;
-                    }
-               }
-               $aMbxResponse['SORT_ARRAY'] = $server_sort_array;
-           }
-       }
-    }
+/**
+ * Retrieve the mailbox cache from the session.
+ */
+sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
+
+
+$aMailbox = sqm_api_mailbox_select($imapConnection,$mailbox,$aConfig,$aMailboxPref);
+
+
+/*
+ * After initialisation of the mailbox array it's time to handle the FORM data
+ */
+$sError = handleMessageListForm($imapConnection,$aMailbox);
+if ($sError) {
+   $note = $sError;
 }
 
-$aLastSelectedMailbox['NAME'] = $mailbox;
-$aLastSelectedMailbox['EXISTS'] = $aMbxResponse['EXISTS'];
-$aLastSelectedMailbox['UIDVALIDITY'] = $aMbxResponse['UIDVALIDITY'];
-$aLastSelectedMailbox['UIDNEXT'] = $aMbxResponse['UIDNEXT'];
-$aLastSelectedMailbox['PERMANENTFLAGS'] = $aMbxResponse['PERMANENTFLAGS'];
-$aLastSelectedMailbox['OFFSET'] = (isset($startMessage) && $startMessage) ? $startMessage -1 : 0;
-$aLastSelectedMailbox['PAGEOFFSET'] = (isset($startMessage) && $startMessage) ? $startMessage : 1;
-$aLastSelectedMailbox['SORT'] = ($sort !== false) ? $sort : 0;
-$aLastSelectedMailbox['LIMIT'] = ($show_num != 999999) ? $show_num : $aMbxResponse['EXISTS'];
-
-$aLastSelectedMailbox['UIDSET'] = $aMbxResponse['SORT_ARRAY'];
-$aLastSelectedMailbox['SEEN'] = (isset($aMbxResponse['SEEN'])) ? $aMbxResponse['SEEN'] : $aMbxResponse['EXISTS'];
-$aLastSelectedMailbox['RECENT'] = (isset($aMbxResponse['RECENT'])) ? $aMbxResponse['RECENT'] : 0;
-$aLastSelectedMailbox['RIGHTS'] = $aMbxResponse['RIGHTS'];
-
-$aLastSelectedMailbox['AUTO_EXPUNGE'] = $auto_expunge;
-
-/* decide if we are thread sorting or not */
-$aLastSelectedMailbox['ALLOW_THREAD'] = $allow_thread_sort;
-if ($allow_thread_sort == TRUE) {
-    if (isset($set_thread)) {
-        $aLastSelectedMailbox['SORT_ARRAY'] = false;
-        if (sqsession_is_registered('indent_array')) {
-            sqsession_unregister('indent_array');
-        }
-        if (sqsession_is_registered('server_sort_array')) {
-            sqsession_unregister('server_sort_array');
-        }
-        if ($set_thread == 1) {
-            setPref($data_dir, $username, "thread_$mailbox", 1);
-            $thread_sort_messages = '1';
-        } else if ($set_thread == 2)  {
-            setPref($data_dir, $username, "thread_$mailbox", 0);
-            $thread_sort_messages = '0';
-        }
+/*
+ * If we try to forward messages as attachment we have to open a new window
+ * in case of compose in new window or redirect to compose.php
+ */
+if (isset($aMailbox['FORWARD_SESSION'])) {
+    if ($compose_new_win) {
+        // write the session in order to make sure that the compose window has
+        // access to the composemessages array which is stored in the session
+        session_write_close();
+        sqsession_is_active();
+        $comp_uri = SM_PATH . 'src/compose.php?mailbox='. urlencode($mailbox).
+                    '&session='.$aMailbox['FORWARD_SESSION'];
+        displayPageHeader($color, $mailbox, "comp_in_new('$comp_uri');", false);
     } else {
-        $thread_sort_messages = getPref($data_dir, $username, "thread_$mailbox");
+        // save mailboxstate
+        sqsession_register($aMailbox,'aLastSelectedMailbox');
+        session_write_close();
+        // we have to redirect to the compose page
+        global $PHP_SELF;
+        if (!strpos($PHP_SELF,'?')) {
+            $location = $PHP_SELF.'?mailbox=INBOX&amp;startMessage=1';
+        } else {
+            $location = $PHP_SELF;
+        }
+        $location = set_url_var($location, 'session',$aMailbox['FORWARD_SESSION'], false);
+        header("Location: $location");
+        exit;
     }
-} else {
-    $thread_sort_messages = 0;
-}
-if ($thread_sort_messages == 1) {
-    $aLastSelectedMailbox['SORT_METHOD'] = 'THREAD';
-} else if ($allow_server_sort) {
-    $aLastSelectedMailbox['SORT_METHOD'] = 'SERVER';
-} else {
-    $aLastSelectedMailbox['SORT_METHOD'] = 'SQUIRREL';
-}
-
-if ($composenew) {
-    $comp_uri = SM_PATH . 'src/compose.php?mailbox='. urlencode($mailbox).
-        "&session=$session";
-    displayPageHeader($color, $mailbox, "comp_in_new('$comp_uri');", false);
 } else {
     displayPageHeader($color, $mailbox);
 }
+
 do_hook('right_main_after_header');
 
 /* display a message to the user that their mail has been sent */
@@ -244,13 +227,29 @@ if ( sqgetGlobalVar('just_logged_in', $just_logged_in, SQ_SESSION) ) {
         }
     }
 }
-
-showMessagesForMailbox($imapConnection,$aLastSelectedMailbox);
+if ($aMailbox['EXISTS'] > 0) {
+    showMessagesForMailbox($imapConnection,$aMailbox);
+} else {
+    $string = '<b>' . _("THIS FOLDER IS EMPTY") . '</b>';
+    echo '    <table width="100%" cellpadding="1" cellspacing="0" align="center"'.' border="0" bgcolor="'.$color[9].'">';
+    echo '     <tr><td>';
+    echo '       <table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.$color[4].'">';
+    echo '        <tr><td><br />';
+    echo '            <table cellpadding="1" cellspacing="5" align="center" border="0">';
+    echo '              <tr>' . html_tag( 'td', $string."\n", 'left')
+                        . '</tr>';
+    echo '            </table>';
+    echo '        <br /></td></tr>';
+    echo '       </table></td></tr>';
+    echo '    </table>';
+}
 
 do_hook('right_main_bottom');
 sqimap_logout ($imapConnection);
 echo '</body></html>';
 
-sqsession_register($aLastSelectedMailbox,'aLastSelectedMailbox');
+/* add the mailbox to the cache */
+$mailbox_cache[$aMailbox['NAME']] = $aMailbox;
+sqsession_register($mailbox_cache,'mailbox_cache');
 
 ?>
index 78beb7317bb9d9e9a4858225b9c7723d04b2962c..75fd28a1704c64fa3ce0b119e6d0db339b9c9fdd 100644 (file)
@@ -349,8 +349,13 @@ function asearch_find_recent(&$recent_array, &$mailbox_array, &$biop_array, &$un
 function asearch_push_recent(&$mailbox_array, &$biop_array, &$unop_array, &$where_array, &$what_array, &$exclude_array, &$sub_array)
 {
     global $recent_prefkeys, $search_memory;
-
-    $criteria = array($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+    //global $what; // Hack to access issued search from read_body.php
+    $what = 1;
+    /**
+     * Update search history and store it in the session so we can retrieve the
+     * issued search when returning from an external page like read_body.php
+     */
+    $criteria[$what] = array($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
     sqsession_register($criteria, ASEARCH_CRITERIA);
     if ($search_memory > 0) {
         $recent_array = asearch_read_recent();
@@ -391,25 +396,26 @@ function asearch_edit_recent($index)
 }
 
 /** Get last search criteria from session or prefs
+* FIX ME, try to avoid globals
 */
-function asearch_edit_last()
-{
+function asearch_edit_last($index) {
     if (sqGetGlobalVar(ASEARCH_CRITERIA, $criteria, SQ_SESSION)) {
         global $where_array, $mailbox_array, $what_array, $unop_array;
         global $biop_array, $exclude_array, $sub_array;
-        $mailbox_array = $criteria[0];
-        $biop_array = $criteria[1];
-        $unop_array = $criteria[2];
-        $where_array = $criteria[3];
-        $what_array = $criteria[4];
-        $exclude_array = $criteria[5];
-        $sub_array = $criteria[6];
-        sqsession_unregister(ASEARCH_CRITERIA);
-    }
-    else {
+        $mailbox_array = $criteria[$index][0];
+        $biop_array = $criteria[$index][1];
+        $unop_array = $criteria[$index][2];
+        $where_array = $criteria[$index][3];
+        $what_array = $criteria[$index][4];
+        $exclude_array = $criteria[$index][5];
+        $sub_array = $criteria[$index][6];
+        unset($criteria[$index]);
+        //sqsession_unregister(ASEARCH_CRITERIA);
+    else {
         global $search_memory;
-        if ($search_memory > 0)
+        if ($search_memory > 0) {
             asearch_edit_recent(0);
+        }
     }
 }
 
@@ -685,10 +691,11 @@ function asearch_mailbox_exists($mailbox, &$boxes)
 */
 function asearch_get_form_mailbox($imapConnection, &$boxes, $mailbox, $row_num = 0)
 {
-    if (($mailbox != 'All Folders') && (!asearch_mailbox_exists($mailbox, $boxes)))
+    if (($mailbox != 'All Folders') && (!asearch_mailbox_exists($mailbox, $boxes))) {
         $missing = asearch_opt($mailbox, $mailbox, '[' . _("Missing") . '] ' . asearch_get_mailbox_display($mailbox));
-    else
+    } else {
         $missing = '';
+    }
     return '<select name="mailbox[' . $row_num . ']">'
         . $missing
         . asearch_opt('All Folders', $mailbox, '[' . asearch_get_mailbox_display('All Folders') . ']')
@@ -852,51 +859,38 @@ function asearch_print_form_basic($imapConnection, &$boxes, $mailbox_array, $bio
 
 /** Print the $msgs messages from $mailbox mailbox
 */
-function asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $id, $cnt, $sort, $color, $where, $what)
-{
-    /* initialize */
-    $aMailbox['NAME'] = $mailbox;
-    $aMailbox['EXISTS'] = $cnt;
-    $aMailbox['SORT'] = $sort;
-    $aMailbox['UIDVALIDITY'] = $mbxresponse['UIDVALIDITY'];
-    $aMailbox['UIDNEXT'] = $mbxresponse['UIDNEXT'];
-    $aMailbox['PERMANENTFLAGS'] = $mbxresponse['PERMANENTFLAGS'];
-    $aMailbox['RIGHTS'] = $mbxresponse['RIGHTS'];
-    $aMailbox['NAME'] = $mailbox;
-    $aMailbox['UIDSET'] = $id;
-    $aMailbox['OFFSET'] = 0;
-    $aMailbox['PAGEOFFSET'] = 0;
-    $aMailbox['LIMIT'] = $cnt;
-    $aMailbox['SEARCH'] = array($where,$what);
-    $aMailbox['SORT_METHOD'] = 'SEARCH';
-
-    if ($cnt > 0) {
-        global $allow_server_sort, $allow_thread_sort, $thread_sort_messages, $auto_expunge;
-        $aMailbox['ALLOW_THREAD'] = $allow_thread_sort;
-        $aMailbox['AUTO_EXPUNGE'] = $auto_expunge;
-        $msgs = sqimap_get_small_header_list ($imapConnection, $id, count($id));
-        $thread_sort_messages = 0;
-        if ($allow_thread_sort) {
-            global $data_dir, $username;
-            $thread_sort_messages = getPref($data_dir, $username, 'thread_' . $mailbox);
-        }
 
-        $mailbox_display = asearch_get_mailbox_display($mailbox);
+function asearch_print_mailbox_msgs($imapConnection, &$aMailbox, $color)
+{
+    if (fetchMessageHeaders($imapConnection, $aMailbox)) {
+        /**
+         * A mailbox can contain different sets with uid's. Default, for normal
+         * message list view we use '0' as setindex and for search a different
+         * setindex.
+         */
+        $iSetIndx = $aMailbox['SETINDEX'];
+
+        $mailbox_display = asearch_get_mailbox_display($aMailbox['NAME']);
         $mailbox_title = '<b><big>' . _("Folder:") . ' '. $mailbox_display . '&nbsp;</big></b>';
-        $devel = check_sm_version(1, 5, 0);
-        if (!$devel) {
-            echo html_tag('div', $mailbox_title, 'center') . "\n";
-            $mailbox_title = get_selectall_link(1, $real_sort);
-        }
-        $msg_cnt_str = get_msgcnt_str(1, $cnt, $cnt);
+
+        /**
+         * UIDSET contains the array with uid's returned by a search
+         */
+        $cnt = count($aMailbox['UIDSET'][$iSetIndx]);
+
+        $iLimit = ($aMailbox['SHOWALL'][$iSetIndx]) ? $cnt : $aMailbox['LIMIT'];
+        $iEnd = ($aMailbox['PAGEOFFSET'] + ($iLimit - 1) < $aMailbox['EXISTS']) ?
+                $aMailbox['PAGEOFFSET'] + $iLimit - 1 : $cnt;
+
+        $paginator_str = get_paginator_str($aMailbox['NAME'], $aMailbox['PAGEOFFSET'],
+                                        $cnt, $aMailbox['LIMIT'], $aMailbox['SHOWALL'][$iSetIndx]);
+
+        $msg_cnt_str = get_msgcnt_str($aMailbox['PAGEOFFSET'], $iEnd,$cnt);
 
         echo '<table border="0" width="100%" cellpadding="0" cellspacing="0">';
 
         echo '<tr><td>';
-        //if ($devel)
-            mail_message_listing_beginning($imapConnection, $aMailbox, $msg_cnt_str, $mailbox_title);
-        //else
-            /// mail_message_listing_beginning($imapConnection, $aMailbox $msg_cnt_str, $mailbox_title);
+        mail_message_listing_beginning($imapConnection, $aMailbox, $msg_cnt_str, $mailbox_title . " $paginator_str");
         echo '</td></tr>';
 
         echo '<tr><td HEIGHT="5" BGCOLOR="'.$color[4].'"></td></tr>';
@@ -908,14 +902,7 @@ function asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $id
         echo '       <table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="'.$color[5].'">';
         echo '        <tr><td>';
         printHeader($aMailbox);
-        $aMailbox['NAME'] = $mailbox;
-        $aMailbox['MSG_HEADERS'] = $msgs;
-        $aMailbox['UIDSET'] = $id;
-        $aMailbox['OFFSET'] = 0;
-        $aMailbox['PAGEOFFSET'] = 0;
-        $aMailbox['LIMIT'] = $cnt;
-        $aMailbox['SEARCH'] = array($where,$what);
-        displayMessageArray($imapConnection, $aMailbox);//$cnt, 1, $id, $msgs, $mailbox, $sort, $cnt, $where, $what);
+        displayMessageArray($imapConnection, $aMailbox);
         echo '        </td></tr>';
         echo '       </table>';
         echo '     </td></tr>';
@@ -924,6 +911,8 @@ function asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $id
         echo '</td></tr>';
 
         echo '</table>';
+    } else {
+        echo '<br />' . html_tag('div', asearch_get_error_display($color, _("No Messages Found")), 'center') . "\n";
     }
 }
 
@@ -953,6 +942,11 @@ if ( sqgetGlobalVar('checkall', $temp, SQ_GET) ) {
     $checkall = (int) $temp;
 }
 
+/**
+ * Retrieve the mailbox cache from the session.
+ */
+sqgetGlobalVar('mailbox_cache',$mailbox_cache,SQ_SESSION);
+
 
 $search_button_html = _("Search");
 $search_button_text = asearch_unhtmlentities($search_button_html);
@@ -981,18 +975,18 @@ $allow_advanced_search = asearch_nz($allow_advanced_search, 2);
 /**
 * Toggle advanced/basic search
 */
-if (sqgetGlobalVar('advanced', $search_advanced, SQ_GET))
+if (sqgetGlobalVar('advanced', $search_advanced, SQ_GET)) {
     setPref($data_dir, $username, 'search_advanced', $search_advanced & 1);
-
+}
 /** If 1, show advanced search interface
 * Default from allow_advanced_search pref
 * @global integer $search_advanced
 */
-if ($allow_advanced_search > 1)
+if ($allow_advanced_search > 1) {
     $search_advanced = getPref($data_dir, $username, 'search_advanced', 0);
-else
+} else {
     $search_advanced = $allow_advanced_search;
-
+}
 if ($search_advanced) {
 /** Set recent prefkeys according to $search_advanced
 * @global array $recent_prefkeys
@@ -1005,8 +999,7 @@ if ($search_advanced) {
     $saved_prefkeys = array('asearch_saved_where', 'asearch_saved_mailbox', 'asearch_saved_what', 'asearch_saved_unop', 'asearch_saved_biop', 'asearch_saved_exclude', 'asearch_saved_sub');
 
 /*$asearch_prefkeys = array('where', 'mailbox', 'what', 'biop', 'unop', 'exclude', 'sub');*/
-}
-else {
+} else {
     $recent_prefkeys = array('search_where', 'search_folder', 'search_what', 'search_unop');
     $saved_prefkeys = array('saved_where', 'saved_folder', 'saved_what', 'saved_unop');
 }
@@ -1028,19 +1021,38 @@ else {
 * - 'delete_saved'
 * @global string $submit
 */
-if (isset($_GET['submit']))
+if (isset($_GET['submit'])) {
     $submit = strip_tags($_GET['submit']);
-
+}
 /** Searched mailboxes
 * @global array $mailbox_array
 */
 if (isset($_GET['mailbox'])) {
     $mailbox_array = $_GET['mailbox'];
-    if (!is_array($mailbox_array))
+    $targetmailbox = $_GET['mailbox'];
+    if (!is_array($mailbox_array)) {
         $mailbox_array = array($mailbox_array);
-}
-else
+    }
+} else {
     $mailbox_array = array();
+}
+$aMailboxGlobalPref = array(
+                       MBX_PREF_SORT         => 0,
+                       MBX_PREF_LIMIT        => (int)  $show_num,
+                       MBX_PREF_AUTO_EXPUNGE => (bool) $auto_expunge,
+                       MBX_PREF_INTERNALDATE => (bool) getPref($data_dir, $username, 'internal_date_sort')
+                    // MBX_PREF_FUTURE       => (var)  $future
+                     );
+
+/**
+ * system wide admin settings and incoming vars.
+ */
+$aConfig = array(
+                'allow_thread_sort' => $allow_thread_sort,
+                'allow_server_sort' => $allow_server_sort,
+                'user'              => $username,
+                'max_cache_size'
+                );
 
 /** Binary operators
 * @global array $biop_array
@@ -1049,10 +1061,9 @@ if (isset($_GET['biop'])) {
     $biop_array = $_GET['biop'];
     if (!is_array($biop_array))
         $biop_array = array($biop_array);
-}
-else
+} else {
     $biop_array = array();
-
+}
 /** Unary operators
 * @global array $unop_array
 */
@@ -1060,79 +1071,99 @@ if (isset($_GET['unop'])) {
     $unop_array = $_GET['unop'];
     if (!is_array($unop_array))
         $unop_array = array($unop_array);
-}
-else
+} else {
     $unop_array = array();
-
+}
 /** Where to search
 * @global array $where_array
 */
 if (isset($_GET['where'])) {
     $where_array = $_GET['where'];
-    if (!is_array($where_array))
+    if (!is_array($where_array)) {
         $where_array = array($where_array);
-}
-else
+    }
+} else {
     $where_array = array();
-
+}
 /** What to search
 * @global array $what_array
 */
 if (isset($_GET['what'])) {
     $what_array = $_GET['what'];
-    if (!is_array($what_array))
+    if (!is_array($what_array)) {
         $what_array = array($what_array);
-}
-else
+    }
+} else {
     $what_array = array();
-
+}
 /** Whether to exclude this criteria from search
 * @global array $exclude_array
 */
-if (isset($_GET['exclude']))
+if (isset($_GET['exclude'])) {
     $exclude_array = $_GET['exclude'];
-else
+} else {
     $exclude_array = array();
-
+}
 /** Search within subfolders
 * @global array $sub_array
 */
-if (isset($_GET['sub']))
+if (isset($_GET['sub'])) {
     $sub_array = $_GET['sub'];
-else
+} else {
     $sub_array = array();
-
+}
 /** Row number used by recent and saved stuff
 */
-if (isset($_GET['rownum']))
+if (isset($_GET['rownum'])) {
     $submit_rownum = strip_tags($_GET['rownum']);
-
+}
 /** Change global sort
 */
-if (sqgetGlobalVar('newsort', $newsort, SQ_GET)) {
-    setPref($data_dir, $username, 'sort', $newsort);
-    $sort = $newsort;
-    sqsession_register($sort, 'sort');
-    asearch_edit_last();
+if (sqgetGlobalVar('srt', $temp, SQ_GET)) {
+    $srt = (int) $temp;
+    asearch_edit_last(1);
+    asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+}
+if (sqgetGlobalVar('startMessage', $temp, SQ_GET)) {
+    $startMessage = (int) $temp;
+    asearch_edit_last(1);
+    asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
 }
 
-/** Toggle mailbox threading
-*/
-if (sqgetGlobalVar('set_thread', $set_thread, SQ_GET)) {
-    setPref($data_dir, $username, 'thread_' . $mailbox_array[0], $set_thread & 1);
-    asearch_edit_last();
+if ( sqgetGlobalVar('showall', $temp, SQ_GET) ) {
+    $showall = (int) $temp;
+    asearch_edit_last(1);
+    asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
 }
+/**
+ * Incoming submit buttons from the message list with search results
+ */
+if (sqgetGlobalVar('moveButton',      $moveButton,      SQ_POST) ||
+    sqgetGlobalVar('expungeButton',   $expungeButton,   SQ_POST) ||
+    sqgetGlobalVar('delete',          $markDelete,      SQ_POST) ||
+    sqgetGlobalVar('undeleteButton',  $undeleteButton,  SQ_POST) ||
+    sqgetGlobalVar('markRead',        $markRead,        SQ_POST) ||
+    sqgetGlobalVar('markUnread',      $markUnread,      SQ_POST) ||
+    sqgetGlobalVar('markFlagged',     $markFlagged,     SQ_POST) ||
+    sqgetGlobalVar('markUnflagged',   $markUnflagged,   SQ_POST) ||
+    sqgetGlobalVar('attache',         $attache,         SQ_POST)) {
+    asearch_edit_last(1);
+    $submit = '';
+    asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+}
+
+
 
 /** Toggle show/hide saved searches
 */
-if (sqgetGlobalVar('search_show_saved', $search_show_saved, SQ_GET))
+if (sqgetGlobalVar('search_show_saved', $search_show_saved, SQ_GET)) {
     setPref($data_dir, $username, 'search_show_saved', $search_show_saved & 1);
-
+}
 /** Toggle show/hide recent searches
 */
-if (sqgetGlobalVar('search_show_recent', $search_show_recent, SQ_GET))
+if (sqgetGlobalVar('search_show_recent', $search_show_recent, SQ_GET)) {
     setPref($data_dir, $username, 'search_show_recent', $search_show_recent & 1);
-
+}
 // end of get globals
 
 /** If TRUE, do not show search interface
@@ -1145,72 +1176,82 @@ $search_silent = FALSE;
 if ((empty($submit)) && (!empty($where_array))) {
     /* This happens when the Enter key is used or called from outside */
     $submit = $search_button_text;
-    if (count($where_array) != count($unop_array))     /* Hack needed to handle coming back from read_body et als */
-        asearch_edit_last();
+    /* Hack needed to handle coming back from read_body et als */
+    if (count($where_array) != count($unop_array)) {
+        /**
+         * Hack to use already existen where and what vars.
+         * where now contains the initiator page of the messagelist
+         * and in this case 'search'. what contains an index to access
+         * the search history
+         */
+
+        sqgetGlobalVar('what',$what,SQ_GET);
+        asearch_edit_last($what);
+    }
 }
 
 if (!isset($submit)) {
     $submit = '';
-}
-else {
+} else {
     switch ($submit) {
-        case $search_button_text:
-            if (asearch_check_query($where_array, $what_array, $exclude_array) == '')
-                asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+      case $search_button_text:
+        if (asearch_check_query($where_array, $what_array, $exclude_array) == '') {
+            asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+        }
         break;
-        case 'Search_silent':
-            $search_silent = TRUE;
+      case 'Search_silent':
+        $search_silent = TRUE;
         /*nobreak;*/
-        case 'Search_no_update':
-            $submit = $search_button_text;
+      case 'Search_no_update':
+        $submit = $search_button_text;
         break;
-        case $del_excluded_button_text:
-            $delarray = array_keys($exclude_array);
-            while (!empty($delarray)) {
-                $delrow = array_pop($delarray);
-                array_splice($mailbox_array, $delrow, 1);
-                array_splice($biop_array, $delrow, 1);
-                array_splice($unop_array, $delrow, 1);
-                array_splice($where_array, $delrow, 1);
-                array_splice($what_array, $delrow, 1);
-/*                     array_splice($exclude_array, $delrow, 1);*/     /* There is still some php magic that eludes me */
-                array_splice($sub_array, $delrow, 1);
-            }
-            $exclude_array = array();
+      case $del_excluded_button_text:
+        $delarray = array_keys($exclude_array);
+        while (!empty($delarray)) {
+            $delrow = array_pop($delarray);
+            array_splice($mailbox_array, $delrow, 1);
+            array_splice($biop_array, $delrow, 1);
+            array_splice($unop_array, $delrow, 1);
+            array_splice($where_array, $delrow, 1);
+            array_splice($what_array, $delrow, 1);
+            /* array_splice($exclude_array, $delrow, 1);*/     /* There is still some php magic that eludes me */
+            array_splice($sub_array, $delrow, 1);
+        }
+        $exclude_array = array();
         break;
-        case $del_all_button_text:
-            $mailbox_array = array();
-            $biop_array = array();
-            $unop_array = array();
-            $where_array = array();
-            $what_array = array();
-            $exclude_array = array();
-            $sub_array = array();
+      case $del_all_button_text:
+        $mailbox_array = array();
+        $biop_array = array();
+        $unop_array = array();
+        $where_array = array();
+        $what_array = array();
+        $exclude_array = array();
+        $sub_array = array();
         break;
-        case 'save_recent':
-            asearch_save_recent($submit_rownum);
+      case 'save_recent':
+        asearch_save_recent($submit_rownum);
         break;
-        case 'search_recent':
-            $submit = $search_button_text;
-            asearch_edit_recent($submit_rownum);
-            asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+      case 'search_recent':
+        $submit = $search_button_text;
+        asearch_edit_recent($submit_rownum);
+        asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
         break;
-        case 'edit_recent':    /* no link to do this, yet */
-            asearch_edit_recent($submit_rownum);
+      case 'edit_recent':      /* no link to do this, yet */
+        asearch_edit_recent($submit_rownum);
         break;
-        case 'forget_recent':
-            asearch_forget_recent($submit_rownum);
+      case 'forget_recent':
+        asearch_forget_recent($submit_rownum);
         break;
-        case 'search_saved':
-            $submit = $search_button_text;
-            asearch_edit_saved($submit_rownum);
-            asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+      case 'search_saved':
+        $submit = $search_button_text;
+        asearch_edit_saved($submit_rownum);
+        asearch_push_recent($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
         break;
-        case 'edit_saved':
-            asearch_edit_saved($submit_rownum);
+      case 'edit_saved':
+        asearch_edit_saved($submit_rownum);
         break;
-        case 'delete_saved':
-            asearch_delete_saved($submit_rownum);
+      case 'delete_saved':
+        asearch_delete_saved($submit_rownum);
         break;
     }
 }
@@ -1271,8 +1312,7 @@ if ($search_advanced) {
         'ALL' => _("And"),
         'OR' => _("Or")
     );
-}
-else {
+} else {
     //Texts in basic form only
     $imap_asearch_options = array(
         'BCC' => _("Bcc"),
@@ -1289,6 +1329,8 @@ uasort($imap_asearch_options, 'asearch_unhtml_strcoll');
 
 /* open IMAP connection */
 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
+
+
 /* get mailboxes once here */
 $boxes = sqimap_mailbox_list($imapConnection);
 /* ensure we have a valid default mailbox name */
@@ -1300,10 +1342,9 @@ if (isset($composenew) && $composenew) {
     $comp_uri = "../src/compose.php?mailbox=" . urlencode($mailbox)
         . "&amp;session=$composesession&amp;attachedmessages=true&amp";
     displayPageHeader($color, $mailbox, "comp_in_new('$comp_uri');", false);
-}
-else
+} else {
     displayPageHeader($color, $mailbox);
-
+}
 do_hook('search_before_form');
 
 if (!$search_silent) {
@@ -1328,10 +1369,11 @@ if (!$search_silent) {
         $mailbox_array[0] = $mailbox;
         $biop_array[0] = '';
         $unop_array[0] = '';
-        if ($mailbox == $sent_folder)
+        if ($mailbox == $sent_folder) {
             $where_array[0] = 'TO';
-        else
+        } else {
             $where_array[0] = 'FROM';
+        }
         $what_array[0] = '';
         $exclude_array[0] = '';
         $sub_array[0] = '';
@@ -1349,20 +1391,11 @@ if (!$search_silent) {
             $sub_array[] = asearch_nz($sub_array[$last_index]);
         }
         asearch_print_form($imapConnection, $boxes, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
-    }
-    else
+    } else {
         asearch_print_form_basic($imapConnection, $boxes, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
+    }
 }
 
-/*********************************************************************
-* Check to see if we can use cache or not. Currently the only time  *
-* when you will not use it is when a link on the left hand frame is *
-* used. Also check to make sure we actually have the array in the   *
-* registered session data.  :)                                      *
-*********************************************************************/
-if (!isset($use_mailbox_cache))
-    $use_mailbox_cache = 0;
-
 do_hook('search_after_form');
 
 if ($submit == $search_button_text) {
@@ -1374,38 +1407,74 @@ if ($submit == $search_button_text) {
     flush();
 
     $query_error = asearch_check_query($where_array, $what_array, $exclude_array);
-    if ($query_error != '')
+    if ($query_error != '') {
         echo '<br />' . html_tag('div', asearch_get_error_display($color, $query_error), 'center') . "\n";
-    else {
-        // Disable thread sort for now if there is more than one mailbox or at least one 'All Folders'
-        global $allow_thread_sort;
-        $old_allow_thread_sort = $allow_thread_sort;
-        $allow_thread_sort = ((count(array_unique($mailbox_array)) <= 1) && (!in_array('All Folders', $mailbox_array)));
-
+    } else {
         $mboxes_array = sqimap_asearch_get_selectable_unformatted_mailboxes($boxes);
-        $mboxes_msgs = sqimap_asearch($imapConnection, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array, $mboxes_array);
-        if (empty($mboxes_msgs))
-            echo '<br />' . html_tag('div', asearch_get_error_display($color, _("No Messages Found")), 'center') . "\n";
-        else {
-            foreach($mboxes_msgs as $mailbox => $msgs) {
-                echo '<br />';
-                $mbxresponse = sqimap_mailbox_select($imapConnection, $mailbox);
-                //$msgs = sqimap_get_small_header_list ($imapConnection, $msgs, count($msgs));
-/* For now just keep the first criteria to make the regular search happy if the user tries to come back to search */
-/*                     $where = asearch_serialize($where_array);
-                $what = asearch_serialize($what_array);*/
-                $where = $where_array[0];
-                $what = $what_array[0];
-                asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $msgs, count($msgs), $sort, $color, urlencode($where), urlencode($what));
+        /**
+         * Retrieve the search queries
+         */
+        $mboxes_mailbox = sqimap_asearch($imapConnection, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array, $mboxes_array);
+        foreach($mboxes_mailbox as $mbx => $search) {
+            $aMailboxPrefSer=getPref($data_dir, $username, "pref_$mbx");
+
+            if ($aMailboxPrefSer) {
+                $aMailboxPref = unserialize($aMailboxPrefSer);
+            } else {
+                setUserPref($username,"pref_$mbx",serialize($aMailboxGlobalPref));
+                $aMailboxPref = $aMailboxGlobalPref;
             }
-        }
+            if (isset($srt) && $targetmailbox == $mbx) {
+                $aMailboxPref[MBX_PREF_SORT] = (int) $srt;
+            }
+            if (isset($startMessage) && $targetmailbox == $mbx) {
+                $aConfig['offset'] = $startMessage;
+            } else if (isset($aConfig['offset'])) {
+                unset($aConfig['offset']);
+            }
+            if (isset($showall) && $targetmailbox == $mbx) {
+                $aConfig['showall'] = $showall;
+            } else if (isset($aConfig['showall'])) {
+                unset($aConfig['showall']);
+            }
+            /**
+             * Set the max cache size to the number of mailboxes to avoid cache cleanups
+             * when searching all mailboxes
+             */
+            $aConfig['max_cache_size'] = count($mboxes_mailbox) +1;
+
+            /**
+            * until there is no per mailbox option screen to set prefs we override
+            * the mailboxprefs by the default ones
+            */
+            $aMailboxPref[MBX_PREF_LIMIT] = (int)  $show_num;
+            $aMailboxPref[MBX_PREF_AUTO_EXPUNGE] = (bool) $auto_expunge;
+            $aMailboxPref[MBX_PREF_INTERNALDATE] = (bool) getPref($data_dir, $username, 'internal_date_sort');
+
+            echo '<br />';
+            $aConfig['search'] = $search['search'];
+            $aConfig['charset'] = $search['charset'];
+            $aConfig['setindex'] = 1; // $what $where = 'search'
+
+            $aMailbox = sqm_api_mailbox_select($imapConnection,$mbx,$aConfig,$aMailboxPref);
+            /**
+            * Handle form actions like flag / unflag, seen / unseen, delete
+            */
+            if (sqgetGlobalVar('mailbox',$postMailbox,SQ_POST)) {
+                if ($postMailbox === $mbx) {
+                    handleMessageListForm($imapConnection,$aMailbox);
+                }
+            }
+            asearch_print_mailbox_msgs($imapConnection, $aMailbox, $color);
+            /* add the mailbox to the cache */
+            $mailbox_cache[$aMailbox['NAME']] = $aMailbox;
 
-        $allow_thread_sort = $old_allow_thread_sort;   // Restore thread sort
+        }
     }
 }
 
 do_hook('search_bottom');
 sqimap_logout($imapConnection);
 echo '</body></html>';
-
+sqsession_register($mailbox_cache,'mailbox_cache');
 ?>
\ No newline at end of file