From 58993ffcbbfb8b362ebf9d088125fb73d7f6cbed Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Wed, 13 Mar 2013 06:04:09 -0400 Subject: [PATCH] Fix HTML part detection for some specific message structures (#1488992) --- program/lib/Roundcube/rcube_message.php | 67 ++++++++++++++++----------------- 1 files changed, 33 insertions(+), 34 deletions(-) diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php index 08b94d8..6160c65 100644 --- a/program/lib/Roundcube/rcube_message.php +++ b/program/lib/Roundcube/rcube_message.php @@ -106,7 +106,6 @@ if (!empty($this->headers->structure)) { $this->get_mime_numbers($this->headers->structure); $this->parse_structure($this->headers->structure); - $this->parse_attachments(); } else { $this->body = $this->storage->get_body($uid); @@ -211,18 +210,20 @@ if (!$recursive) { $level = explode('.', $part->mime_id); - // Skip if level too deep or part has a file name - if (count($level) > 2 || $part->filename) { + // Skip if part is an attachment + if ($this->is_attachment($part)) { continue; } - // HTML part can be on the lower level, if not... - if (count($level) > 1) { - array_pop($level); + // Check if the part belongs to higher-level's alternative/related + while (array_pop($level) !== null) { + if (!count($level)) { + return true; + } + $parent = $this->mime_parts[join('.', $level)]; - // ... parent isn't multipart/alternative or related if ($parent->mimetype != 'multipart/alternative' && $parent->mimetype != 'multipart/related') { - continue; + continue 2; } } } @@ -272,7 +273,7 @@ $out = $this->get_part_content($mime_id); // create instance of html2text class - $txt = new html2text($out); + $txt = new rcube_html2text($out); return $txt->get_text(); } } @@ -323,7 +324,7 @@ // parse headers from message/rfc822 part if (!isset($structure->headers['subject'])) { - list($headers, $dump) = explode("\r\n\r\n", $this->get_part_content($structure->mime_id, null, true, 4096)); + list($headers, $dump) = explode("\r\n\r\n", $this->get_part_content($structure->mime_id, null, true, 8192)); $structure->headers = rcube_mime::parse_headers($headers); } } @@ -351,15 +352,22 @@ // print body if message doesn't have multiple parts if ($message_ctype_primary == 'text' && !$recursive) { + // parts with unsupported type add to attachments list + if (!in_array($message_ctype_secondary, array('plain', 'html', 'enriched'))) { + $this->attachments[] = $structure; + return; + } + $structure->type = 'content'; $this->parts[] = $structure; // Parse simple (plain text) message body - if ($message_ctype_secondary == 'plain') + if ($message_ctype_secondary == 'plain') { foreach ((array)$this->uu_decode($structure) as $uupart) { $this->mime_parts[$uupart->mime_id] = $uupart; $this->attachments[] = $uupart; } + } } // the same for pgp signed messages else if ($mimetype == 'application/pgp' && !$recursive) { @@ -379,7 +387,7 @@ // get html/plaintext parts, other add to attachments list foreach ($structure->parts as $p => $sub_part) { $sub_mimetype = $sub_part->mimetype; - $is_multipart = in_array($sub_mimetype, array('multipart/related', 'multipart/mixed', 'multipart/alternative')); + $is_multipart = preg_match('/^multipart\/(related|relative|mixed|alternative)/', $sub_mimetype); // skip empty text parts if (!$sub_part->size && !$is_multipart) { @@ -459,6 +467,17 @@ $p->ctype_secondary = 'plain'; $p->mimetype = 'text/plain'; $p->realtype = 'multipart/encrypted'; + + $this->parts[] = $p; + } + // this is an S/MIME ecrypted message -> create a plaintext body with the according message + else if ($mimetype == 'application/pkcs7-mime') { + $p = new stdClass; + $p->type = 'content'; + $p->ctype_primary = 'text'; + $p->ctype_secondary = 'plain'; + $p->mimetype = 'text/plain'; + $p->realtype = 'application/pkcs7-mime'; $this->parts[] = $p; } @@ -554,7 +573,7 @@ continue; // part belongs to a related message and is linked - if ($mimetype == 'multipart/related' + if (preg_match('/^multipart\/(related|relative)/', $mimetype) && ($mail_part->headers['content-id'] || $mail_part->headers['content-location'])) { if ($mail_part->headers['content-id']) $mail_part->content_id = preg_replace(array('/^</', '/>$/'), '', $mail_part->headers['content-id']); @@ -593,7 +612,7 @@ } // if this was a related part try to resolve references - if ($mimetype == 'multipart/related' && sizeof($this->inline_parts)) { + if (preg_match('/^multipart\/(related|relative)/', $mimetype) && sizeof($this->inline_parts)) { $a_replaces = array(); $img_regexp = '/^image\/(gif|jpe?g|png|tiff|bmp|svg)/'; @@ -639,26 +658,6 @@ // message is a single part non-text (without filename) else if (preg_match('/application\//i', $mimetype)) { $this->attachments[] = $structure; - } - } - - - /** - * Parse attachment parts - */ - private function parse_attachments() - { - // Attachment must have a name - foreach ($this->attachments as $attachment) { - if (!$attachment->filename) { - $ext = rcube_mime::get_mime_extensions($attachment->mimetype); - $ext = array_shift($ext); - - $attachment->filename = 'Part_' . $attachment->mime_id; - if ($ext) { - $attachment->filename .= '.' . $ext; - } - } } } -- Gitblit v1.9.1