Add option that allows email address to be shown on message listings instead of full...
[squirrelmail.git] / functions / mime.php
index 0a265568041d086335b27794769a542d286eea19..ca7f836c0affe9722c52f5b89ecc92b61eea8892 100644 (file)
@@ -181,7 +181,7 @@ function mime_fetch_body($imap_stream, $id, $ent_id=1, $fetch_size=0) {
     return $ret;
 }
 
-function mime_print_body_lines ($imap_stream, $id, $ent_id=1, $encoding, $rStream='php://stdout') {
+function mime_print_body_lines ($imap_stream, $id, $ent_id=1, $encoding, $rStream='php://stdout', $force_crlf='') {
 
     /* Don't kill the connection if the browser is over a dialup
      * and it would take over 30 seconds to download it.
@@ -203,9 +203,9 @@ function mime_print_body_lines ($imap_stream, $id, $ent_id=1, $encoding, $rStrea
     } else {
         $body = mime_fetch_body ($imap_stream, $id, $ent_id);
         if (is_resource($rStream)) {
-            fputs($rStream,decodeBody($body,$encoding));
+            fputs($rStream,decodeBody($body, $encoding, $force_crlf));
         } else {
-            echo decodeBody($body, $encoding);
+            echo decodeBody($body, $encoding, $force_crlf);
         }
     }
 
@@ -291,7 +291,8 @@ function translateText(&$body, $wrap_at, $charset) {
 
     $body_ary = explode("\n", $body);
     for ($i=0; $i < count($body_ary); $i++) {
-        $line = $body_ary[$i];
+        $line = rtrim($body_ary[$i],"\r");
+
         if (strlen($line) - 2 >= $wrap_at) {
             sqWordWrap($line, $wrap_at, $charset);
         }
@@ -342,10 +343,9 @@ function translateText(&$body, $wrap_at, $charset) {
  * @param string $ent_num (since 1.3.0) message part id
  * @param integer $id (since 1.3.0) message id
  * @param string $mailbox (since 1.3.0) imap folder name
- * @param boolean $clean (since 1.5.1) Do not output stuff that's irrelevant for the printable version.
  * @return string html formated message text
  */
-function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $mailbox='INBOX', $clean=FALSE) {
+function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $mailbox='INBOX') {
     /* This if statement checks for the entity to show as the
      * primary message. To add more of them, just put them in the
      * order that is their priority.
@@ -361,10 +361,7 @@ function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $ma
 
     // If there's no "view_unsafe_images" variable in the URL, turn unsafe
     // images off by default.
-    // FIXME: Update this code to use the default value FALSE.
-    if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
-        $view_unsafe_images = false;
-    }
+    sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
 
     $body = '';
     $urlmailbox = urlencode($mailbox);
@@ -404,9 +401,7 @@ function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $ma
                 $body = trim($body);
                 translateText($body, $wrap_at,
                         $body_message->header->getParameter('charset'));
-            } elseif ($use_iframe && ! $clean) {
-                // $clean is used to remove iframe in printable view.
-
+            } elseif ($use_iframe) {
                 /**
                  * If we don't add html message between iframe tags,
                  * we must detect unsafe images and modify $has_unsafe_images.
@@ -446,11 +441,6 @@ function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $ma
                     $body_message->header->getParameter('charset'));
         }
 
-        // if this is the clean display (i.e. printer friendly), stop here.
-        if ( $clean ) {
-            return $body;
-        }
-
         /*
          * Previously the links for downloading and unsafe images were printed
          * under the mail. By putting the links in a global variable we can
@@ -506,9 +496,7 @@ function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num, $id, $ma
 }
 
 /**
- * Generate attachments array for passing to templates.  Separated from
- * formatAttachments() below so that the same array can be given to the
- * print-friendly version.
+ * Generate attachments array for passing to templates.
  *
  * @since 1.5.2
  * @param object $message SquirrelMail message object
@@ -701,44 +689,79 @@ function sqimap_base64_decode(&$string) {
 }
 
 /**
- * Decodes encoded message body
+ * Decodes encoded string (usually message body)
+ *
+ * This function decodes a string (usually the message body)
+ * depending on the encoding type.  Currently quoted-printable
+ * and base64 encodings are supported.
+ *
+ * The decode_body hook was added to this function in 1.4.2/1.5.0.
+ * The $force_crlf parameter was added in 1.5.2.
+ *
+ * @param string $string     The encoded string
+ * @param string $encoding   used encoding
+ * @param string $force_crlf Whether or not to force CRLF or LF
+ *                           line endings (or to leave as is).
+ *                           If given as "LF", line endings will
+ *                           all be converted to LF; if "CRLF",
+ *                           line endings will all be converted
+ *                           to CRLF.  If given as an empty value,
+ *                           the global $default_force_crlf will
+ *                           be consulted (it can be specified in
+ *                           config/config_local.php).  Otherwise,
+ *                           any other value will cause the string
+ *                           to be left alone.  Note that this will
+ *                           be overridden to "LF" if not using at
+ *                           least PHP version 4.3.0. (OPTIONAL;
+ *                           default is empty - consult global
+ *                           default value)
+ *
+ * @return string The decoded string
  *
- * This function decodes the body depending on the encoding type.
- * Currently quoted-printable and base64 encodings are supported.
- * decode_body hook was added to this function in 1.4.2/1.5.0
- * @param string $body encoded message body
- * @param string $encoding used encoding
- * @return string decoded string
  * @since 1.0
+ *
  */
-function decodeBody($body, $encoding) {
+function decodeBody($string, $encoding, $force_crlf='') {
+
+    global $force_crlf_default;
+    if (empty($force_crlf)) $force_crlf = $force_crlf_default;
+    $force_crlf = strtoupper($force_crlf);
+
+    // must force line endings to LF due to broken
+    // quoted_printable_decode() in PHP versions
+    // before 4.3.0 (see below)
+    //
+    if (!check_php_version(4, 3, 0) || $force_crlf == 'LF')
+        $string = str_replace("\r\n", "\n", $string);
+    else if ($force_crlf == 'CRLF')
+        $string = str_replace("\n", "\r\n", $string);
 
-    $body = str_replace("\r\n", "\n", $body);
     $encoding = strtolower($encoding);
 
     $encoding_handler = do_hook('decode_body', $encoding);
 
 
-    // plugins get first shot at decoding the body
+    // plugins get first shot at decoding the string
     //
     if (!empty($encoding_handler) && function_exists($encoding_handler)) {
-        $body = $encoding_handler('decode', $body);
+        $string = $encoding_handler('decode', $string);
 
     } elseif ($encoding == 'quoted-printable' ||
             $encoding == 'quoted_printable') {
-        /**
-         * quoted_printable_decode() function is broken in older
-         * php versions. Text with \r\n decoding was fixed only
-         * in php 4.3.0. Minimal code requirement 4.0.4 +
-         * str_replace("\r\n", "\n", $body); call.
-         */
-        $body = quoted_printable_decode($body);
+
+        // quoted_printable_decode() function is broken in older
+        // php versions.  Text with \r\n decoding was fixed only
+        // in php 4.3.0.  Minimal code requirement is PHP 4.0.4+
+        // and the above call to:  str_replace("\r\n", "\n", $string);
+        //
+        $string = quoted_printable_decode($string);
+
     } elseif ($encoding == 'base64') {
-        $body = base64_decode($body);
+        $string = base64_decode($string);
     }
 
     // All other encodings are returned raw.
-    return $body;
+    return $string;
 }
 
 /**
@@ -1857,10 +1880,7 @@ function sq_fix_url($attname, &$attvalue, $message, $id, $mailbox,$sQuote = '"')
 
     // If there's no "view_unsafe_images" variable in the URL, turn unsafe
     // images off by default.
-    // FIXME: Update this code to use the default value FALSE.
-    if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
-        $view_unsafe_images = false;
-    }
+    sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
 
     $secremoveimg = '../images/' . _("sec_remove_eng.png");
 
@@ -1896,15 +1916,72 @@ function sq_fix_url($attname, &$attvalue, $message, $id, $mailbox,$sQuote = '"')
                                 $attvalue = $sQuote . $secremoveimg . $sQuote;
                             } else {
                                 if (isset($aUrl['path'])) {
+
+                                    // No one has been able to show that image URIs
+                                    // can be exploited, so for now, no restrictions
+                                    // are made at all.  If this proves to be a problem,
+                                    // the commented-out code below can be of help.
+                                    // (One consideration is that I see nothing in this
+                                    // function that specifically says that we will
+                                    // only ever arrive here when inspecting an image
+                                    // tag, although that does seem to be the end
+                                    // result - e.g., <script src="..."> where malicious
+                                    // image URIs are in fact a problem are already
+                                    // filtered out elsewhere.
+                                    /* ---------------------------------
                                     // validate image extension.
                                     $ext = strtolower(substr($aUrl['path'],strrpos($aUrl['path'],'.')));
                                     if (!in_array($ext,array('.jpeg','.jpg','xjpeg','.gif','.bmp','.jpe','.png','.xbm'))) {
-                                        $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
+                                        // If URI is to something other than
+                                        // a regular image file, get the contents
+                                        // and try to see if it is an image.
+                                        // Don't use Fileinfo (finfo_file()) because
+                                        // we'd need to make the admin configure the
+                                        // location of the magic.mime file (FIXME: add finfo_file() support later?)
+                                        //
+                                        $mime_type = '';
+                                        if (function_exists('mime_content_type')
+                                         && ($FILE = @fopen($attvalue, 'rb', FALSE))) {
+
+                                            // fetch file
+                                            //
+                                            $file_contents = '';
+                                            while (!feof($FILE)) {
+                                                $file_contents .= fread($FILE, 8192);
+                                            }
+                                            fclose($FILE);
+
+                                            // store file locally
+                                            //
+                                            global $attachment_dir, $username;
+                                            $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
+                                            $localfilename = GenerateRandomString(32, '', 7);
+                                            $full_localfilename = "$hashed_attachment_dir/$localfilename";
+                                            while (file_exists($full_localfilename)) {
+                                                $localfilename = GenerateRandomString(32, '', 7);
+                                                $full_localfilename = "$hashed_attachment_dir/$localfilename";
+                                            }
+                                            $FILE = fopen("$hashed_attachment_dir/$localfilename", 'wb');
+                                            fwrite($FILE, $file_contents);
+                                            fclose($FILE);
+
+                                            // get mime type and remove file
+                                            //
+                                            $mime_type = mime_content_type("$hashed_attachment_dir/$localfilename");
+                                            unlink("$hashed_attachment_dir/$localfilename");
+                                        }
+                                        // debug: echo "$attvalue FILE TYPE IS $mime_type<HR>";
+                                        if (substr(strtolower($mime_type), 0, 5) != 'image') {
+                                            $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
+                                        }
                                     }
+                                    --------------------------------- */
                                 } else {
                                     $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
                                 }
                             }
+                        } else {
+                            $attvalue = $sQuote . $attvalue . $sQuote;
                         }
                         break;
                     case 'outbind':
@@ -1913,13 +1990,13 @@ function sq_fix_url($attname, &$attvalue, $message, $id, $mailbox,$sQuote = '"')
                          * One day MS might actually make it match something useful, for now, falling
                          * back to using cid2http, so we can grab the blank.png.
                          */
-                        $attvalue = sq_cid2http($message, $id, $attvalue, $mailbox);
+                        $attvalue = $sQuote . sq_cid2http($message, $id, $attvalue, $mailbox) . $sQuote;
                         break;
                     case 'cid':
                         /**
                             * Turn cid: urls into http-friendly ones.
                             */
-                        $attvalue = sq_cid2http($message, $id, $attvalue, $mailbox);
+                        $attvalue = $sQuote . sq_cid2http($message, $id, $attvalue, $mailbox) . $sQuote;
                         break;
                     default:
                         $attvalue = $sQuote . SM_PATH . 'images/blank.png' . $sQuote;
@@ -2132,7 +2209,7 @@ function sq_cid2http($message, $id, $cidurl, $mailbox){
     }
 
     if (!empty($linkurl)) {
-        $httpurl = $quotchar . SM_PATH . 'src/download.php?absolute_dl=true&amp;' .
+        $httpurl = $quotchar . sqm_baseuri() . 'src/download.php?absolute_dl=true&amp;' .
             "passed_id=$id&amp;mailbox=" . urlencode($mailbox) .
             '&amp;ent_id=' . $linkurl . $quotchar;
     } else {
@@ -2502,10 +2579,7 @@ function magicHTML($body, $id, $message, $mailbox = 'INBOX', $take_mailto_links
 
     // If there's no "view_unsafe_images" variable in the URL, turn unsafe
     // images off by default.
-    // FIXME: Update this code to use the default value FALSE.
-    if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
-        $view_unsafe_images = false;
-    }
+    sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
 
     if (!$view_unsafe_images){
         /**