DO NOT buffer base64 encoded attachments before we decode them. Instead
authorstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Wed, 18 Jun 2003 18:39:12 +0000 (18:39 +0000)
committerstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Wed, 18 Jun 2003 18:39:12 +0000 (18:39 +0000)
decode them directly after we retrieved the data from the imapserver and
echo te result. This will safe a lot of memmory usage :)

git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@5078 7612ce4b-ef26-0410-bec9-ea0150e637f0

functions/imap_general.php
functions/mime.php

index dbc42968526dbab1b0b0bb096d7648ac5a23da2b..d7109bc653fc18354a776e7a76c53e85814d1bed 100755 (executable)
@@ -51,11 +51,14 @@ function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$respon
     
 }
 
-function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
+function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, 
+                            &$message, $unique_id = false,$filter=false,
+                             $outputstream=false,$no_return=false) {
     if ($imap_stream) {
         $sid = sqimap_session_id($unique_id);
         fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
-        $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response, $message, $query);
+        $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response,
+                                  $message, $query,$filter,$outputstream,$no_return);
         return $read;
     } else {
         global $squirrelmail_language, $color;
@@ -96,13 +99,69 @@ function sqimap_fgets($imap_stream) {
     return $results;
 }
 
+function sqimap_fread($imap_stream,$iSize,$filter=false,
+                      $outputstream=false, $no_return=false) {
+    if (!$filter || !$outputstream) {
+        $iBufferSize = $iSize;
+    } else {
+        $iBufferSize = 32768;
+    }
+    $iRet = $iSize - $iBufferSize;
+    $i = 0;
+    $results = '';
+    while (($i * $iBufferSize) < $iRet) {
+        $sRead = fread($imap_stream,$iBufferSize);
+        if (!$sRead) {
+            $results = false;
+            break;
+        }
+        ++$i;
+        if ($filter) {
+           $filter($sRead);
+        }
+        if ($outputstream) {
+           if (is_resource($outputstream)) {
+               fwrite($outputstream,$sRead);
+           } else if ($outputstream == 'php://stdout') {
+               echo $sRead;
+           }
+        }
+        if ($no_return) {
+            $sRead = '';
+        }    
+        $results .= $sRead;
+    }
+    if ($results !== false) {
+        $sRead = fread($imap_stream,($iSize - ($i * $iBufferSize)));  
+        if ($filter) {
+           $filter($sRead);
+        }
+        if ($outputstream) {
+           if (is_resource($outputstream)) {      
+               fwrite($outputstream,$sRead);
+           } else if ($outputstream == 'php://stdout') { // FIXME
+               echo $sRead;
+           }
+        }
+        if ($no_return) {
+            $sRead = '';
+        }    
+        $results .= $sRead;
+    }
+    return $results;       
+}        
+
+
+
 /*
  * Reads the output from the IMAP stream.  If handle_errors is set to true,
  * 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_list ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
+function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, 
+          &$response, &$message, $query = '',
+           $filter = false, $outputstream = false, $no_return = false) {
     global $color, $squirrelmail_language;
     $read = '';
     $tag_uid_a = explode(' ',trim($tag_uid));
@@ -171,7 +230,7 @@ function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, &$respon
                             $j = strrpos($read,'{');
                             $iLit = substr($read,$j+1,-3);
                             $fetch_data[] = $read;
-                            $sLiteral = fread($imap_stream,$iLit);
+                            $sLiteral = sqimap_fread($imap_stream,$iLit,$filter,$outputstream,$no_return);
                             if ($sLiteral === false) { /* error */
                                 break 4; /* while while switch while */
                             }
@@ -335,9 +394,11 @@ function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, &$respon
     }
 }
 
-function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
-    $res = sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, $response, $message, $query);
+function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors, 
+                           &$response, &$message, $query = '',
+                           $filter=false,$outputstream=false,$no_return=false) {
+    $res = sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, 
+              $response, $message, $query,$filter,$outputstream,$no_return); 
     /* sqimap_read_data should be called for one response
        but since it just calls sqimap_read_data_list which 
        handles multiple responses we need to check for that
index 57ab298121fddc10171f21ccc5a026973688da7a..6c58f107a7f42d987fb2c2a8f03b66ccd779df3b 100644 (file)
@@ -15,9 +15,9 @@
 require_once(SM_PATH . 'functions/imap.php');
 require_once(SM_PATH . 'functions/attachment_common.php');
 
-/* --------------------------------------------------------------------------------- */
-/* MIME DECODING                                                                     */
-/* --------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* MIME DECODING                                                              */
+/* -------------------------------------------------------------------------- */
 
 /* This function gets the structure of a message and stores it in the "message" class.
  * It will return this object for use with all relevant header information and
@@ -99,6 +99,7 @@ function mime_fetch_body($imap_stream, $id, $ent_id=1) {
     /* Do a bit of error correction.  If we couldn't find the entity id, just guess
      * that it is the first one.  That is usually the case anyway.
      */
+
     if (!$ent_id) {
         $cmd = "FETCH $id BODY[]";
     } else {
@@ -156,7 +157,6 @@ function mime_fetch_body($imap_stream, $id, $ent_id=1) {
 function mime_print_body_lines ($imap_stream, $id, $ent_id=1, $encoding) {
     global $uid_support;
 
-    $sid = sqimap_session_id($uid_support);
     /* Don't kill the connection if the browser is over a dialup
      * and it would take over 30 seconds to download it.
      * DonĀ“t call set_time_limit in safe mode.
@@ -165,14 +165,35 @@ function mime_print_body_lines ($imap_stream, $id, $ent_id=1, $encoding) {
     if (!ini_get('safe_mode')) {
         set_time_limit(0);
     }
-    if ($uid_support) {
-       $sid_s = substr($sid,0,strpos($sid, ' '));
+    /* in case of base64 encoded attachments, do not buffer them.
+       Instead, echo the decoded attachment directly to screen */
+    if (strtolower($encoding) == 'base64') {
+        if (!$ent_id) {
+           $query = "FETCH $id BODY[]";
+        } else {
+           $query = "FETCH $id BODY[$ent_id]";
+        }
+        sqimap_run_command($imap_stream,$query,true,$response,$message,$uid_support,'sqimap_base64_decode','php://stdout',true);
     } else {
-       $sid_s = $sid;
+       $body = mime_fetch_body ($imap_stream, $id, $ent_id);
+       echo decodeBody($body, $encoding);
     }
 
-    $body = mime_fetch_body ($imap_stream, $id, $ent_id);
-    echo decodeBody($body, $encoding);
+    /* 
+       TODO, use the same method for quoted printable.
+       However, I assume that quoted printable attachments aren't that large
+       so the performancegain / memory usage drop will be minimal.
+       If we decide to add that then we need to adapt sqimap_fread because
+       we need to split te result on \n and fread doesn't stop at \n. That 
+       means we also should provide $results from sqimap_fread (by ref) to
+       te function and set $no_return to false. The $filter function for
+       quoted printable should handle unsetting of $results. 
+    */
+    /* 
+       TODO 2: find out how we write to the output stream php://stdout. fwrite
+       doesn't work because 'php://stdout isn't a stream.
+    */
+
     return;
 /*
     fputs ($imap_stream, "$sid FETCH $id BODY[$ent_id]\r\n");
@@ -518,6 +539,10 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
     return $attachments;
 }
 
+function sqimap_base64_decode(&$string) {
+    $string = base64_decode($string);
+}
+
 /* This function decodes the body depending on the encoding type. */
 function decodeBody($body, $encoding) {
     global $show_html_default;