[evolution] I#1729 - Composer: Forward can lost unreferenced attachments with Content-ID



commit 622707b34fc715f82e2e19109a43a34a7ff14e11
Author: Milan Crha <mcrha redhat com>
Date:   Fri Dec 10 09:25:53 2021 +0100

    I#1729 - Composer: Forward can lost unreferenced attachments with Content-ID
    
    Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1729

 src/composer/e-msg-composer.c | 78 +++++++++++++++++++++++++++++++++++++++++++
 src/composer/e-msg-composer.h |  3 +-
 src/e-util/e-html-editor.c    | 70 ++++++++++++++++++++++++++++++++++++++
 src/e-util/e-html-editor.h    |  4 +++
 src/mail/em-composer-utils.c  |  1 +
 5 files changed, 155 insertions(+), 1 deletion(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index ac2cd1ee8f..178ba8e1e4 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -3334,6 +3334,84 @@ e_msg_composer_add_attachments_from_part_list (EMsgComposer *composer,
        g_hash_table_destroy (added_mime_parts);
 }
 
+static void
+e_msg_composer_filter_inline_attachments (EMsgComposer *composer,
+                                         GSList *used_mime_parts) /* CamelMimePart * */
+{
+       GSList *removed_parts = NULL, *link;
+       gboolean been_changed;
+       EHTMLEditor *editor;
+       EContentEditor *content_editor;
+
+       editor = e_msg_composer_get_editor (composer);
+       content_editor = e_html_editor_get_content_editor (editor);
+
+       been_changed = e_content_editor_get_changed (content_editor);
+       e_html_editor_remove_unused_cid_parts (editor, used_mime_parts, &removed_parts);
+
+       for (link = removed_parts; link; link = g_slist_next (link)) {
+               CamelMimePart *mime_part = link->data;
+               e_msg_composer_attach (composer, mime_part);
+       }
+
+       g_slist_free_full (removed_parts, g_object_unref);
+
+       /* This is not a user change */
+       e_content_editor_set_changed (content_editor, been_changed);
+}
+
+static void
+e_mg_composer_got_used_inline_images_cb (GObject *source_object,
+                                        GAsyncResult *result,
+                                        gpointer user_data)
+{
+       EMsgComposer *composer = user_data;
+       EContentEditorContentHash *content_hash;
+
+       content_hash = e_content_editor_get_content_finish (E_CONTENT_EDITOR (source_object), result, NULL);
+       if (content_hash) {
+               GSList *inline_images_parts;
+
+               inline_images_parts = e_content_editor_util_get_content_data (content_hash, 
E_CONTENT_EDITOR_GET_INLINE_IMAGES);
+
+               e_msg_composer_filter_inline_attachments (composer, inline_images_parts);
+
+               g_hash_table_destroy (content_hash);
+       } else {
+               e_msg_composer_filter_inline_attachments (composer, NULL);
+       }
+
+       g_object_unref (composer);
+}
+
+/**
+ * e_msg_composer_check_inline_attachments:
+ * @composer: an #EMsgComposer
+ *
+ * Checks which inline attachments are referenced in the message body
+ * and those which are not referenced are added as regular attachments.
+ *
+ * Since: 3.44
+ **/
+void
+e_msg_composer_check_inline_attachments (EMsgComposer *composer)
+{
+       EHTMLEditor *editor;
+       EContentEditor *content_editor;
+
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+
+       editor = e_msg_composer_get_editor (composer);
+       content_editor = e_html_editor_get_content_editor (editor);
+
+       if (e_content_editor_get_html_mode (content_editor)) {
+               e_content_editor_get_content (content_editor, E_CONTENT_EDITOR_GET_INLINE_IMAGES,
+                       "localhost", NULL, e_mg_composer_got_used_inline_images_cb, g_object_ref (composer));
+       } else {
+               e_msg_composer_filter_inline_attachments (composer, NULL);
+       }
+}
+
 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 2e4657b35d..fbbf6bea95 100644
--- a/src/composer/e-msg-composer.h
+++ b/src/composer/e-msg-composer.h
@@ -191,7 +191,8 @@ void                e_msg_composer_add_attachments_from_part_list
                                                (EMsgComposer *composer,
                                                 EMailPartList *part_list,
                                                 gboolean just_inlines);
-
+void           e_msg_composer_check_inline_attachments
+                                               (EMsgComposer *composer);
 
 void           e_msg_composer_request_close    (EMsgComposer *composer);
 gboolean       e_msg_composer_can_close        (EMsgComposer *composer,
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index e4cdd319b1..04a6434a6e 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -1751,6 +1751,76 @@ e_html_editor_remove_all_cid_parts (EHTMLEditor *editor)
        g_hash_table_remove_all (editor->priv->cid_parts);
 }
 
+typedef struct _RemoveUnusedCidPartsData {
+       GHashTable *used_hash; /* CamelMimePart * ~> NULL */
+       GSList **out_removed_mime_parts;
+} RemoveUnusedCidPartsData;
+
+static gboolean
+remove_unused_cid_parts_cb (gpointer key,
+                           gpointer value,
+                           gpointer user_data)
+{
+       RemoveUnusedCidPartsData *data = user_data;
+       CamelMimePart *mime_part = value;
+       gboolean remove;
+
+       remove = !data->used_hash || !g_hash_table_contains (data->used_hash, mime_part);
+
+       if (remove && data->out_removed_mime_parts)
+               *data->out_removed_mime_parts = g_slist_prepend (*data->out_removed_mime_parts, g_object_ref 
(mime_part));
+
+       return remove;
+}
+
+/**
+ * e_html_editor_remove_unused_cid_parts:
+ * @editor: an #EHTMLEditor
+ * @used_mime_parts: (nullable) (element-type CamelMimePart): list of used CamelMimePart-s to keep
+ * @out_removed_mime_parts: (out) (optional) (element-type CamelMimePart) (transfer full): list of removed 
parts
+ *
+ * Traverses the list of "cid:" parts and removes all which are not part
+ * of the @used_mime_parts.
+ *
+ * The optional @out_removed_mime_parts is filled with the removed parts.
+ * Free it with g_slist_free_full (list, g_object_unref);, when no longer needed.
+ *
+ * Since: 3.44
+ **/
+void
+e_html_editor_remove_unused_cid_parts (EHTMLEditor *editor,
+                                      GSList *used_mime_parts,
+                                      GSList **out_removed_mime_parts)
+{
+       RemoveUnusedCidPartsData data;
+
+       g_return_if_fail (E_IS_HTML_EDITOR (editor));
+
+       if (out_removed_mime_parts)
+               *out_removed_mime_parts = NULL;
+
+       data.used_hash = NULL;
+       data.out_removed_mime_parts = out_removed_mime_parts;
+
+       if (used_mime_parts) {
+               GSList *link;
+
+               data.used_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+               for (link = used_mime_parts; link; link = g_slist_next (link)) {
+                       g_hash_table_insert (data.used_hash, link->data, NULL);
+               }
+       }
+
+       g_hash_table_foreach_remove (editor->priv->cid_parts, remove_unused_cid_parts_cb, &data);
+
+       if (data.used_hash)
+               g_hash_table_destroy (data.used_hash);
+
+       if (out_removed_mime_parts)
+               *out_removed_mime_parts = g_slist_reverse (*out_removed_mime_parts);
+}
+
 /**
  * e_html_editor_ref_cid_part:
  * @editor: an #EHTMLEditor
diff --git a/src/e-util/e-html-editor.h b/src/e-util/e-html-editor.h
index 8be1af19ea..b96ab542f9 100644
--- a/src/e-util/e-html-editor.h
+++ b/src/e-util/e-html-editor.h
@@ -120,6 +120,10 @@ void               e_html_editor_add_cid_part      (EHTMLEditor *editor,
                                                 CamelMimePart *mime_part);
 void           e_html_editor_remove_cid_part   (EHTMLEditor *editor,
                                                 const gchar *cid_uri);
+void           e_html_editor_remove_unused_cid_parts
+                                               (EHTMLEditor *editor,
+                                                GSList *used_mime_parts, /*  CamelMimePart * */
+                                                GSList **out_removed_mime_parts); /*  CamelMimePart * */
 void           e_html_editor_remove_all_cid_parts
                                                (EHTMLEditor *editor);
 CamelMimePart * e_html_editor_ref_cid_part     (EHTMLEditor *editor,
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index 1f9a7ee41a..a54d72dee9 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -2573,6 +2573,7 @@ forward_non_attached (EMsgComposer *composer,
                emu_set_source_headers (composer, folder, uid, CAMEL_MESSAGE_FORWARDED);
 
                emu_update_composers_security (composer, validity_found);
+               e_msg_composer_check_inline_attachments (composer);
                composer_set_no_change (composer);
                gtk_widget_show (GTK_WIDGET (composer));
 


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