+/**
+ * Run the imap SORT command as defined in
+ * @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
+ * @param resource $imapConnection the current imap stream
+ * @param string $search_string the full search expression as defined in rfc 3501
+ * @param string $search_charset mandatory charset
+ * @param string $sort_criteria the full sort criteria expression eg "SUBJECT REVERSE DATE"
+ * @return array an IDs or UIDs array of matching messages or an empty array
+ */
+function sqimap_run_sort($imapConnection, $search_string, $search_charset, $sort_criteria)
+{
+ if ($search_charset == '')
+ $search_charset = 'US-ASCII';
+ $query = 'SORT (' . $sort_criteria . ') "' . strtoupper($search_charset) . '" ALL ' . $search_string;
+ s_debug_dump('C:', $query);
+ $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
+ s_debug_dump('S:', $response);
+
+ /* 6.4 try US-ASCII charset if we received a tagged NO response (SHOULD be [BADCHARSET]) */
+ if (($search_charset != 'US-ASCII') && (strtoupper($response) == 'NO')) {
+ s_debug_dump('S:', $readin);
+ $query = 'SORT (' . $sort_criteria . ') US-ASCII ALL ' . $search_string;
+ s_debug_dump('C:', $query);
+ $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
+ s_debug_dump('S:', $response);
+ }
+
+ if (strtoupper($response) != 'OK') {
+ s_debug_dump('S:', $readin);
+// sqimap_asearch_error_box($response, $query, $message);
+// return array();
+ return sqimap_run_search($imapConnection, $search_string, $search_charset); // Fell back to standard search
+ }
+
+ /* Keep going till we find the * SORT response */
+ foreach ($readin as $readin_part) {
+ s_debug_dump('S:', $readin_part);
+ if (substr($readin_part, 0, 7) == '* SORT ') {
+ //SORT returns untagged responses
+ $messagelist = sqimap_array_merge_unique($messagelist, preg_split("/ /", substr($readin_part, 7)));
+ }
+ }
+
+ if (empty($messagelist)) //Empty search response, ie '* SORT'
+ return array();
+
+ $cnt = count($messagelist);
+ for ($q = 0; $q < $cnt; $q++)
+ $id[$q] = trim($messagelist[$q]);
+ return $id;
+}
+
+/**
+ * Run the imap THREAD command as defined in
+ * @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt
+ * @param resource $imapConnection the current imap stream
+ * @param string $search_string the full search expression as defined in rfc 3501
+ * @param string $search_charset mandatory charset
+ * @param string $thread_algorithm the threading algorithm "ORDEREDSUBJECT" or "REFERENCES"
+ * @return array an IDs or UIDs array of matching messages or an empty array
+ * @global array thread_new will be used by thread view in mailbox_display
+ * @global array server_sort_array will be used by thread view in mailbox_display
+ */
+function sqimap_run_thread($imapConnection, $search_string, $search_charset, $thread_algorithm)
+{
+ global $thread_new, $server_sort_array;
+
+ if (sqsession_is_registered('thread_new'))
+ sqsession_unregister('thread_new');
+ if (sqsession_is_registered('server_sort_array'))
+ sqsession_unregister('server_sort_array');
+
+ $thread_new = array();
+ $thread_new[0] = "";
+
+ $server_sort_array = array();
+
+ if ($search_charset == '')
+ $search_charset = 'US-ASCII';
+ $query = 'THREAD ' . $thread_algorithm . ' "' . strtoupper($search_charset) . '" ALL ' . $search_string;
+ s_debug_dump('C:', $query);
+ $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
+ s_debug_dump('S:', $response);
+
+ /* 6.4 try US-ASCII charset if we received a tagged NO response (SHOULD be [BADCHARSET]) */
+ if (($search_charset != 'US-ASCII') && (strtoupper($response) == 'NO')) {
+ s_debug_dump('S:', $readin);
+ $query = 'THREAD ' . $thread_algorithm . ' US-ASCII ALL ' . $search_string;
+ s_debug_dump('C:', $query);
+ $readin = sqimap_run_command($imapConnection, $query, false, $response, $message, TRUE);
+ s_debug_dump('S:', $response);
+ }
+
+ if (strtoupper($response) != 'OK') {
+ s_debug_dump('S:', $readin);
+ if (empty($response)) { //imap server closed connection. We can't go further.
+/* we should at this point:
+ - warn the user that the THREAD call has failed
+ - (offer him a way to) disconnect it permanently in the prefs
+ - perform the regular search instead or provide a way to do it in one click
+*/
+ global $sort, $mailbox, $php_self;
+ $message = _("The imap server failed to handle threading.");
+ $unthread = _("Click here to unset thread view for this mailbox and start again.");
+ if (preg_match('/^(.+)\?.+$/', $php_self, $regs))
+ $source_url = $regs[1];
+ else
+ $source_url = $php_self;
+ $link = '<a href=' . $source_url . '?sort=' . $sort . '&start_messages=1&set_thread=0&mailbox=' . urlencode($mailbox) . '>' . $unthread . '</a>';
+ sqimap_asearch_error_box($response, $query, $message, $link);
+ return array();
+ }
+ return sqimap_run_search($imapConnection, $search_string, $search_charset); // Fell back to standard search
+ }
+
+ /* Keep going till we find the * THREAD response */
+ foreach ($readin as $readin_part) {
+ s_debug_dump('S:', $readin_part);
+ if (substr($readin_part, 0, 9) == '* THREAD ') {
+ $thread_temp = preg_split("//", substr($readin_part, 9), -1, PREG_SPLIT_NO_EMPTY);
+ break; // Should be the last anyway
+ }
+ }
+
+ if (empty($thread_temp)) //Empty search response, ie '* THREAD'
+ return array();
+
+ $char_count = count($thread_temp);
+ $counter = 0;
+ $k = 0;
+ for ($i=0;$i<$char_count;$i++) {
+ if ($thread_temp[$i] != ')' && $thread_temp[$i] != '(') {
+ $thread_new[$k] = $thread_new[$k] . $thread_temp[$i];
+ }
+ elseif ($thread_temp[$i] == '(') {
+ $thread_new[$k] .= $thread_temp[$i];
+ $counter++;
+ }
+ elseif ($thread_temp[$i] == ')') {
+ if ($counter > 1) {
+ $thread_new[$k] .= $thread_temp[$i];
+ $counter = $counter - 1;
+ }
+ else {
+ $thread_new[$k] .= $thread_temp[$i];
+ $k++;
+ $thread_new[$k] = "";
+ $counter = $counter - 1;
+ }
+ }
+ }
+ sqsession_register($thread_new, 'thread_new');
+ $thread_new = array_reverse($thread_new);
+ $thread_list = implode(" ", $thread_new);
+ $thread_list = str_replace("(", " ", $thread_list);
+ $thread_list = str_replace(")", " ", $thread_list);
+ $thread_list = preg_split("/\s/", $thread_list, -1, PREG_SPLIT_NO_EMPTY);
+ $server_sort_array = $thread_list;
+ sqsession_register($server_sort_array, 'server_sort_array');
+ return $thread_list;
+}
+
+/**
+ * @global bool allow_charset_search user setting
+ * @global array languages sm languages array
+ * @global string squirrelmail_language user language setting
+ * @return string the user defined charset if $allow_charset_search is TRUE else zls ('')
+ */