Added IMAP speed imrpovements from the guys at XS4ALL
authorlkehresman <lkehresman@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Fri, 22 Jun 2001 15:52:06 +0000 (15:52 +0000)
committerlkehresman <lkehresman@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Fri, 22 Jun 2001 15:52:06 +0000 (15:52 +0000)
git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@1416 7612ce4b-ef26-0410-bec9-ea0150e637f0

ChangeLog
functions/imap_general.php
functions/imap_messages.php
functions/imap_search.php
functions/mailbox_display.php

index 532caa7943a7142a23c54459a472036dbeb08880..b38cbc594570b540e4e3d577881673043235cc2f 100644 (file)
--- 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
index da84b5e522e0fbd38ac9f947cbf17fff0ddf5055..fc7626e29cf4f9a29d1dfd39b120d309ff23cdea 100755 (executable)
     **  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 "<small><tt><font color=\"#CC0000\">$read</font></tt></small><br>\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 "<small><tt><font color=\"#CC0000\">$read</font></tt></small><br>\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 "<small><tt><font color=\"#CC0000\">$read</font></tt></small><br>\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 '--<br>';
 
       if ($handle_errors == false)
-          return $data;
+          return $resultlist;
      
       if ($response == 'NO') {
          // ignore this error from m$ exchange, it is not fatal (aka bug)
          echo $message . "</font><br>\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];
    }
    
    /******************************************************************************
index 2c47d5abf5ae5f80dbb2ae67875176eea3225fa9..076b86c6c3b87eeaa7680c0f02658288de52ce06 100755 (executable)
    }
         
    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 "<br><b><font color=$color[2]>\n";
+            echo _("ERROR : Could not complete request.");
+            echo "</b><br>\n";
+            echo _("Unknown response from IMAP server: ");
+            echo $r[0] . "</font><br>\n";
+            exit;
+         }
+         if (!count($id2index[$regs[1]])) {
+            set_up_language($squirrelmail_language);
+            echo "<br><b><font color=$color[2]>\n";
+            echo _("ERROR : Could not complete request.");
+            echo "</b><br>\n";
+            echo _("Unknown messagenumber in reply from server: ");
+            echo $regs[1] . "</font><br>\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 "<br><b><font color=$color[2]>\n";
+            echo _("ERROR : Could not complete request.");
+            echo "</b><br>\n";
+            echo _("Unknown response from IMAP server: ");
+            echo $r[0] . "</font><br>\n";
+            exit;
+         }
+         if (!count($id2index[$regs[1]])) {
+            set_up_language($squirrelmail_language);
+            echo "<br><b><font color=$color[2]>\n";
+            echo _("ERROR : Could not complete request.");
+            echo "</b><br>\n";
+            echo _("Unknown messagenumber in reply from server: ");
+            echo $regs[1] . "</font><br>\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;
    }
 
    /******************************************************************************
       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 "<br><b><font color=$color[2]>\n";
+            echo _("ERROR : Could not complete request.");
+            echo "</b><br>\n";
+            echo _("Unknown response from IMAP server: ");
+            echo $result_list[$i][0] . "</font><br>\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.
index d628446146432564cfc9aad319900a42b296459c..d1ea2020b4861705ee4d56f64995e4c24d1cfaaf 100644 (file)
@@ -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;
index 3630f4eab37b72cc7b9bff0e91333ace4df649e7..0947bc647e1dd41f9e6498c521392e925296f11b 100644 (file)
       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) {
                      $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;
             }
          }