[evolution/gnome-3-30] [Composer] Draft email can lose attachments when opened



commit 88170825f1b39e796cc518cb3e689af085ddfc8a
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jan 18 11:24:30 2019 +0100

    [Composer] Draft email can lose attachments when opened
    
    Parts with Content-ID or Content-Location had been considered as inline
    content and not added into real attachments, even when not referenced
    in the HTML body. This addresses it in a way that it's only for images
    and the worse case is to add it to both inline images and attachments,
    to not lose it.
    
    Reported downstream as:
    https://bugzilla.redhat.com/show_bug.cgi?id=1666572

 src/composer/e-msg-composer.c | 86 +++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 23 deletions(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index 9f56b99426..89c1f69319 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -129,21 +129,25 @@ static void       add_attachments_from_multipart  (EMsgComposer *composer,
 /* used by e_msg_composer_setup_with_message () */
 static void    handle_multipart                (EMsgComposer *composer,
                                                 CamelMultipart *multipart,
+                                                CamelMimePart *parent_part,
                                                 gboolean keep_signature,
                                                 GCancellable *cancellable,
                                                 gint depth);
 static void    handle_multipart_alternative    (EMsgComposer *composer,
                                                 CamelMultipart *multipart,
+                                                CamelMimePart *parent_part,
                                                 gboolean keep_signature,
                                                 GCancellable *cancellable,
                                                 gint depth);
 static void    handle_multipart_encrypted      (EMsgComposer *composer,
                                                 CamelMimePart *multipart,
+                                                CamelMimePart *parent_part,
                                                 gboolean keep_signature,
                                                 GCancellable *cancellable,
                                                 gint depth);
 static void    handle_multipart_signed         (EMsgComposer *composer,
                                                 CamelMultipart *multipart,
+                                                CamelMimePart *parent_part,
                                                 gboolean keep_signature,
                                                 GCancellable *cancellable,
                                                 gint depth);
@@ -3105,6 +3109,31 @@ e_msg_composer_flush_pending_body (EMsgComposer *composer)
        g_object_set_data (G_OBJECT (composer), "body:text", NULL);
 }
 
+static gboolean
+emc_is_attachment_part (CamelMimePart *mime_part,
+                       CamelMimePart *parent_part)
+{
+       const CamelContentDisposition *cd;
+       CamelContentType *ct, *parent_ct = NULL;
+
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), FALSE);
+
+       ct = camel_mime_part_get_content_type (mime_part);
+       cd = camel_mime_part_get_content_disposition (mime_part);
+
+       if (parent_part)
+               parent_ct = camel_mime_part_get_content_type (parent_part);
+
+       if (!camel_content_disposition_is_attachment_ex (cd, ct, parent_ct))
+               return FALSE;
+
+       /* It looks like an attachment now. Make it an attachment for all but images
+          under multipart/related, to avoid this group of false positives. */
+       return !(parent_ct && ct &&
+               camel_content_type_is (parent_ct, "multipart", "related") &&
+               camel_content_type_is (ct, "image", "*"));
+}
+
 static void
 add_attachments_handle_mime_part (EMsgComposer *composer,
                                   CamelMimePart *mime_part,
@@ -3131,8 +3160,9 @@ add_attachments_handle_mime_part (EMsgComposer *composer,
                        composer, (CamelMultipart *) wrapper,
                        just_inlines, depth + 1);
        } else if (just_inlines) {
-               if (camel_mime_part_get_content_id (mime_part) ||
-                   camel_mime_part_get_content_location (mime_part))
+               if (camel_content_type_is (content_type, "image", "*") && (
+                   camel_mime_part_get_content_id (mime_part) ||
+                   camel_mime_part_get_content_location (mime_part)))
                        e_content_editor_insert_image_from_mime_part (
                                cnt_editor, mime_part);
        } else if (related && camel_content_type_is (content_type, "image", "*")) {
@@ -3208,6 +3238,7 @@ e_msg_composer_add_message_attachments (EMsgComposer *composer,
 static void
 handle_multipart_signed (EMsgComposer *composer,
                          CamelMultipart *multipart,
+                        CamelMimePart *parent_part,
                          gboolean keep_signature,
                          GCancellable *cancellable,
                          gint depth)
@@ -3258,24 +3289,24 @@ handle_multipart_signed (EMsgComposer *composer,
                        /* Handle the signed content and configure
                         * the composer to sign outgoing messages. */
                        handle_multipart_signed (
-                               composer, multipart, keep_signature, cancellable, depth);
+                               composer, multipart, parent_part, keep_signature, cancellable, depth);
 
                } else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
                        /* Decrypt the encrypted content and configure
                         * the composer to encrypt outgoing messages. */
                        handle_multipart_encrypted (
-                               composer, mime_part, keep_signature, cancellable, depth);
+                               composer, mime_part, parent_part, keep_signature, cancellable, depth);
 
                } else if (camel_content_type_is (content_type, "multipart", "alternative")) {
                        /* This contains the text/plain and text/html
                         * versions of the message body. */
                        handle_multipart_alternative (
-                               composer, multipart, keep_signature, cancellable, depth);
+                               composer, multipart, parent_part, keep_signature, cancellable, depth);
 
                } else {
                        /* There must be attachments... */
                        handle_multipart (
-                               composer, multipart, keep_signature, cancellable, depth);
+                               composer, multipart, parent_part, keep_signature, cancellable, depth);
                }
 
        } else if (camel_content_type_is (content_type, "text", "*")) {
@@ -3295,6 +3326,7 @@ handle_multipart_signed (EMsgComposer *composer,
 static void
 handle_multipart_encrypted (EMsgComposer *composer,
                             CamelMimePart *multipart,
+                           CamelMimePart *parent_part,
                             gboolean keep_signature,
                             GCancellable *cancellable,
                             gint depth)
@@ -3357,24 +3389,24 @@ handle_multipart_encrypted (EMsgComposer *composer,
                        /* Handle the signed content and configure the
                         * composer to sign outgoing messages. */
                        handle_multipart_signed (
-                               composer, content_multipart, keep_signature, cancellable, depth);
+                               composer, content_multipart, multipart, keep_signature, cancellable, depth);
 
                } else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
                        /* Decrypt the encrypted content and configure the
                         * composer to encrypt outgoing messages. */
                        handle_multipart_encrypted (
-                               composer, mime_part, keep_signature, cancellable, depth);
+                               composer, mime_part, multipart, keep_signature, cancellable, depth);
 
                } else if (camel_content_type_is (content_type, "multipart", "alternative")) {
                        /* This contains the text/plain and text/html
                         * versions of the message body. */
                        handle_multipart_alternative (
-                               composer, content_multipart, keep_signature, cancellable, depth);
+                               composer, content_multipart, multipart, keep_signature, cancellable, depth);
 
                } else {
                        /* There must be attachments... */
                        handle_multipart (
-                               composer, content_multipart, keep_signature, cancellable, depth);
+                               composer, content_multipart, multipart, keep_signature, cancellable, depth);
                }
 
        } else if (camel_content_type_is (content_type, "text", "*")) {
@@ -3396,6 +3428,7 @@ handle_multipart_encrypted (EMsgComposer *composer,
 static void
 handle_multipart_alternative (EMsgComposer *composer,
                               CamelMultipart *multipart,
+                             CamelMimePart *parent_part,
                               gboolean keep_signature,
                               GCancellable *cancellable,
                               gint depth)
@@ -3428,20 +3461,20 @@ handle_multipart_alternative (EMsgComposer *composer,
                                /* Handle the signed content and configure
                                 * the composer to sign outgoing messages. */
                                handle_multipart_signed (
-                                       composer, mp, keep_signature, cancellable, depth + 1);
+                                       composer, mp, parent_part, keep_signature, cancellable, depth + 1);
 
                        } else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
                                /* Decrypt the encrypted content and configure
                                 * the composer to encrypt outgoing messages. */
                                handle_multipart_encrypted (
-                                       composer, mime_part, keep_signature,
+                                       composer, mime_part, parent_part, keep_signature,
                                        cancellable, depth + 1);
 
                        } else {
                                /* Depth doesn't matter so long as we
                                 * don't pass 0. */
                                handle_multipart (
-                                       composer, mp, keep_signature, cancellable, depth + 1);
+                                       composer, mp, parent_part, keep_signature, cancellable, depth + 1);
                        }
 
                } else if (camel_content_type_is (content_type, "text", "html")) {
@@ -3480,6 +3513,7 @@ handle_multipart_alternative (EMsgComposer *composer,
 static void
 handle_multipart (EMsgComposer *composer,
                   CamelMultipart *multipart,
+                 CamelMimePart *parent_part,
                   gboolean keep_signature,
                   GCancellable *cancellable,
                   gint depth)
@@ -3510,25 +3544,25 @@ handle_multipart (EMsgComposer *composer,
                                /* Handle the signed content and configure
                                 * the composer to sign outgoing messages. */
                                handle_multipart_signed (
-                                       composer, mp, keep_signature, cancellable, depth + 1);
+                                       composer, mp, parent_part, keep_signature, cancellable, depth + 1);
 
                        } else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
                                /* Decrypt the encrypted content and configure
                                 * the composer to encrypt outgoing messages. */
                                handle_multipart_encrypted (
-                                       composer, mime_part, keep_signature,
+                                       composer, mime_part, parent_part, keep_signature,
                                        cancellable, depth + 1);
 
                        } else if (camel_content_type_is (
                                content_type, "multipart", "alternative")) {
                                handle_multipart_alternative (
-                                       composer, mp, keep_signature, cancellable, depth + 1);
+                                       composer, mp, parent_part, keep_signature, cancellable, depth + 1);
 
                        } else {
                                /* Depth doesn't matter so long as we
                                 * don't pass 0. */
                                handle_multipart (
-                                       composer, mp, keep_signature, cancellable, depth + 1);
+                                       composer, mp, parent_part, keep_signature, cancellable, depth + 1);
                        }
 
                } else if (depth == 0 && i == 0) {
@@ -3542,8 +3576,9 @@ handle_multipart (EMsgComposer *composer,
 
                        e_msg_composer_set_pending_body (composer, html, length, TRUE);
 
-               } else if (camel_mime_part_get_content_id (mime_part) ||
-                          camel_mime_part_get_content_location (mime_part)) {
+               } else if (camel_content_type_is (content_type, "image", "*") && (
+                          camel_mime_part_get_content_id (mime_part) ||
+                          camel_mime_part_get_content_location (mime_part))) {
                        /* special in-line attachment */
                        EHTMLEditor *editor;
                        EContentEditor *cnt_editor;
@@ -3552,6 +3587,11 @@ handle_multipart (EMsgComposer *composer,
                        cnt_editor = e_html_editor_get_content_editor (editor);
 
                        e_content_editor_insert_image_from_mime_part (cnt_editor, mime_part);
+
+                       /* Add it to both, to not lose attachments not referenced in HTML body.
+                          The inserted images are not included in the message when not referenced. */
+                       if (emc_is_attachment_part (mime_part, parent_part))
+                               e_msg_composer_attach (composer, mime_part);
                } else {
                        /* normal attachment */
                        e_msg_composer_attach (composer, mime_part);
@@ -3958,25 +3998,25 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
                        /* Handle the signed content and configure the
                         * composer to sign outgoing messages. */
                        handle_multipart_signed (
-                               composer, multipart, keep_signature, cancellable, 0);
+                               composer, multipart, mime_part, keep_signature, cancellable, 0);
 
                } else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
                        /* Decrypt the encrypted content and configure the
                         * composer to encrypt outgoing messages. */
                        handle_multipart_encrypted (
-                               composer, mime_part, keep_signature, cancellable, 0);
+                               composer, mime_part, mime_part, keep_signature, cancellable, 0);
 
                } else if (camel_content_type_is (
                        content_type, "multipart", "alternative")) {
                        /* This contains the text/plain and text/html
                         * versions of the message body. */
                        handle_multipart_alternative (
-                               composer, multipart, keep_signature, cancellable, 0);
+                               composer, multipart, mime_part, keep_signature, cancellable, 0);
 
                } else {
                        /* There must be attachments... */
                        handle_multipart (
-                               composer, multipart, keep_signature, cancellable, 0);
+                               composer, multipart, mime_part, keep_signature, cancellable, 0);
                }
        } else {
                CamelMimePart *mime_part;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]