[evolution] I#1471 - Composer: Lost attachments in reply/forward of an encrypted message



commit 29c564a64fe7a59be23111f18b799ec58931faae
Author: Milan Crha <mcrha redhat com>
Date:   Mon Apr 26 11:50:10 2021 +0200

    I#1471 - Composer: Lost attachments in reply/forward of an encrypted message
    
    Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1471

 src/composer/e-msg-composer.c | 64 +++++++++++++++++++++++++++++++++++++
 src/composer/e-msg-composer.h |  6 ++++
 src/mail/em-composer-utils.c  | 32 +++++++++----------
 src/mail/em-utils.c           | 73 ++++++++++++++++++++++++++++++++++---------
 src/mail/em-utils.h           | 11 ++++++-
 5 files changed, 154 insertions(+), 32 deletions(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index 492170e7b1..8303470809 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -3255,6 +3255,70 @@ e_msg_composer_add_message_attachments (EMsgComposer *composer,
                composer, (CamelMultipart *) wrapper, just_inlines, 0);
 }
 
+/**
+ * e_msg_composer_add_attachments_from_part_list:
+ * @composer: the composer to add the attachments to
+ * @part_list: an #EMailPartList with parts used to format the message
+ * @just_inlines: whether to attach all attachments or just add inline images
+ *
+ * Walk through all the parts in @part_list and add them to the @composer.
+ *
+ * Since: 3.42
+ */
+void
+e_msg_composer_add_attachments_from_part_list (EMsgComposer *composer,
+                                              EMailPartList *part_list,
+                                              gboolean just_inlines)
+{
+       EHTMLEditor *editor;
+       GQueue queue = G_QUEUE_INIT;
+       GList *link;
+
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+
+       if (!part_list)
+               return;
+
+       editor = e_msg_composer_get_editor (composer);
+
+       e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+       for (link = g_queue_peek_head_link (&queue); link; link = g_list_next (link)) {
+               EMailPart *part = link->data;
+               CamelMimePart *mime_part;
+               CamelContentType *content_type;
+
+               if (!e_mail_part_get_is_attachment (part))
+                       continue;
+
+               mime_part = e_mail_part_ref_mime_part (part);
+               if (!mime_part)
+                       continue;
+
+               content_type = camel_mime_part_get_content_type (mime_part);
+               if (!content_type)
+                       continue;
+
+               if (!just_inlines &&
+                   camel_content_type_is (content_type, "text", "*") &&
+                   camel_mime_part_get_filename (mime_part) == NULL) {
+                       /* Do nothing if this is a text/anything without a
+                        * filename, otherwise attach it too. */
+               } 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))) {
+                               e_html_editor_add_cid_part (editor, mime_part);
+               } else if (!just_inlines) {
+                       e_msg_composer_attach (composer, mime_part);
+               }
+
+               g_object_unref (mime_part);
+       }
+
+       while (!g_queue_is_empty (&queue))
+               g_object_unref (g_queue_pop_head (&queue));
+}
+
 static void
 handle_multipart_signed (EMsgComposer *composer,
                          CamelMultipart *multipart,
diff --git a/src/composer/e-msg-composer.h b/src/composer/e-msg-composer.h
index f385889ba4..2e4657b35d 100644
--- a/src/composer/e-msg-composer.h
+++ b/src/composer/e-msg-composer.h
@@ -29,6 +29,7 @@
 #include <shell/e-shell.h>
 
 #include <composer/e-composer-header-table.h>
+#include <em-format/e-mail-part-list.h>
 
 /* Standard GObject macros */
 #define E_TYPE_MSG_COMPOSER \
@@ -186,6 +187,11 @@ void               e_msg_composer_add_message_attachments
                                                (EMsgComposer *composer,
                                                 CamelMimeMessage *message,
                                                 gboolean just_inlines);
+void           e_msg_composer_add_attachments_from_part_list
+                                               (EMsgComposer *composer,
+                                                EMailPartList *part_list,
+                                                gboolean just_inlines);
+
 
 void           e_msg_composer_request_close    (EMsgComposer *composer);
 gboolean       e_msg_composer_can_close        (EMsgComposer *composer,
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index 944347064a..58c95017d1 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -2486,6 +2486,7 @@ forward_non_attached (EMsgComposer *composer,
                       EMailForwardStyle style)
 {
        CamelSession *session;
+       EMailPartList *part_list = NULL;
        gchar *text, *forward, *subject;
        guint32 validity_found = 0;
        guint32 flags;
@@ -2508,17 +2509,11 @@ forward_non_attached (EMsgComposer *composer,
        g_free (subject);
 
        forward = quoting_text (QUOTING_FORWARD, composer);
-       text = em_utils_message_to_html (session, message, forward, flags, NULL, NULL, NULL, &validity_found);
+       text = em_utils_message_to_html_ex (session, message, forward, flags, NULL, NULL, NULL, 
&validity_found, &part_list);
 
-       if (text != NULL) {
-               CamelDataWrapper *content;
-
-               content = camel_medium_get_content (CAMEL_MEDIUM (message));
-
-               if (CAMEL_IS_MULTIPART (content))
-                       e_msg_composer_add_message_attachments (
-                               composer, message, FALSE);
+       e_msg_composer_add_attachments_from_part_list (composer, part_list, FALSE);
 
+       if (text != NULL) {
                e_msg_composer_set_body_text (composer, text, TRUE);
 
                emu_add_composer_references_from_message (composer, message);
@@ -2533,6 +2528,7 @@ forward_non_attached (EMsgComposer *composer,
        }
 
        g_clear_object (&session);
+       g_clear_object (&part_list);
        g_free (forward);
 }
 
@@ -3597,7 +3593,8 @@ static void
 composer_set_body (EMsgComposer *composer,
                    CamelMimeMessage *message,
                    EMailReplyStyle style,
-                   EMailPartList *parts_list)
+                   EMailPartList *parts_list,
+                  EMailPartList **out_used_part_list)
 {
        gchar *text, *credits, *original;
        ESource *identity_source;
@@ -3625,9 +3622,9 @@ composer_set_body (EMsgComposer *composer,
                break;
        case E_MAIL_REPLY_STYLE_OUTLOOK:
                original = quoting_text (QUOTING_ORIGINAL, composer);
-               text = em_utils_message_to_html (
+               text = em_utils_message_to_html_ex (
                        session, message, original, E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS | keep_sig_flag,
-                       parts_list, NULL, NULL, &validity_found);
+                       parts_list, NULL, NULL, &validity_found, out_used_part_list);
                e_msg_composer_set_body_text (composer, text, TRUE);
                g_free (text);
                g_free (original);
@@ -3643,9 +3640,9 @@ composer_set_body (EMsgComposer *composer,
 
                g_clear_object (&identity_source);
 
-               text = em_utils_message_to_html (
+               text = em_utils_message_to_html_ex (
                        session, message, credits, E_MAIL_FORMATTER_QUOTE_FLAG_CITE | keep_sig_flag,
-                       parts_list, NULL, NULL, &validity_found);
+                       parts_list, NULL, NULL, &validity_found, out_used_part_list);
                g_free (credits);
                e_msg_composer_set_body_text (composer, text, TRUE);
                g_free (text);
@@ -4484,6 +4481,7 @@ em_utils_reply_to_message (EMsgComposer *composer,
        EShell *shell;
        ESourceMailCompositionReplyStyle prefer_reply_style = E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT;
        ESource *source;
+       EMailPartList *used_part_list = NULL;
        EContentEditor *cnt_editor;
        gchar *identity_uid = NULL, *identity_name = NULL, *identity_address = NULL;
        guint32 flags;
@@ -4566,7 +4564,6 @@ em_utils_reply_to_message (EMsgComposer *composer,
        }
 
        reply_setup_composer (composer, message, identity_uid, identity_name, identity_address, to, cc, 
folder, message_uid, postto);
-       e_msg_composer_add_message_attachments (composer, message, TRUE);
 
        if (postto)
                g_object_unref (postto);
@@ -4617,7 +4614,10 @@ em_utils_reply_to_message (EMsgComposer *composer,
                        break;
        }
 
-       composer_set_body (composer, message, style, parts_list);
+       composer_set_body (composer, message, style, parts_list, &used_part_list);
+
+       e_msg_composer_add_attachments_from_part_list (composer, used_part_list, TRUE);
+       g_clear_object (&used_part_list);
 
        if (folder)
                emu_set_source_headers (composer, folder, message_uid, flags);
diff --git a/src/mail/em-utils.c b/src/mail/em-utils.c
index acc8c70854..1be0785b12 100644
--- a/src/mail/em-utils.c
+++ b/src/mail/em-utils.c
@@ -1223,12 +1223,13 @@ is_only_text_part_in_this_level (GList *parts,
 /**
  * em_utils_message_to_html:
  * @session: a #CamelSession
- * @message:
- * @credits:
- * @flags: EMFormatQuote flags
- * @source:
- * @append: Text to append, can be NULL.
- * @validity_found: if not NULL, then here will be set what validities
+ * @message: a #CamelMimeMessage
+ * @credits: (nullable): credits attribution string when quoting, or %NULL
+ * @flags: the %EMFormatQuote flags
+ * @part_list: (nullable): an #EMailPartList
+ * @prepend: (nulalble): text to prepend, or %NULL
+ * @append: (nullable): text to append, or %NULL
+ * @validity_found: (nullable): if not %NULL, then here will be set what validities
  *         had been found during message conversion. Value is a bit OR
  *         of EM_FORMAT_VALIDITY_FOUND_* constants.
  *
@@ -1236,16 +1237,55 @@ is_only_text_part_in_this_level (GList *parts,
  * string is given.
  *
  * Return value: The html version as a NULL terminated string.
+ *
+ * See: em_utils_message_to_html_ex
  **/
 gchar *
 em_utils_message_to_html (CamelSession *session,
                           CamelMimeMessage *message,
                           const gchar *credits,
                           guint32 flags,
-                          EMailPartList *parts_list,
+                          EMailPartList *part_list,
                           const gchar *prepend,
                           const gchar *append,
                           EMailPartValidityFlags *validity_found)
+{
+       return em_utils_message_to_html_ex (session, message, credits, flags, part_list, prepend, append, 
validity_found, NULL);
+}
+
+/**
+ * em_utils_message_to_html_ex:
+ * @session: a #CamelSession
+ * @message: a #CamelMimeMessage
+ * @credits: (nullable): credits attribution string when quoting, or %NULL
+ * @flags: the %EMFormatQuote flags
+ * @part_list: (nullable): an #EMailPartList
+ * @prepend: (nulalble): text to prepend, or %NULL
+ * @append: (nullable): text to append, or %NULL
+ * @validity_found: (nullable): if not %NULL, then here will be set what validities
+ *         had been found during message conversion. Value is a bit OR
+ *         of EM_FORMAT_VALIDITY_FOUND_* constants.
+ * @out_part_list: (nullable): if not %NULL, sets it to the part list being
+ *         used to generate the body. Unref it with g_object_unref(),
+ *         when no longer needed.
+ *
+ * Convert a message to html, quoting if the @credits attribution
+ * string is given.
+ *
+ * Return value: The html version as a NULL terminated string.
+ *
+ * Since: 3.42
+ **/
+gchar *
+em_utils_message_to_html_ex (CamelSession *session,
+                             CamelMimeMessage *message,
+                             const gchar *credits,
+                             guint32 flags,
+                             EMailPartList *part_list,
+                             const gchar *prepend,
+                             const gchar *append,
+                             EMailPartValidityFlags *validity_found,
+                            EMailPartList **out_part_list)
 {
        EMailFormatter *formatter;
        EMailParser *parser = NULL;
@@ -1271,7 +1311,7 @@ em_utils_message_to_html (CamelSession *session,
        e_mail_formatter_update_style (formatter,
                gtk_widget_get_state_flags (GTK_WIDGET (window)));
 
-       if (parts_list == NULL) {
+       if (part_list == NULL) {
                GSettings *settings;
                gchar *charset;
 
@@ -1285,13 +1325,13 @@ em_utils_message_to_html (CamelSession *session,
                g_free (charset);
 
                parser = e_mail_parser_new (session);
-               parts_list = e_mail_parser_parse_sync (parser, NULL, NULL, message, NULL);
+               part_list = e_mail_parser_parse_sync (parser, NULL, NULL, message, NULL);
        } else {
-               g_object_ref (parts_list);
+               g_object_ref (part_list);
        }
 
        /* Return all found validities and possibly show hidden prefer-plain part */
-       e_mail_part_list_queue_parts (parts_list, NULL, &queue);
+       e_mail_part_list_queue_parts (part_list, NULL, &queue);
        head = g_queue_peek_head_link (&queue);
 
        for (link = head; link != NULL; link = g_list_next (link)) {
@@ -1332,16 +1372,19 @@ em_utils_message_to_html (CamelSession *session,
                        stream, prepend, strlen (prepend), NULL, NULL, NULL);
 
        e_mail_formatter_format_sync (
-               formatter, parts_list, stream, 0,
+               formatter, part_list, stream, 0,
                E_MAIL_FORMATTER_MODE_PRINTING, NULL);
        g_object_unref (formatter);
 
        if (hidden_text_html_part != NULL)
                hidden_text_html_part->is_hidden = TRUE;
 
-       g_object_unref (parts_list);
-       if (parser != NULL)
-               g_object_unref (parser);
+       if (out_part_list)
+               *out_part_list = part_list;
+       else
+               g_object_unref (part_list);
+
+       g_clear_object (&parser);
 
        if (append != NULL && *append != '\0')
                g_output_stream_write_all (
diff --git a/src/mail/em-utils.h b/src/mail/em-utils.h
index a258e3430c..ee1bebbf49 100644
--- a/src/mail/em-utils.h
+++ b/src/mail/em-utils.h
@@ -76,10 +76,19 @@ gchar *             em_utils_message_to_html        (CamelSession *session,
                                                 CamelMimeMessage *msg,
                                                 const gchar *credits,
                                                 guint32 flags,
-                                                struct _EMailPartList *parts_list,
+                                                struct _EMailPartList *part_list,
                                                 const gchar *prepend,
                                                 const gchar *append,
                                                 EMailPartValidityFlags *validity_found);
+gchar *                em_utils_message_to_html_ex     (CamelSession *session,
+                                                CamelMimeMessage *message,
+                                                const gchar *credits,
+                                                guint32 flags,
+                                                EMailPartList *part_list,
+                                                const gchar *prepend,
+                                                const gchar *append,
+                                                EMailPartValidityFlags *validity_found,
+                                                EMailPartList **out_part_list);
 
 void           em_utils_empty_trash            (GtkWidget *parent,
                                                 EMailSession *session);


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