Fix misdetection of filenames containing spaces.
[banana.git] / banana / mimepart.inc.php
index 6b0f399..b072242 100644 (file)
@@ -107,7 +107,7 @@ class BananaMimePart
             $this->body         = null;
             $this->format       = null;
             $this->id           = null;
-        } 
+        }
     }
 
     public function addAttachment(array $file, $content_type = null, $disposition = 'attachment')
@@ -124,7 +124,7 @@ class BananaMimePart
         return false;
     }
 
-    protected function getHeader($title, $filter = null)
+    public function getHeader($title, $filter = null)
     {
         if (!isset($this->headers[$title])) {
             return null;
@@ -136,7 +136,7 @@ class BananaMimePart
             return trim($matches[1]);
         }
         return null;
-    } 
+    }
 
     protected function fromRaw($data)
     {
@@ -156,10 +156,12 @@ class BananaMimePart
             return;
         }
         $content       = join("\n", $lines);
+        unset($lines);
         $test          = trim($content);
         if (empty($test)) {
             return;
         }
+        unset($test);
 
         $content_type = strtolower($this->getHeader('content-type', '/^\s*([^ ;]+?)(;|$)/'));
         if (empty($content_type)) {
@@ -172,7 +174,7 @@ class BananaMimePart
             $disposition  = $this->getHeader('content-disposition', '/(inline|attachment)/i');
             $boundary     = $this->getHeader('content-type', '/boundary="?([^ "]+?)"?\s*(;|$)/i');
             $charset      = strtolower($this->getHeader('content-type', '/charset="?([^ "]+?)"?\s*(;|$)/i'));
-            $filename     = $this->getHeader('content-disposition', '/filename="?([^ "]+?)"?\s*(;|$)/i');
+            $filename     = $this->getHeader('content-disposition', '/filename="?([^"]+?)"?\s*(;|$)/i');
             $format       = strtolower($this->getHeader('content-type', '/format="?([^ "]+?)"?\s*(;|$)/i'));
             $id           = $this->getHeader('content-id', '/<(.*?)>/');
             $sign_protocole = strtolower($this->getHeader('content-type', '/protocol="?([^ "]+?)"?\s*(;|$)/i'));
@@ -181,6 +183,10 @@ class BananaMimePart
             }
         }
         list($type, $subtype) = explode('/', $content_type);
+        if ($disposition == 'attachment') {
+            $this->makeDataPart($content, $content_type, $encoding, $filename, $disposition, $id);
+            return;
+        }
         switch ($type) {
           case 'text': case 'message':
             $this->makeTextPart($content, $content_type, $encoding, $charset, $format);
@@ -201,7 +207,14 @@ class BananaMimePart
             $parts = $this->findUUEncoded();
             if (count($parts)) {
                 $this->convertToMultiPart();
-                $this->multipart    = array_merge(array($textpart), $parts);
+                $this->multipart = array_merge($this->multipart, $parts);
+                // Restore "message" headers to the previous level"
+                $this->headers = array();
+                foreach (Banana::$msgshow_headers as $hdr) {
+                    if (isset($this->multipart[0]->headers[$hdr])) {
+                        $this->headers[$hdr] = $this->multipart[0]->headers[$hdr];
+                    }
+                }
             }
         }
     }
@@ -220,11 +233,11 @@ class BananaMimePart
         foreach ($parts as &$part) {
             $newpart = new BananaMimePart($part);
             if (!is_null($newpart->content_type)) {
-                if ($signed && $newpart->content_type == $this->signature['protocole']) { 
+                if ($signed && $newpart->content_type == $this->signature['protocole']) {
                     $signature = $newpart->body;
-                } elseif ($signed) { 
-                    $signed_message = $part; 
-                } 
+                } elseif ($signed) {
+                    $signed_message = $part;
+                }
                 $this->multipart[] = $newpart;
             }
         }
@@ -238,6 +251,9 @@ class BananaMimePart
     {
         if ($is_filename) {
             $type = mime_content_type($data);
+            if ($type == 'text/plain') { // XXX Workaround a bug of php 5.2.0+etch10 (fallback for mime_content_type is text/plain)
+                $type = preg_replace('/;.*/', '', trim(shell_exec('file -bi ' . escapeshellarg($data))));
+            }
         } else {
             $arg = escapeshellarg($data);
             $type = preg_replace('/;.*/', '', trim(shell_exec("echo $arg | file -bi -")));
@@ -248,7 +264,7 @@ class BananaMimePart
     private function findUUEncoded()
     {
         $this->decodeContent();
-        $parts = array(); 
+        $parts = array();
         if (preg_match_all("/\n(begin \d+ ([^\r\n]+)\r?(?:\n(?!end)[^\n]*)*\nend)/",
             $this->body, $matches, PREG_SET_ORDER)) {
             foreach ($matches as &$match) {
@@ -257,11 +273,12 @@ class BananaMimePart
                 if ($mime != 'application/x-empty') {
                     $this->body = trim(str_replace($match[0], '', $this->body));
                     $newpart = new BananaMimePart;
+                    self::decodeHeader($match[2]);
                     $newpart->makeDataPart($data, $mime, '8bit', $match[2], 'attachment');
                     $parts[] = $newpart;
                 }
-            }   
-        } 
+            }
+        }
         return $parts;
     }
 
@@ -272,7 +289,7 @@ class BananaMimePart
         return str_replace('_', ' ', $s);
     }
 
-    static public function decodeHeader(&$val, $key)
+    static public function decodeHeader(&$val, $key = null)
     {
         if (preg_match('/[\x80-\xff]/', $val)) {
             if (!is_utf8($val)) {
@@ -295,7 +312,7 @@ class BananaMimePart
                 if (strpos($line, ':') !== false) {
                     list($hdr, $val) = explode(":", $line, 2);
                     $hdr = strtolower($hdr);
-                    if (in_array($hdr, Banana::$msgparse_headers)) {  
+                    if (in_array($hdr, Banana::$msgparse_headers)) {
                         $headers[$hdr] = ltrim($val);
                     } else {
                         unset($hdr);
@@ -405,15 +422,15 @@ class BananaMimePart
         $content = "";
         if ($with_headers) {
             foreach ($this->getHeaders() as $key => $value) {
-                $line = "$key: $value"; 
+                $line = "$key: $value";
                 $line = explode("\n", wordwrap($line, Banana::$msgshow_wrap));
                 for ($i = 1 ; $i < count($line) ; $i++) {
                     $line[$i] = "\t" . $line[$i];
                 }
                 $content .= implode("\n", $line) . "\n";
-            } 
+            }
             $content .= "\n";
-        } 
+        }
         if ($this->isType('multipart')) {
             $this->setBoundary();
             foreach ($this->multipart as &$part) {
@@ -430,9 +447,9 @@ class BananaMimePart
 
     public function getText()
     {
-        $signed =& $this->getSignedPart(); 
-        if ($signed !== $this) { 
-            return $signed->getText(); 
+        $signed =& $this->getSignedPart();
+        if ($signed !== $this) {
+            return $signed->getText();
         }
         $this->decodeContent();
         return $this->body;
@@ -440,9 +457,9 @@ class BananaMimePart
 
     public function toHtml()
     {
-        $signed =& $this->getSignedPart(); 
-        if ($signed !== $this) { 
-            return $signed->toHtml(); 
+        $signed =& $this->getSignedPart();
+        if ($signed !== $this) {
+            return $signed->toHtml();
         }
         @list($type, $subtype) = $this->getType();
         if ($type == 'image') {
@@ -468,11 +485,11 @@ class BananaMimePart
             if (!$part) {
                 $part = $this->content_type;
             }
-            return '[' . Banana::$page->makeImgLink(array('group' => Banana::$group,
+            return '<span>[' . Banana::$page->makeImgLink(array('group' => Banana::$group,
                                                  'artid' => Banana::$artid,
                                                  'part'  => $part,
                                                  'text'  => $this->filename ? $this->filename : $this->content_type,
-                                                 'img'   => 'save')) . ']';
+                                                 'img'   => 'save')) . ']</span>';
         } elseif ($type == 'multipart' && ($subtype == 'mixed' || $subtype == 'report')) {
             $text = '';
             foreach ($this->multipart as &$part) {