X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fimap_messages.php;h=c10439c834a59643f59bc13a1d7006f4a663a03e;hb=aa84daced451fe171b6b606939dba8df6bcab26c;hp=7e63ddc85462e4fd088a613c1c2ca3e4e8fb2c4e;hpb=f6382d6b141b4d79fd98661aea6aafb1b10f2850;p=squirrelmail.git diff --git a/functions/imap_messages.php b/functions/imap_messages.php index 7e63ddc8..c10439c8 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-2007 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); } @@ -90,17 +94,15 @@ function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) { $msgs_id = sqimap_message_list_squisher($id); $set_string = ($set ? '+' : '-'); - // mpl-spirit for ($i=0; $i (540) - * [1] => (1386) - * [2] => (1599 759 959 37) - * [3] => (492 1787) - * [4] => ((933)(1891)) - * [5] => (1030 (1497)(845)(1637)) - */ - 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; + $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); } @@ -498,33 +454,6 @@ function elapsedTime($start) { return $timepassed; } - -/** - * Normalise the different Priority headers into a uniform value, - * namely that of the X-Priority header (1, 3, 5). Supports: - * Prioirty, X-Priority, Importance. - * X-MS-Mail-Priority is not parsed because it always coincides - * with one of the other headers. - * - * FIXME: DUPLICATE CODE ALERT: - * NOTE: this is actually a duplicate from the function in - * class/mime/Rfc822Header.php. - * @todo obsolate function or use it instead of code block in parseFetch() - */ -function parsePriority($sValue) { - $aValue = split('/\w/',trim($sValue)); - $value = strtolower(array_shift($aValue)); - if ( is_numeric($value) ) { - return $value; - } - if ( $value == 'urgent' || $value == 'high' ) { - return 1; - } elseif ( $value == 'non-urgent' || $value == 'low' ) { - return 5; - } - return 3; -} - /** * Parses a string in an imap response. String starts with " or { which means it * can handle double quoted strings and literal strings @@ -671,7 +600,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(); @@ -773,8 +702,9 @@ function parseFetch($aResponse,$aMessageList = array()) { case 'x-priority': $aMsg['x-priority'] = ($value) ? (int) $value{0} : 3; break; case 'priority': case 'importance': + // duplicate code with Rfc822Header.cls:parsePriority() if (!isset($aMsg['x-priority'])) { - $aPrio = split('/\w/',trim($value)); + $aPrio = preg_split('/\s/',trim($value)); $sPrio = strtolower(array_shift($aPrio)); if (is_numeric($sPrio)) { $iPrio = (int) $sPrio; @@ -817,9 +747,14 @@ function parseFetch($aResponse,$aMessageList = array()) { break; } } - $msgi ="$unique_id"; - $aMsg['UID'] = $unique_id; - $aMessageList[$msgi] = $aMsg; + if (!empty($unique_id)) { + $msgi = "$unique_id"; + $aMsg['UID'] = $unique_id; + } else { + $msgi = ''; + } + $aMessageList[$msgi] = $aMsg; + $aResponse[$j] = NULL; } return $aMessageList; } @@ -950,9 +885,10 @@ function sqimap_parse_address($read, &$i) { * @param resource $imap_stream imap connection * @param integer $id uid of the message * @param string $mailbox used for error handling, can be removed because we should return an error code and generate the message elsewhere - * @return Message Message object + * @param int $hide Indicates whether or not to hide any errors: 0 = don't hide, 1 = hide (just exit), 2 = hide (return FALSE), 3 = hide (return error string) (OPTIONAL; default don't hide) + * @return mixed Message object or FALSE/error string if error occurred and $hide is set to 2/3 */ -function sqimap_get_message($imap_stream, $id, $mailbox) { +function sqimap_get_message($imap_stream, $id, $mailbox, $hide=0) { // typecast to int to prohibit 1:* msgs sets $id = (int) $id; $flags = array(); @@ -960,17 +896,25 @@ 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 { + + if ($hide == 1) exit; + if ($hide == 2) return FALSE; + /* the message was not found, maybe the mailbox was modified? */ - global $sort, $startMessage, $color; + global $sort, $startMessage; + + $errmessage = _("The server couldn't find the message you requested."); + + if ($hide == 3) return $errmessage; + + $errmessage .= '

'._("Most probably your message list was out of date and the message has been moved away or deleted (perhaps by another program accessing the same mailbox)."); - $errmessage = _("The server couldn't find the message you requested.") . - '

'._("Most probably your message list was out of date and the message has been moved away or deleted (perhaps by another program accessing the same mailbox)."); /* this will include a link back to the message list */ - error_message($errmessage, $mailbox, $sort, (int) $startMessage, $color); + error_message($errmessage, $mailbox, $sort, (int) $startMessage); exit; } $bodystructure = implode('',$read); @@ -979,7 +923,40 @@ function sqimap_get_message($imap_stream, $id, $mailbox) { $rfc822_header = new Rfc822Header(); $rfc822_header->parseHeader($read); $msg->rfc822_header = $rfc822_header; + + parse_message_entities($msg, $id, $imap_stream); return $msg; -} + } + -?> \ No newline at end of file +/** + * Recursively parse embedded messages (if any) in the given + * message, building correct rfc822 headers for each one + * + * @param object $msg The message object to scan for attached messages + * NOTE: this is passed by reference! Changes made + * within will affect the caller's copy of $msg! + * @param int $id The top-level message UID on the IMAP server, even + * if the $msg being passed in is only an attached entity + * thereof. + * @param resource $imap_stream A live connection to the IMAP server. + * + * @return void + * + * @since 1.5.2 + * + */ +function parse_message_entities(&$msg, $id, $imap_stream) { + global $uid_support; + if (!empty($msg->entities)) foreach ($msg->entities as $i => $entity) { + if (is_object($entity) && get_class($entity) == 'Message') { + if (!empty($entity->rfc822_header)) { + $read = sqimap_run_command($imap_stream, "FETCH $id BODY[". $entity->entity_id .".HEADER]", true, $response, $message, $uid_support); + $rfc822_header = new Rfc822Header(); + $rfc822_header->parseHeader($read); + $msg->entities[$i]->rfc822_header = $rfc822_header; + } + parse_message_entities($msg->entities[$i], $id, $imap_stream); + } + } +}