imap_utf7 decoding of mailboxes (mailbox-tree)
[squirrelmail.git] / functions / mime.php
index 8e599f3bfaf6e346978d9dd3c48a0407cf73fe61..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;
@@ -561,6 +586,7 @@ function decodeHeader ($string, $utfencode=true,$htmlsave=true) {
     $i = 0;
     $iLastMatch = -2;
     $encoded = false;
+
     $aString = explode(' ',$string);
     $ret = '';
     foreach ($aString as $chunk) {
@@ -573,6 +599,7 @@ function decodeHeader ($string, $utfencode=true,$htmlsave=true) {
         $encoded = false;
         /* if encoded words are not separated by a linear-space-white we still catch them */
         $j = $i-1;
+       if ($chunk{0} === '=') { /* performance, saves an unnessecarry preg call */
         while ($match = preg_match('/^(.*)=\?([^?]*)\?(Q|B)\?([^?]*)\?=(.*)$/Ui',$chunk,$res)) {
             /* if the last chunk isn't an encoded string then put back the space, otherwise don't */
             if ($iLastMatch !== $j) {
@@ -614,6 +641,7 @@ function decodeHeader ($string, $utfencode=true,$htmlsave=true) {
             $chunk = $res[5];
             $encoded = true;
         }
+       }
         if (!$encoded) {
             if ($htmlsave) {
                 $ret .= ' ';
@@ -629,6 +657,15 @@ function decodeHeader ($string, $utfencode=true,$htmlsave=true) {
         }
         ++$i;
     }
+    /* remove the first added space */
+    if ($ret) {
+        if ($htmlsave) {
+            $ret = substr($ret,6);
+        } else {
+            $ret = substr($ret,1);
+        }
+    }
+    
     return $ret;
 }