X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fimap_messages.php;h=d99bcebd7aa22e34f8e8331181b7713d30142fb2;hb=9a09a81dc665789aa03072d834f4febbff10cd46;hp=b4c62084f841376c4528462398419c5cd9f601f5;hpb=628dba17ca643fd316ab6f1a1800ce8cc300f3fd;p=squirrelmail.git diff --git a/functions/imap_messages.php b/functions/imap_messages.php index b4c62084..d99bcebd 100755 --- a/functions/imap_messages.php +++ b/functions/imap_messages.php @@ -6,7 +6,7 @@ * This implements functions that manipulate messages * NOTE: Quite a few functions in this file are obsolete * - * @copyright © 1999-2005 The SquirrelMail Project Team + * @copyright © 1999-2006 The SquirrelMail Project Team * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @version $Id$ * @package squirrelmail @@ -39,9 +39,14 @@ function sqimap_msgs_list_copy($imap_stream, $id, $mailbox, $handle_errors = tru * @param string $id The list of messages to move * @param string $mailbox The destination to move to * @param bool $handle_errors Show error messages in case of a NO, BAD or BYE response + * @param string $source_mailbox (since 1.5.1) name of source mailbox. It is used to + * validate that target mailbox != source mailbox. * @return bool If the move completed without errors */ -function sqimap_msgs_list_move($imap_stream, $id, $mailbox, $handle_errors = true) { +function sqimap_msgs_list_move($imap_stream, $id, $mailbox, $handle_errors = true, $source_mailbox = false) { + if ($source_mailbox!==false && $source_mailbox==$mailbox) { + return false; + } $msgs_id = sqimap_message_list_squisher($id); if (sqimap_msgs_list_copy ($imap_stream, $id, $mailbox, $handle_errors)) { return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true); @@ -64,16 +69,15 @@ function sqimap_msgs_list_delete($imap_stream, $mailbox, $id, $bypass_trash=fals // 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; - $bRes = true; if (($move_to_trash == true) && ($bypass_trash != true) && (sqimap_mailbox_exists($imap_stream, $trash_folder) && ($mailbox != $trash_folder)) ) { - $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; + /** + * turn off internal error handling (fourth argument = false) and + * ignore copy to trash errors (allows to delete messages when overquota) + */ + sqimap_msgs_list_copy ($imap_stream, $id, $trash_folder, false); } + return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true); } @@ -114,29 +118,34 @@ function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) { /** * Sort the message list and crunch to be as small as possible * (overflow could happen, so make it small if possible) + * @param array $aUid array with uid's + * @return string $s message set string */ -function sqimap_message_list_squisher($messages_array) { - if( !is_array( $messages_array ) ) { - return $messages_array; - } - - sort($messages_array, SORT_NUMERIC); - $msgs_str = ''; - while ($messages_array) { - $start = array_shift($messages_array); - $end = $start; - while (isset($messages_array[0]) && $messages_array[0] == $end + 1) { - $end = array_shift($messages_array); - } - if ($msgs_str != '') { - $msgs_str .= ','; - } - $msgs_str .= $start; - if ($start != $end) { - $msgs_str .= ':' . $end; +function sqimap_message_list_squisher($aUid) { + if( !is_array( $aUid ) ) { + return $aUid; + } + sort($aUid, SORT_NUMERIC); + + if (count($aUid)) { + $s = ''; + for ($i=0,$iCnt=count($aUid);$i<$iCnt;++$i) { + $iStart = $aUid[$i]; + $iEnd = $iStart; + while ($i<($iCnt-1) && $aUid[$i+1] == $iEnd +1) { + $iEnd = $aUid[$i+1]; + ++$i; + } + if ($s) { + $s .= ','; + } + $s .= $iStart; + if ($iStart != $iEnd) { + $s .= ':' . $iEnd; + } } } - return $msgs_str; + return $s; } @@ -157,11 +166,20 @@ function sqimap_get_sort_order($imap_stream, $sSortField, $reverse, $search='ALL } $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); + // use sqimap_run_command_list in case of unsollicited responses. If we don't we could loose the SORT response + $aData = sqimap_run_command_list ($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 ($response == 'NO') { + if (strpos($message,'BADCHARSET') !== false || + strpos($message,'character') !== false) { + sqm_trigger_imap_error('SQM_IMAP_BADCHARSET',$query, $response, $message); + $query = "SORT ($sSortField) US-ASCII $search"; + $aData = sqimap_run_command_list ($imap_stream, $query, true, $response, $message, TRUE); + } else { + sqm_trigger_imap_error('SQM_IMAP_ERROR',$query, $response, $message); + } + } else if ($response == 'BAD') { + sqm_trigger_imap_error('SQM_IMAP_NO_SORT',$query, $response, $message); } } @@ -175,7 +193,7 @@ function sqimap_get_sort_order($imap_stream, $sSortField, $reverse, $search='ALL /** * Parses a UID list returned on a SORT or SEARCH request - * @param array $aData imap response + * @param array $aData imap response (retrieved from sqimap_run_command_list) * @param string $sCommand issued imap command (SEARCH or SORT) * @return array $aUid uid list */ @@ -183,8 +201,10 @@ 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])); + for ($j=0,$jCnt=count($aData[$i]);$j<$jCnt;++$j) { + if (preg_match("/^\* $sCommand (.+)$/", $aData[$i][$j], $aMatch)) { + $aUid += preg_split("/ /", trim($aMatch[1])); + } } } } @@ -281,137 +301,17 @@ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = return $aUid; } - -/** - * Returns an indent array for printMessageinfo() - * This represents the amount of indent needed (value), - * for this message number (key) - */ - -/* - * Notes for future work: - * indent_array should contain: indent_level, parent and flags, - * sibling notes .. - * To achieve that we need to define the following flags: - * 0: hasnochildren - * 1: haschildren - * 2: is first - * 4: is last - * a node has sibling nodes if it's not the last node - * a node has no sibling nodes if it's the last node - * By using binary comparations we can store the flag in one var - * - * example: - * -1 par = 0, level = 0, flag = 1 + 2 + 4 = 7 (haschildren, isfirst, islast) - * \-2 par = 1, level = 1, flag = 0 + 2 = 2 (hasnochildren, isfirst) - * |-3 par = 1, level = 1, flag = 1 + 4 = 5 (haschildren, islast) - * \-4 par = 3, level = 2, flag = 1 + 2 + 4 = 7 (haschildren, isfirst, islast) - * \-5 par = 4, level = 3, flag = 0 + 2 + 4 = 6 (hasnochildren, isfirst, islast) - */ -function get_parent_level($thread_new) { - $parent = ''; - $child = ''; - $cutoff = 0; - - /* - * loop through the threads and take unwanted characters out - * of the thread string then chop it up - */ - for ($i=0;$i (540) - * [1] => (1386) - * [2] => (1599 759 959 37) - * [3] => (492 1787) - * [4] => ((933)(1891)) - * [5] => (1030 (1497)(845)(1637)) + * -- 3 + * \-- 6 + * |-- 4 + * | \-- 23 + * | + * \-- 44 + * \-- 7 + * \-- 96 */ - for ($i=0,$iCnt=count($thread_temp);$i<$iCnt;$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; +/* + * Notes for future work: + * indent_array should contain: indent_level, parent and flags, + * sibling nodes .. + * To achieve that we need to define the following flags: + * 0: hasnochildren + * 1: haschildren + * 2: is first + * 4: is last + * a node has sibling nodes if it's not the last node + * a node has no sibling nodes if it's the last node + * By using binary comparations we can store the flag in one var + * + * example: + * -1 par = 0, level = 0, flag = 1 + 2 + 4 = 7 (haschildren, isfirst, islast) + * \-2 par = 1, level = 1, flag = 0 + 2 = 2 (hasnochildren, isfirst) + * |-3 par = 1, level = 1, flag = 1 + 4 = 5 (haschildren, islast) + * \-4 par = 3, level = 2, flag = 1 + 2 + 4 = 7 (haschildren, isfirst, islast) + * \-5 par = 4, level = 3, flag = 0 + 2 + 4 = 6 (hasnochildren, isfirst, islast) + */ + + $j = 0; + $k = 0; + $l = 0; + $aUidThread = array(); + $aIndent = array(); + $aUidSubThread = array(); + $aDepthStack = array(); + $sUid = ''; + + if ($sThreadResponse) { + for ($i=0,$iCnt = strlen($sThreadResponse);$i<$iCnt;++$i) { + $cChar = $sThreadResponse{$i}; + switch ($cChar) { + case '(': // new sub thread + // correction for a subthread of a thread with no parents in thread + if (!count($aUidSubThread) && $j > 0) { + --$l; + } + $aDepthStack[$j] = $l; + ++$j; + break; + case ')': // close sub thread + if($sUid !== '') { + $aUidSubThread[] = $sUid; + $aIndent[$sUid] = $j + $l - 1; + ++$l; + $sUid = ''; + } + --$j; + if ($j === 0) { + // show message that starts the thread first. + $aUidSubThread = array_reverse($aUidSubThread); + // do not use array_merge because it's extremely slow and is causing timeouts + foreach ($aUidSubThread as $iUid) { + $aUidThread[] = $iUid; + } + $aUidSubThread = array(); + $l = 0; + $aDepthStack = array(); + } else { + $l = $aDepthStack[$j]; + } + break; + case ' ': // new child + if ($sUid !== '') { + $aUidSubThread[] = $sUid; + $aIndent[$sUid] = $j + $l - 1; + ++$l; + $sUid = ''; + } + break; + default: // part of UID + $sUid .= $cChar; + break; } } } - - $thread_new = array_reverse($thread_new); - /* place the threads after each other in one string */ - $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; - - $indent_array = get_parent_level ($thread_new); - return array($thread_list,$indent_array); + unset($sThreadResponse); + // show newest threads first + $aUidThread = array_reverse($aUidThread); + return array($aUidThread,$aIndent); } @@ -669,7 +628,7 @@ function sqimap_get_small_header_list($imap_stream, $msg_list, * @return array $aMessageList associative array with messages. Key is the UID, value is an associative array * @author Marc Groot Koerkamp */ -function parseFetch($aResponse,$aMessageList = array()) { +function parseFetch(&$aResponse,$aMessageList = array()) { for ($j=0,$iCnt=count($aResponse);$j<$iCnt;++$j) { $aMsg = array(); @@ -822,6 +781,7 @@ function parseFetch($aResponse,$aMessageList = array()) { $msgi = ''; } $aMessageList[$msgi] = $aMsg; + $aResponse[$j] = NULL; } return $aMessageList; } @@ -962,7 +922,7 @@ function sqimap_get_message($imap_stream, $id, $mailbox) { if ($read) { if (preg_match('/.+FLAGS\s\((.*)\)\s/AUi',$read[0],$regs)) { if (trim($regs[1])) { - $flags = preg_split('/ /', $regs[1],-1,'PREG_SPLIT_NI_EMPTY'); + $flags = preg_split('/ /', $regs[1],-1,PREG_SPLIT_NO_EMPTY); } } } else { @@ -983,5 +943,3 @@ function sqimap_get_message($imap_stream, $id, $mailbox) { $msg->rfc822_header = $rfc822_header; return $msg; } - -?>