From c82d09a052b929be2087a73d95be8657a33027b3 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 17 Dec 2015 03:20:08 -0500
Subject: [PATCH] Fix handling of message/rfc822 attachments on replies and forwards (#1490607)
---
CHANGELOG | 1
program/steps/mail/compose.inc | 50 +++++++++++++------------
program/steps/mail/func.inc | 11 -----
program/lib/Roundcube/rcube_message.php | 44 ++++-----------------
4 files changed, 36 insertions(+), 70 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index cb04b39..f00cf41 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@
- Fix HTML sanitizer to skip <!-- node type X --> in output (#1490583)
- Fix invalid LDAP query in ACL user autocompletion (#1490591)
- Fix regression in displaying contents of message/rfc822 parts (#1490606)
+- Fix handling of message/rfc822 attachments on replies and forwards (#1490607)
RELEASE 1.1.3
-------------
diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php
index 0d969a0..b9008af 100644
--- a/program/lib/Roundcube/rcube_message.php
+++ b/program/lib/Roundcube/rcube_message.php
@@ -677,24 +677,16 @@
$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') ||
@@ -705,8 +697,9 @@
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;
@@ -728,14 +721,6 @@
if (!empty($mail_part->filename)) {
$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') {
@@ -760,21 +745,14 @@
// 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'])
$mail_part->content_location = $mail_part->headers['content-base'] . $mail_part->headers['content-location'];
$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)
@@ -790,10 +768,6 @@
$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') {
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index c888028..f158029 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -749,11 +749,9 @@
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;
}
}
@@ -763,7 +761,7 @@
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;
@@ -1180,6 +1178,10 @@
$messages = array();
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') {
@@ -1196,23 +1198,10 @@
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;
}
}
@@ -1244,9 +1233,22 @@
{
global $RCMAIL, $COMPOSE;
- $cid_map = array();
+ $cid_map = array();
+ $messages = array();
+
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['attachments'][$attachment['id']] = $attachment;
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 7c30673..12acaf8 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1218,17 +1218,6 @@
// 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);
--
Gitblit v1.9.1