From 324ac3c54f72cb39a994d9a80a586fce591fca84 Mon Sep 17 00:00:00 2001 From: stekkel Date: Mon, 31 May 2004 20:07:44 +0000 Subject: [PATCH] Rewrite of internal message caching 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 --- functions/file_prefs.php | 32 +- functions/forms.php | 2 +- functions/imap_asearch.php | 264 ++------ functions/imap_mailbox.php | 38 -- functions/imap_messages.php | 141 ++-- functions/mailbox_display.php | 1168 ++++++++++++++++++++++++--------- functions/rfc822address.php | 16 +- include/load_prefs.php | 14 +- src/download.php | 26 +- src/left_main.php | 22 +- src/move_messages.php | 133 +++- src/read_body.php | 199 +++--- src/right_main.php | 249 ++++--- src/search.php | 477 ++++++++------ 14 files changed, 1667 insertions(+), 1114 deletions(-) diff --git a/functions/file_prefs.php b/functions/file_prefs.php index 224e9890..d8a5cc97 100644 --- a/functions/file_prefs.php +++ b/functions/file_prefs.php @@ -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); } diff --git a/functions/forms.php b/functions/forms.php index 97fb746f..6acf361d 100644 --- a/functions/forms.php +++ b/functions/forms.php @@ -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"' : '')); } diff --git a/functions/imap_asearch.php b/functions/imap_asearch.php index 0c2c21c6..667e9614 100644 --- a/functions/imap_asearch.php +++ b/functions/imap_asearch.php @@ -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 = '' . $unthread . ''; - 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); } ?> diff --git a/functions/imap_mailbox.php b/functions/imap_mailbox.php index e2198947..e85f6fde 100755 --- a/functions/imap_mailbox.php +++ b/functions/imap_mailbox.php @@ -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 */ diff --git a/functions/imap_messages.php b/functions/imap_messages.php index 2edf381c..f8cc0792 100755 --- a/functions/imap_messages.php +++ b/functions/imap_messages.php @@ -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(); diff --git a/functions/mailbox_display.php b/functions/mailbox_display.php index b256a43e..165c6d63 100644 --- a/functions/mailbox_display.php +++ b/functions/mailbox_display.php @@ -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("    ",$iIndent); } $td_str .= ' 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 = '
' . _("Thread sorting is not supported by your IMAP server.") . '
' . _("Please report this to the system administrator."). '
'; + $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 = '
' . _( "Server-side sorting is not supported by your IMAP server.") . '
' . _("Please report this to the system administrator."). '
'; + } 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 = '' . _("THIS FOLDER IS EMPTY") . ''; - echo ' '; - echo ' '; - echo '
'; - echo ' '; - echo ' '; - echo '

'; - echo ' '; - echo ' ' . html_tag( 'td', $string."\n", 'left') - . ''; - echo '
'; - echo '
'; - 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) { $indent, 'LAST' => $bLast ); - printMessageInfo($aMsg); + printMessageInfo($aMsg); ++$t; } else { break; @@ -776,15 +1137,11 @@ function mail_message_listing_beginning ($imapConnection, $msg_cnt_str = '', $paginator = ' ' ) { - 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&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 = '[
' . $thread_name . ']'; } 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 '
' ."\n" + echo '' ."\n" . $moveFields; + + ?> @@ -885,8 +1237,9 @@ function mail_message_listing_beginning ($imapConnection, if (in_array('\\deleted',$aMailbox['PERMANENTFLAGS'], true)) { echo '
'; - //echo $thread_link_str; //previous behaviour - getMbxList($imapConnection); + echo '   '; echo getButton('SUBMIT', 'moveButton',_("Move")) . "\n "; } @@ -1051,7 +1404,7 @@ function ShowSortButton($aMailbox, $Down, $Up ) { } /* Now that we have everything figured out, show the actual button. */ - echo ' sort$text"; 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 = ' '; /* 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) . '
'; - */ + /* + * 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) . '
'; + */ - /* 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 = "" ._("Paginate") . ''; } @@ -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 = "" . _("Show All") . ''; + $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 '   '; -} /** * 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; +} + ?> diff --git a/functions/rfc822address.php b/functions/rfc822address.php index c57af132..86b141ff 100644 --- a/functions/rfc822address.php +++ b/functions/rfc822address.php @@ -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); diff --git a/include/load_prefs.php b/include/load_prefs.php index 618c64fa..1f91c82e 100644 --- a/include/load_prefs.php +++ b/include/load_prefs.php @@ -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'); diff --git a/src/download.php b/src/download.php index bdd2a23c..fa966ed4 100644 --- a/src/download.php +++ b/src/download.php @@ -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'); ?> diff --git a/src/left_main.php b/src/left_main.php index 39c3b9d8..2863f557 100644 --- a/src/left_main.php +++ b/src/left_main.php @@ -68,7 +68,7 @@ function formatMailboxName($imapConnection, $box_array) { /* Create the link for this folder. */ if ($status !== false) { - $line .= ''; } 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 .= ''; } - $pre .= ""; + $pre .= ""; if ($unseen > 0) { $end .= ''; } @@ -389,7 +389,7 @@ function ListBoxes ($boxes, $j=0 ) { if ($unseen > 0) { $pre .= ''; } - $pre .= ""; + $pre .= ""; if ($unseen > 0) { $end .= ''; } @@ -406,7 +406,7 @@ function ListBoxes ($boxes, $j=0 ) { if ($unseen > 0) { $pre .= ''; } - $pre .= ""; + $pre .= ""; if ($unseen > 0) { $end .= ''; } @@ -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 .= ''; @@ -519,7 +519,7 @@ function ListAdvancedBoxes ($boxes, $mbx, $j='ID.0000' ) { if (! isset($numMessages)) { $numMessages = $boxes->total; } - $pre = "" . $pre; + $pre = "" . $pre; $end .= ''; 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 = "" . $pre; + $pre = "" . $pre; $end .= ''; } } @@ -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 ''; echo ''."\n"; } else { - //sqimap_get_status_mbx_tree($imap_stream,$boxes) + //sqimap_get_status_mbx_tree($imap_stream,$boxes) ListBoxes($boxes); } } /* if ($oldway) else ... */ diff --git a/src/move_messages.php b/src/move_messages.php index b3d757df..d142747d 100644 --- a/src/move_messages.php +++ b/src/move_messages.php @@ -1,5 +1,5 @@ $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."); + } + } +} ?> diff --git a/src/read_body.php b/src/read_body.php index 7e12373e..43805d15 100644 --- a/src/read_body.php +++ b/src/read_body.php @@ -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 . '['._("View Message").']'; // 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. '&mailbox='.$urlMailbox.'&sort='.$sort. + "&where=$where&what=$what" . '&startMessage='.$startMessage.'&show_more=0'; $prev_link = ''.$prev_link.''; } @@ -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. '&mailbox='.$urlMailbox.'&sort='.$sort. + "&where=$where&what=$what" . '&startMessage='.$startMessage.'&show_more=0'; $next_link = ''.$next_link.''; } @@ -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. '&mailbox='.$urlMailbox.'&sort='.$sort. '&startMessage='.$startMessage.'&show_more=0'. + "&where=$where&what=$what" . '&delete_id='.$passed_id; $del_prev_link = ''.$del_prev_link.''; } @@ -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. '&mailbox='.$urlMailbox.'&sort='.$sort. '&startMessage='.$startMessage.'&show_more=0'. + "&where=$where&what=$what" . '&delete_id='.$passed_id; $del_next_link = ''.$del_next_link.''; } @@ -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) . - '&what=' . urlencode($what) . '&mailbox=' . $urlMailbox; + $msgs_url .= "$where?where=read_body.php&what=$what&mailbox=" . $urlMailbox. + "&startMessage=$startMessage"; + if ($where == 'search.php') { $msgs_str = _("Search Results"); } else { - $msgs_url .= 'right_main.php?sort=' . $sort . '&startMessage=' . - $startMessage . '&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 .= ' '; - 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 .= '
'; 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 .= '' . _("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 .= '
'; } @@ -659,25 +660,13 @@ function formatMenubar($aMailbox, $passed_id, $passed_ent_id, $message, $mbx_res // Add top move link $menu_row .= '
'; 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 .= '
'. + $menu_row .= ''. ''. - 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:") . ''; echo ' '; @@ -924,6 +911,8 @@ function asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $id echo ''; echo '
'; @@ -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'); ?> diff --git a/src/right_main.php b/src/right_main.php index c8ec8ab5..ac40bf2a 100644 --- a/src/right_main.php +++ b/src/right_main.php @@ -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&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 = '' . _("THIS FOLDER IS EMPTY") . ''; + echo ' '; + echo ' '; + echo '
'; + echo ' '; + echo ' '; + echo '

'; + echo ' '; + echo ' ' . html_tag( 'td', $string."\n", 'left') + . ''; + echo '
'; + echo '
'; +} do_hook('right_main_bottom'); sqimap_logout ($imapConnection); echo ''; -sqsession_register($aLastSelectedMailbox,'aLastSelectedMailbox'); +/* add the mailbox to the cache */ +$mailbox_cache[$aMailbox['NAME']] = $aMailbox; +sqsession_register($mailbox_cache,'mailbox_cache'); ?> diff --git a/src/search.php b/src/search.php index 78beb731..75fd28a1 100644 --- a/src/search.php +++ b/src/search.php @@ -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 ''; echo ''; echo ''; @@ -908,14 +902,7 @@ function asearch_print_mailbox_msgs($imapConnection, $mbxresponse, $mailbox, $id echo '
'; - //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 '
'; echo ' '; echo '
'; 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 '
'; echo '
'; + } else { + echo '
' . 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) . "&session=$composesession&attachedmessages=true&"; 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 '
' . 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 '
' . html_tag('div', asearch_get_error_display($color, _("No Messages Found")), 'center') . "\n"; - else { - foreach($mboxes_msgs as $mailbox => $msgs) { - echo '
'; - $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 '
'; + $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 ''; - +sqsession_register($mailbox_cache,'mailbox_cache'); ?> \ No newline at end of file -- 2.25.1