From be346095a044f6a3f8b05fc38766f89ceef9391a Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Thu, 17 Dec 2015 09:12:06 +0100 Subject: [PATCH] Fix handling of message/rfc822 attachments on replies and forwards (#1490607) --- CHANGELOG | 1 + program/lib/Roundcube/rcube_message.php | 44 +++++----------------- program/steps/mail/compose.inc | 49 +++++++++++++------------ program/steps/mail/func.inc | 11 ------ 4 files changed, 35 insertions(+), 70 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c014d94b7..5b783e136 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ CHANGELOG Roundcube Webmail =========================== - Fix regression in displaying contents of message/rfc822 parts (#1490606) +- Fix handling of message/rfc822 attachments on replies and forwards (#1490607) RELEASE 1.2-beta ---------------- diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php index f478a445b..3e95b2b46 100644 --- a/program/lib/Roundcube/rcube_message.php +++ b/program/lib/Roundcube/rcube_message.php @@ -696,24 +696,16 @@ class rcube_message $mail_part = &$structure->parts[$i]; $primary_type = $mail_part->ctype_primary; $secondary_type = $mail_part->ctype_secondary; + $part_mimetype = $mail_part->mimetype; - // real content-type of message/rfc822 - if ($mail_part->real_mimetype) { - $part_orig_mimetype = $mail_part->mimetype; - $part_mimetype = $mail_part->real_mimetype; - list($primary_type, $secondary_type) = explode('/', $part_mimetype); - } - else { - $part_mimetype = $part_orig_mimetype = $mail_part->mimetype; - } - - // multipart/alternative - if ($primary_type == 'multipart') { + // multipart/alternative or message/rfc822 + if ($primary_type == 'multipart' || $part_mimetype == 'message/rfc822') { $this->parse_structure($mail_part, true); // list message/rfc822 as attachment as well (mostly .eml) - if ($part_orig_mimetype == 'message/rfc822' && !empty($mail_part->filename)) + if ($primary_type == 'message' && !empty($mail_part->filename)) { $this->attachments[] = $mail_part; + } } // part text/[plain|html] or delivery status else if ((($part_mimetype == 'text/plain' || $part_mimetype == 'text/html') && $mail_part->disposition != 'attachment') || @@ -724,8 +716,9 @@ class rcube_message array('object' => $this, 'structure' => $mail_part, 'mimetype' => $part_mimetype, 'recursive' => true)); - if ($plugin['abort']) + if ($plugin['abort']) { continue; + } if ($part_mimetype == 'text/html' && $mail_part->size) { $this->got_html_part = true; @@ -748,14 +741,6 @@ class rcube_message $this->attachments[] = $mail_part; } } - // part message/* - else if ($primary_type == 'message') { - $this->parse_structure($mail_part, true); - - // list as attachment as well (mostly .eml) - if (!empty($mail_part->filename)) - $this->attachments[] = $mail_part; - } // ignore "virtual" protocol parts else if ($primary_type == 'protocol') { continue; @@ -786,7 +771,8 @@ class rcube_message // part belongs to a related message and is linked if (preg_match('/^multipart\/(related|relative)/', $mimetype) - && ($mail_part->headers['content-id'] || $mail_part->headers['content-location'])) { + && ($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']); if ($mail_part->headers['content-location']) @@ -794,14 +780,6 @@ class rcube_message $this->inline_parts[] = $mail_part; } - // attachment encapsulated within message/rfc822 part needs further decoding (#1486743) - else if ($part_orig_mimetype == 'message/rfc822') { - $this->parse_structure($mail_part, true); - - // list as attachment as well (mostly .eml) - if (!empty($mail_part->filename)) - $this->attachments[] = $mail_part; - } // regular attachment with valid content type // (content-type name regexp according to RFC4288.4.2) else if (preg_match('/^[a-z0-9!#$&.+^_-]+\/[a-z0-9!#$&.+^_-]+$/i', $part_mimetype)) { @@ -817,10 +795,6 @@ class rcube_message $this->attachments[] = $mail_part; } } - // attachment part as message/rfc822 (#1488026) - else if ($mail_part->mimetype == 'message/rfc822') { - $this->parse_structure($mail_part); - } // calendar part not marked as attachment (#1490325) else if ($part_mimetype == 'text/calendar') { if (!$mail_part->filename) { diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 934b86292..bbb29d094 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -772,11 +772,9 @@ function rcmail_prepare_message_body() if (!empty($MESSAGE->parts)) { // collect IDs of message/rfc822 parts - if ($COMPOSE['mode'] == RCUBE_COMPOSE_EDIT || $COMPOSE['mode'] == RCUBE_COMPOSE_DRAFT) { - foreach ($MESSAGE->attachments as $part) { - if ($part->mimetype == 'message/rfc822') { - $messages[] = $part->mime_id; - } + foreach ($MESSAGE->mime_parts as $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; } } @@ -798,7 +796,7 @@ function rcmail_prepare_message_body() continue; } - // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode + // skip all content parts inside the message/rfc822 part foreach ($messages as $mimeid) { if (strpos($part->mime_id, $mimeid . '.') === 0) { continue 2; @@ -1253,6 +1251,10 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) } foreach ((array)$message->mime_parts as $pid => $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; + } + if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { // skip parts that aren't valid attachments if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') { @@ -1274,23 +1276,10 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) continue; } - // skip message/rfc822 attachments on forwards (#1489214) - // Thunderbird when forwarding in inline mode displays such attachments - // and skips any attachments from inside of such part, this however - // skipped e.g. images used in HTML body or other attachments. So, - // better to skip .eml attachments but not their content (included files). - if ($part->mimetype == 'message/rfc822') { - if ($COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD) { - continue; - } - $messages[] = $part->mime_id; - } - else if ($COMPOSE['mode'] != RCUBE_COMPOSE_FORWARD) { - // skip attachments included in message/rfc822 attachment (#1486487) - foreach ($messages as $mimeid) { - if (strpos($part->mime_id, $mimeid . '.') === 0) { - continue 2; - } + // skip attachments included in message/rfc822 attachment (#1486487, #1490607) + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; } } @@ -1320,14 +1309,26 @@ function rcmail_write_inline_attachments(&$message) { global $RCMAIL, $COMPOSE; - $cid_map = array(); + $cid_map = array(); + $messages = array(); if ($message->pgp_mime) { return $cid_map; } foreach ((array)$message->mime_parts as $pid => $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; + } + if (($part->content_id || $part->content_location) && $part->filename) { + // skip attachments included in message/rfc822 attachment (#1486487, #1490607) + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; + } + } + if ($attachment = rcmail_save_attachment($message, $pid, $COMPOSE['id'])) { $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 5b927933b..0f1a87a0e 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -1233,17 +1233,6 @@ function rcmail_message_body($attrib) // fetch part body $body = $MESSAGE->get_part_body($part->mime_id, true); - // extract headers from message/rfc822 parts - if ($part->mimetype == 'message/rfc822') { - $msgpart = rcube_mime::parse_message($body); - $body = rcube_message::format_part_body($msgpart->body, $msgpart); - - if (!empty($msgpart->headers) && !empty($body)) { - $part = $msgpart; - $out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers)); - } - } - // message is cached but not exists (#1485443), or other error if ($body === false) { rcmail_message_error($MESSAGE->uid);