소스 검색

Fixed on the fly decoding of base64 attachment. We need to do on the fly
decoding because otherwise we have to buffer entire attachments in memory
which will cause out of memory errors with large attachments.

The fix has to do with the grouping of bytes in pairs of 4 which represents
24 bits of data. If such group is splitted over 2 lines then on the fly
decoding went wrong. Now we count the pure base64 data (without \r\n, \r \n
and spaces), divide it by 4 and return incomplete pairs which get processed
the in the next loop.

stekkel 21 년 전
부모
커밋
5d2e086e5a
2개의 변경된 파일26개의 추가작업 그리고 13개의 파일을 삭제
  1. 5 12
      functions/imap_general.php
  2. 21 1
      functions/mime.php

+ 5 - 12
functions/imap_general.php

@@ -206,6 +206,7 @@ function sqimap_fread($imap_stream,$iSize,$filter=false,
     if ($iSize < $iBufferSize) {
     if ($iSize < $iBufferSize) {
         $iBufferSize = $iSize;
         $iBufferSize = $iSize;
     }
     }
+
     $iRetrieved = 0;
     $iRetrieved = 0;
     $results = '';
     $results = '';
     $sRead = $sReadRem = '';
     $sRead = $sReadRem = '';
@@ -226,19 +227,10 @@ function sqimap_fread($imap_stream,$iSize,$filter=false,
             $sRead = $sReadRem . $sRead;
             $sRead = $sReadRem . $sRead;
             $sReadRem = '';
             $sReadRem = '';
         }
         }
-        if (substr($sRead,-1) !== "\n") {  
-            $i = strrpos($sRead,"\n");
-            if ($i !== false && $iRetrieved<$iSize) {
-                ++$i;
-                $sReadRem = substr($sRead,$i);
-                $sRead = substr($sRead,0,$i);
-            } else if ($iLength && $iRetrieved<$iSize) { // linelength > received buffer
-                $sReadRem = $sRead;
-                $sRead = '';
-            }
-        } 
+
         if ($filter && $sRead) {
         if ($filter && $sRead) {
-           $filter($sRead);
+           // in case the filter is base64 decoding we return a remainder 
+           $sReadRem = $filter($sRead);
         }
         }
         if ($outputstream && $sRead) {
         if ($outputstream && $sRead) {
            if (is_resource($outputstream)) {
            if (is_resource($outputstream)) {
@@ -256,6 +248,7 @@ function sqimap_fread($imap_stream,$iSize,$filter=false,
     return $results;       
     return $results;       
 }        
 }        
 
 
+
 /**
 /**
  * Obsolete function, inform plugins that use it
  * Obsolete function, inform plugins that use it
  * @deprecated use sqimap_run_command or sqimap_run_command_list instead
  * @deprecated use sqimap_run_command or sqimap_run_command_list instead

+ 21 - 1
functions/mime.php

@@ -550,10 +550,30 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
 }
 }
 
 
 function sqimap_base64_decode(&$string) {
 function sqimap_base64_decode(&$string) {
-    $string = str_replace("\r\n", "\n", $string);
+
+    // base64 enoded data goes in pairs of 4 bytes. To achieve on the
+    // fly decoding (to reduce memory usage) you have to check if the
+    // data has incomplete pairs
+
+    // remove the noise in order to check if the 4 bytes pairs are complete
+    $string = str_replace(array("\r\n","\n", "\r", " "),array('','','',''),$string);
+
+    $sStringRem = '';    
+    $iMod = strlen($string) % 4;
+    if ($iMod) {
+        $sStringRem = substr($string,-$iMod);
+        // check if $sStringRem contains padding characters
+        if (substr($sStringRem,-1) != '=') {
+            $string = substr($string,0,-$iMod);
+        } else {
+            $sStringRem = '';
+        }
+    }
     $string = base64_decode($string);
     $string = base64_decode($string);
+    return $sStringRem;
 }
 }
 
 
+
 /* This function decodes the body depending on the encoding type. */
 /* This function decodes the body depending on the encoding type. */
 function decodeBody($body, $encoding) {
 function decodeBody($body, $encoding) {
     global $show_html_default;
     global $show_html_default;