From: lkehresman Date: Fri, 22 Jun 2001 15:52:06 +0000 (+0000) Subject: Added IMAP speed imrpovements from the guys at XS4ALL X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=commitdiff_plain;h=91f68e943315d185d3d6477b46ad824a8fbea769;hp=f61de96662fb1e93329d4a78c9edeeafdf508975;ds=sidebyside Added IMAP speed imrpovements from the guys at XS4ALL git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@1416 7612ce4b-ef26-0410-bec9-ea0150e637f0 --- diff --git a/ChangeLog b/ChangeLog index 532caa79..b38cbc59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 1.1.3 -- DEVELOPMENT ---------------------------- +- Added major speed improvements to IMAP functions by our friends at XS4ALL - Fixed MOTD - Fixed multipart/alternative messages - Updated Dutch translation diff --git a/functions/imap_general.php b/functions/imap_general.php index da84b5e5..fc7626e2 100755 --- a/functions/imap_general.php +++ b/functions/imap_general.php @@ -19,71 +19,87 @@ ** this will also handle all errors that are received. If it is not set, ** the errors will be sent back through $response and $message ******************************************************************************/ - function sqimap_read_data ($imap_stream, $pre, $handle_errors, &$response, &$message) { - global $color, $squirrelmail_language, $imap_general_debug; - $read = fgets($imap_stream, 9096); + function sqimap_read_data_list ($imap_stream, $pre, $handle_errors, + &$response, &$message) { + global $color, $squirrelmail_language, $imap_general_debug; - if (ereg("^\\* [0-9]+ FETCH.*\\{([0-9]+)\\}", $read, $regs)) { - $size = $regs[1]; - } else { - $size = 0; - } - - $data = array(); - $total_size = 0; + $read = ""; + $resultlist = array(); - $continue = true; - while ($continue) { - // Continue if needed for this single line + $more_msgs = true; + while ($more_msgs) { + $data = array(); + $total_size = 0; while (strpos($read, "\n") === false) { $read .= fgets($imap_stream, 9096); } - // For debugging purposes - if ($imap_general_debug) { - echo "$read
\n"; - flush(); - } - - // If we know the size, no need to look at the end parameters - if ($size > 0) { - if ($total_size == $size) { - $data[] = $read; - $read = fgets($imap_stream, 9096); - while (!ereg("^$pre (OK|BAD|NO)(.*)$", $read, $regs)) { - $read = fgets($imap_stream, 9096); - } - $continue = false; - } else if ($total_size > $size) { - $difference = $total_size - $size; - $total_size = $total_size - strlen($read); - $read = substr ($read, 0, strlen($read)-$difference); - $data[] = $read; - $junk = fgets($imap_stream, 9096); - $continue = false; - } else { - $data[] = $read; - $read = fgets($imap_stream, 9096); + if (ereg("^\\* [0-9]+ FETCH.*\\{([0-9]+)\\}", $read, $regs)) { + $size = $regs[1]; + } else if (ereg("^\\* [0-9]+ FETCH", $read, $regs)) { + // Sizeless response, probably single-line + // For debugging purposes + if ($imap_general_debug) { + echo "$read
\n"; + flush(); } - $total_size += strlen($read); + $size = 0; + $data[] = $read; + $read = fgets($imap_stream, 9096); } else { - if (ereg("^$pre (OK|BAD|NO)(.*)$", $read, $regs)) { - $continue = false; + $size = 0; + } + while (1) { + while (strpos($read, "\n") === false) { + $read .= fgets($imap_stream, 9096); + } + // For debugging purposes + if ($imap_general_debug) { + echo "$read
\n"; + flush(); + } + // If we know the size, no need to look at the end parameters + if ($size > 0) { + if ($total_size == $size) { + // We've reached the end of this 'message', switch to the next one. + $data[] = $read; + $break; + } else if ($total_size > $size) { + $difference = $total_size - $size; + $total_size = $total_size - strlen($read); + $data[] = substr ($read, 0, strlen($read)-$difference); + $read = substr ($read, strlen($read)-$difference, strlen($read)); + break; + } else { + $data[] = $read; + $read = fgets($imap_stream, 9096); + } + $total_size += strlen($read); } else { - $data[] = $read; - $read = fgets ($imap_stream, 9096); + if (ereg("^$pre (OK|BAD|NO)(.*)", $read, $regs) || + ereg("^\\* [0-9]+ FETCH.*", $read, $regs)) { + break; + } else { + $data[] = $read; + $read = fgets ($imap_stream, 9096); + } } } - } + while (($more_msgs = !ereg("^$pre (OK|BAD|NO)(.*)$", $read, $regs)) && + !ereg("^\\* [0-9]+ FETCH.*", $read, $regs)) { + $read = fgets($imap_stream, 9096); + } + $resultlist[] = $data; + } $response = $regs[1]; $message = trim($regs[2]); if ($imap_general_debug) echo '--
'; if ($handle_errors == false) - return $data; + return $resultlist; if ($response == 'NO') { // ignore this error from m$ exchange, it is not fatal (aka bug) @@ -105,8 +121,12 @@ echo $message . "
\n"; exit; } - - return $data; + return $resultlist; + } + + function sqimap_read_data ($imap_stream, $pre, $handle_errors, &$response, &$message) { + $res = sqimap_read_data_list($imap_stream, $pre, $handle_errors, $response, $message); + return $res[0]; } /****************************************************************************** diff --git a/functions/imap_messages.php b/functions/imap_messages.php index 2c47d5ab..076b86c6 100755 --- a/functions/imap_messages.php +++ b/functions/imap_messages.php @@ -60,88 +60,154 @@ } function sqimap_get_small_header ($imap_stream, $id, $sent) { + $res = sqimap_get_small_header_list($imap_stream, array($id), $sent); + return $res[0]; + } - fputs ($imap_stream, "a001 FETCH $id BODY.PEEK[HEADER.FIELDS (Date To From Cc Subject Message-Id X-Priority Content-Type)]\r\n"); - $read = sqimap_read_data ($imap_stream, "a001", true, $response, $message); + function sqimap_get_small_header_list ($imap_stream, $msg_list, $issent) { - $subject = _("(no subject)"); - $from = _("Unknown Sender"); - $priority = "0"; - $messageid = "<>"; - $cc = ""; - $to = ""; - $date = ""; - $type[0] = ""; - $type[1] = ""; - - $g = 0; - for ($i = 0; $i < count($read); $i++) { - if (eregi ("^to:(.*)$", $read[$i], $regs)) { - //$to = sqimap_find_displayable_name(substr($read[$i], 3)); - $to = $regs[1]; - } else if (eregi ("^from:(.*)$", $read[$i], $regs)) { - //$from = sqimap_find_displayable_name(substr($read[$i], 5)); - $from = $regs[1]; - } else if (eregi ("^x-priority:(.*)$", $read[$i], $regs)) { - $priority = trim($regs[1]); - } else if (eregi ("^message-id:(.*)$", $read[$i], $regs)) { - $messageid = trim($regs[1]); - } else if (eregi ("^cc:(.*)$", $read[$i], $regs)) { - $cc = $regs[1]; - } else if (eregi ("^date:(.*)$", $read[$i], $regs)) { - $date = $regs[1]; - } else if (eregi ("^subject:(.*)$", $read[$i], $regs)) { - $subject = htmlspecialchars(trim($regs[1])); - if ($subject == "") - $subject = _("(no subject)"); - } else if (eregi ("^content-type:(.*)$", $read[$i], $regs)) { - $type = strtolower(trim($regs[1])); - if ($pos = strpos($type, ";")) - $type = substr($type, 0, $pos); - $type = explode("/", $type); - if (! isset($type[1])) - $type[1] = ''; - } - - } + /* Get the small headers for each message in $msg_list */ + + $maxmsg = sizeof($msg_list); + $msgs_str = implode(",", $msg_list); + $results = array(); + $read_list = array(); + $sizes_list = array(); + + /* We need to return the data in the same order as the caller supplied + in $msg_list, but IMAP servers are free to return responses in + whatever order they wish... So we need to re-sort manually */ - // If there isn't a date, it takes the internal date and uses - // that as the normal date. - if (trim($date) == "") { - fputs ($imap_stream, "a002 FETCH $id INTERNALDATE\r\n"); - $internal_read = sqimap_read_data ($imap_stream, "a002", true, $r, $m); - - // * 22 FETCH (INTERNALDATE " 8-Sep-2000 13:17:07 -0500") - $date = $internal_read[0]; - $date = eregi_replace(".*internaldate \"", "", $date); - $date = eregi_replace("\".*", "", $date); - $date_ary = explode(" ", trim($date)); - $date_ary[0] = str_replace("-", " ", $date_ary[0]); - $date = implode (" ", $date_ary); + for ($i = 0; $i < sizeof($msg_list); $i++) { + $id2index[$msg_list[$i]] = $i; } - fputs ($imap_stream, "a003 FETCH $id RFC822.SIZE\r\n"); - $read = sqimap_read_data($imap_stream, "a003", true, $r, $m); - eregi("([0-9]+)[^0-9]*$", $read[0], $regs); - $size = $regs[1]; + $query = "a001 FETCH $msgs_str BODY.PEEK[HEADER.FIELDS (Date To From Cc Subject Message-Id X-Priority Content-Type)]\r\n"; + fputs ($imap_stream, $query); + $readin_list = sqimap_read_data_list($imap_stream, "a001", true, $response, $message); + + foreach ($readin_list as $r) { + if (!eregi("^\\* ([0-9]+) FETCH", $r[0], $regs)) { + set_up_language($squirrelmail_language); + echo "
\n"; + echo _("ERROR : Could not complete request."); + echo "
\n"; + echo _("Unknown response from IMAP server: "); + echo $r[0] . "

\n"; + exit; + } + if (!count($id2index[$regs[1]])) { + set_up_language($squirrelmail_language); + echo "
\n"; + echo _("ERROR : Could not complete request."); + echo "
\n"; + echo _("Unknown messagenumber in reply from server: "); + echo $regs[1] . "

\n"; + exit; + } + $read_list[$id2index[$regs[1]]] = $r; + } + arsort($read_list); - $header = new small_header; - if ($sent == true) - $header->from = (trim($to) != '')? $to : _("(only Cc/Bcc)"); - else - $header->from = $from; - - $header->date = $date; - $header->subject = $subject; - $header->to = $to; - $header->priority = $priority; - $header->message_id = $messageid; - $header->cc = $cc; - $header->size = $size; - $header->type0 = $type[0]; - $header->type1 = $type[1]; + $query = "a002 FETCH $msgs_str RFC822.SIZE\r\n"; + fputs ($imap_stream, $query); + $sizesin_list = sqimap_read_data_list($imap_stream, "a002", true, $response, $message); - return $header; + foreach ($sizesin_list as $r) { + if (!eregi("^\\* ([0-9]+) FETCH", $r[0], $regs)) { + set_up_language($squirrelmail_language); + echo "
\n"; + echo _("ERROR : Could not complete request."); + echo "
\n"; + echo _("Unknown response from IMAP server: "); + echo $r[0] . "

\n"; + exit; + } + if (!count($id2index[$regs[1]])) { + set_up_language($squirrelmail_language); + echo "
\n"; + echo _("ERROR : Could not complete request."); + echo "
\n"; + echo _("Unknown messagenumber in reply from server: "); + echo $regs[1] . "

\n"; + exit; + } + $sizes_list[$id2index[$regs[1]]] = $r; + } + arsort($sizes_list); + + for ($msgi = 0; $msgi < $maxmsg; $msgi++) { + $subject = _("(no subject)"); + $from = _("Unknown Sender"); + $priority = 0; + $messageid = "<>"; + $cc = ""; + $to = ""; + $date = ""; + $type[0] = ""; + $type[1] = ""; + $read = $read_list[$msgi]; + + for ($i = 0; $i < count($read); $i++) { + if (eregi ("^to:(.*)$", $read[$i], $regs)) { + //$to = sqimap_find_displayable_name(substr($read[$i], 3)); + $to = $regs[1]; + } else if (eregi ("^from:(.*)$", $read[$i], $regs)) { + //$from = sqimap_find_displayable_name(substr($read[$i], 5)); + $from = $regs[1]; + } else if (eregi ("^x-priority:(.*)$", $read[$i], $regs)) { + $priority = trim($regs[1]); + } else if (eregi ("^message-id:(.*)$", $read[$i], $regs)) { + $messageid = trim($regs[1]); + } else if (eregi ("^cc:(.*)$", $read[$i], $regs)) { + $cc = $regs[1]; + } else if (eregi ("^date:(.*)$", $read[$i], $regs)) { + $date = $regs[1]; + } else if (eregi ("^subject:(.*)$", $read[$i], $regs)) { + $subject = htmlspecialchars(trim($regs[1])); + if ($subject == "") + $subject = _("(no subject)"); + } else if (eregi ("^content-type:(.*)$", $read[$i], $regs)) { + $type = strtolower(trim($regs[1])); + if ($pos = strpos($type, ";")) + $type = substr($type, 0, $pos); + $type = explode("/", $type); + if (! isset($type[1])) + $type[1] = ''; + } + + } + if (trim($date) == "") { + fputs($imap_stream, "a002 FETCH $msg_list[$msgi] INTERNALDATE\r\n"); + $readdate = sqimap_read_data($imap_stream, "a002", true, $response, $message); + if (eregi(".*INTERNALDATE \"(.*)\".*", $readdate[0], $regs)) { + $date_list = explode(" ", trim($regs[1])); + $date_list[0] = str_replace("-", " ", $date_list[0]); + $date = implode(" ", $date_list); + } + } + eregi("([0-9]+)[^0-9]*$", $sizes_list[$msgi][0], $regs); + $size = $regs[1]; + + $header = new small_header; + if ($issent == true) + $header->from = (trim($to) != '')? $to : _("(only Cc/Bcc)"); + else + $header->from = $from; + + $header->date = $date; + $header->subject = $subject; + $header->to = $to; + $header->priority = $priority; + $header->message_id = $messageid; + $header->cc = $cc; + $header->size = $size; + $header->type0 = $type[0]; + $header->type1 = $type[1]; + + $result[] = $header; + } + return $result; } /****************************************************************************** @@ -155,6 +221,34 @@ return Array('None'); } + function sqimap_get_flags_list ($imap_stream, $msg_list) { + + $msgs_str = implode(",", $msg_list); + for ($i = 0; $i < sizeof($msg_list); $i++) { + $id2index[$msg_list[$i]] = $i; + } + fputs ($imap_stream, "a001 FETCH $msgs_str FLAGS\r\n"); + $result_list = sqimap_read_data_list ($imap_stream, "a001", true, $response, $message); + $result_flags = array(); + + for ($i = 0; $i < sizeof($result_list); $i++) { + if (eregi("^\\* ([0-9]+).*FETCH.*FLAGS(.*)", $result_list[$i][0], $regs) + && count($id2index[$regs[1]])) { + $result_flags[$id2index[$regs[1]]] = explode(" ", trim(ereg_replace('[\\(\\)\\\\]', '', $regs[2]))); + } else { + set_up_language($squirrelmail_language); + echo "
\n"; + echo _("ERROR : Could not complete request."); + echo "
\n"; + echo _("Unknown response from IMAP server: "); + echo $result_list[$i][0] . "

\n"; + exit; + } + } + arsort($result_flags); + return $result_flags; + } + /****************************************************************************** ** Returns a message array with all the information about a message. See ** the documentation folder for more information about this array. diff --git a/functions/imap_search.php b/functions/imap_search.php index d6284461..d1ea2020 100644 --- a/functions/imap_search.php +++ b/functions/imap_search.php @@ -64,26 +64,24 @@ function sqimap_search($imapConnection,$search_where,$search_what,$mailbox,$colo global $sent_folder; for ($q = 0; $q < count($messagelist); $q++) { - $messagelist[$q] = trim($messagelist[$q]); - if ($mailbox == $sent_folder) - $hdr = sqimap_get_small_header ($imapConnection, $messagelist[$q], true); - else - $hdr = sqimap_get_small_header ($imapConnection, $messagelist[$q], false); - - $from[$q] = $hdr->from; - $date[$q] = $hdr->date; - $subject[$q] = $hdr->subject; - $to[$q] = $hdr->to; - $priority[$q] = $hdr->priority; - $cc[$q] = $hdr->cc; - $size[$q] = $hdr->size; - $type[$q] = $hdr->type0; - $id[$q] = $messagelist[$q]; - $flags[$q] = sqimap_get_flags ($imapConnection, $messagelist[$q]); - } - - $j = 0; - while ($j < count($messagelist)) { + $id[$q] = trim($messagelist[$q]); + } + $issent = ($mailbox == $sent_folder); + $hdr_list = sqimap_get_small_header_list($imapConnection, $id, $issent); + $flags = sqimap_get_flags_list($imapConnection, $id, $issnet); + foreach ($hdr_list as $hdr) { + $from[] = $hdr->from; + $date[] = $hdr->date; + $subject[] = $hdr->subject; + $to[] = $hdr->to; + $priority[] = $hdr->priority; + $cc[] = $hdr->cc; + $size[] = $hdr->size; + $type[] = $hdr->type0; + } + + $j = 0; + while ($j < count($messagelist)) { $date[$j] = ereg_replace(' ', ' ', $date[$j]); $tmpdate = explode(" ", trim($date[$j])); @@ -117,7 +115,7 @@ function sqimap_search($imapConnection,$search_where,$search_what,$mailbox,$colo $num++; } $j++; - } + } /** Find and remove the ones that are deleted */ $i = 0; diff --git a/functions/mailbox_display.php b/functions/mailbox_display.php index 3630f4ea..0947bc64 100644 --- a/functions/mailbox_display.php +++ b/functions/mailbox_display.php @@ -168,30 +168,15 @@ global $message_highlight_list; global $auto_expunge; - if ($auto_expunge == true) sqimap_mailbox_expunge($imapConnection, $mailbox, false); + if ($auto_expunge == true) sqimap_mailbox_expunge($imapConnection, $mailbox, false); sqimap_mailbox_select($imapConnection, $mailbox); + $issent = ($mailbox == $sent_folder); if (!$use_cache) { // if it's sorted if ($numMessages >= 1) { if ($sort < 6) { - for ($q = 0; $q < $numMessages; $q++) { - if($mailbox == $sent_folder) - $hdr = sqimap_get_small_header ($imapConnection, $q+1, true); - else - $hdr = sqimap_get_small_header ($imapConnection, $q+1, false); - - $from[$q] = $hdr->from; - $date[$q] = $hdr->date; - $subject[$q] = $hdr->subject; - $to[$q] = $hdr->to; - $priority[$q] = $hdr->priority; - $cc[$q] = $hdr->cc; - $size[$q] = $hdr->size; - $type[$q] = $hdr->type0; - $flags[$q] = sqimap_get_flags ($imapConnection, $q+1); - $id[$q] = $q + 1; - } + $id = range(1, $numMessages); } else { // if it's not sorted if ($startMessage + ($show_num - 1) < $numMessages) { @@ -206,31 +191,24 @@ $startMessage = 1; } - $real_startMessage = $numMessages - $startMessage + 1; - $real_endMessage = $numMessages - $startMessage - $show_num; + $real_endMessage = $numMessages - $startMessage - $show_num + 2; if ($real_endMessage <= 0) $real_endMessage = 1; + $id = array_reverse(range($real_endMessage, $real_startMessage)); + } - $j = 0; - for ($q = $real_startMessage; $q >= $real_endMessage; $q--) { - if($mailbox == $sent_folder) - $hdr = sqimap_get_small_header ($imapConnection, $q, true); - else - $hdr = sqimap_get_small_header ($imapConnection, $q, false); - - $from[$j] = $hdr->from; - $date[$j] = $hdr->date; - $subject[$j] = $hdr->subject; - $to[$j] = $hdr->to; - $priority[$j] = $hdr->priority; - $cc[$j] = $hdr->cc; - $size[$j] = $hdr->size; - $type[$j] = $hdr->type0; - $flags[$j] = sqimap_get_flags ($imapConnection, $q); - $id[$j] = $q; - $j++; - } + $msgs_list = sqimap_get_small_header_list($imapConnection, $id, $issent); + $flags = sqimap_get_flags_list($imapConnection, $id, $issent); + foreach ($msgs_list as $hdr) { + $from[] = $hdr->from; + $date[] = $hdr->date; + $subject[] = $hdr->subject; + $to[] = $hdr->to; + $priority[] = $hdr->priority; + $cc[] = $hdr->cc; + $size[] = $hdr->size; + $type[] = $hdr->type0; } }