[balsa] Fix handling of Multipart/Related



commit 5053850ac66ec918d0b47d45fb6a04bcaf2d55ed
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Sun Nov 17 21:45:36 2019 -0500

    Fix handling of Multipart/Related
    
    * libbalsa/body.[ch]: implement a new helper function
      libbalsa_message_body_mp_related_root() returning the root object
      of a multipart/related;
    * libbalsa/html.c: pass the HTML body to the Webkit callbacks
      when printing;
    * src/balsa-message.c: use the new helper for fetching the
      multipart/related root object;
    * src/print-gtk.c: properly handle multipart/related

 ChangeLog           | 13 +++++++++++++
 libbalsa/body.c     | 41 +++++++++++++++++++++++++++++++++++++++++
 libbalsa/body.h     |  1 +
 libbalsa/html.c     |  1 +
 src/balsa-message.c |  5 ++---
 src/print-gtk.c     |  5 +++++
 6 files changed, 63 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index adc14db01..0cd7a4be6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2019-11-17  Albrecht Dreß  <albrecht dress arcor de>
+
+       Fix handling of Multipart/Related
+
+       * libbalsa/body.[ch]: implement a new helper function
+         libbalsa_message_body_mp_related_root() returning the root object
+         of a multipart/related;
+       * libbalsa/html.c: pass the HTML body to the Webkit callbacks
+         when printing;
+       * src/balsa-message.c: use the new helper for fetching the
+         multipart/related root object;
+       * src/print-gtk.c: properly handle multipart/related
+
 2019-11-14  Albrecht Dreß  <albrecht dress arcor de>
 
        Display S/MIME and TLS certificate chains
diff --git a/libbalsa/body.c b/libbalsa/body.c
index 996f61be6..35acc0275 100644
--- a/libbalsa/body.c
+++ b/libbalsa/body.c
@@ -886,6 +886,47 @@ libbalsa_message_body_get_by_id(LibBalsaMessageBody * body,
     return libbalsa_message_body_get_by_id(body->next, id);
 }
 
+/** @brief Find the root object of a multipart/related
+ *
+ * @param body multipart/related body
+ * @return the root part
+ *
+ * A multipart/related (typical case: a HTML with inlined images) @em may have a "start" Content-Type 
parameter, indicating the
+ * Content-ID of the part containing the "root" of the compound object.  If the parameter is missing, the 
root object is the very
+ * first child of the container (see RFC 2387, Sect. 3.2).
+ *
+ * RFC 2387, Sect. 3.1 defines that the multipart/related @em must have a "type" parameter, giving the 
Content-Type of the root
+ * object, but in practice it is often omitted.
+ */
+LibBalsaMessageBody *
+libbalsa_message_body_mp_related_root(LibBalsaMessageBody *body)
+{
+       gchar *conttype;
+       LibBalsaMessageBody *root_body = NULL;
+
+    /* note: checking for a non-NULL body and for the proper content-type is somewhat paranoid... */
+    g_return_val_if_fail(body != NULL, NULL);
+
+    conttype = libbalsa_message_body_get_mime_type(body);
+    if (strcmp(conttype, "multipart/related") == 0) {
+               gchar *start_cont_id;
+
+               /* get the "start" parameter, and identify matching child */
+               start_cont_id = libbalsa_message_body_get_parameter(body, "start");
+               if ((start_cont_id != NULL) && (body->parts != NULL)) {
+                       root_body = libbalsa_message_body_get_by_id(body->parts, start_cont_id);
+               }
+               g_free(start_cont_id);
+
+               /* fall back to first child if either the parameter is missing or if the child cannot be 
identified */
+               if (root_body == NULL) {
+                       root_body = body->parts;
+               }
+    }
+    g_free(conttype);
+    return root_body;
+}
+
 LibBalsaMsgProtectState
 libbalsa_message_body_protect_state(const LibBalsaMessageBody *body)
 {
diff --git a/libbalsa/body.h b/libbalsa/body.h
index 765eb37de..acc2bb94e 100644
--- a/libbalsa/body.h
+++ b/libbalsa/body.h
@@ -130,6 +130,7 @@ gboolean libbalsa_message_body_is_delsp(LibBalsaMessageBody * body);
 LibBalsaMessageBody *libbalsa_message_body_get_by_id(LibBalsaMessageBody *
                                                      body,
                                                      const gchar * id);
+LibBalsaMessageBody *libbalsa_message_body_mp_related_root(LibBalsaMessageBody *body);
 
 LibBalsaMsgProtectState libbalsa_message_body_protect_state(const LibBalsaMessageBody *body);
 gboolean libbalsa_message_body_multipart_signed(const LibBalsaMessageBody *body);
diff --git a/libbalsa/html.c b/libbalsa/html.c
index 3d9f5dc14..891ad9baf 100644
--- a/libbalsa/html.c
+++ b/libbalsa/html.c
@@ -703,6 +703,7 @@ libbalsa_html_print_bitmap(LibBalsaMessageBody *body,
     have_src_oth = g_regex_match_simple(SRC_REGEX, text, G_REGEX_CASELESS, 0);
 
     info = g_new0(LibBalsaWebKitInfo, 1);
+    info->body = body;
        offline_window = gtk_offscreen_window_new();
        render_width = (gint) (width * HTML_PRINT_DPI / 72.0);
        g_debug("%s: request Cairo width %g, render width %d", __func__, width, render_width);
diff --git a/src/balsa-message.c b/src/balsa-message.c
index 0790be0ac..b52001d95 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -2176,9 +2176,8 @@ add_multipart(BalsaMessage *balsa_message, LibBalsaMessageBody *body,
     type=g_mime_content_type_new_from_string(body->content_type);
 
     if (g_mime_content_type_is_type(type, "multipart", "related")) {
-        /* FIXME: more processing required see RFC1872 */
-        /* Add the first part */
-        body = add_body(balsa_message, body->parts, container);
+        /* add the compound object root part */
+        body = add_body(balsa_message, libbalsa_message_body_mp_related_root(body), container);
     } else if (g_mime_content_type_is_type(type, "multipart", "alternative")) {
             /* Add the most suitable part. */
         body = add_body(balsa_message, preferred_part(body->parts), container);
diff --git a/src/print-gtk.c b/src/print-gtk.c
index 14a66edbb..910f399de 100644
--- a/src/print-gtk.c
+++ b/src/print-gtk.c
@@ -242,6 +242,11 @@ scan_body(GList *bpo_list, GtkPrintContext * context, BalsaPrintSetup * psetup,
 
                        print_part = find_alt_part(body->parts, psetup->print_alt_html);
                        bpo_list = print_single_part(bpo_list, context, psetup, print_part, no_first_sep, 
add_signature);
+               } else if (g_ascii_strcasecmp(conttype, "multipart/related") == 0) {
+                       /* catch the case of a RFC 2387 multipart/related, typically a text/html with images 
which are enclosed in the
+                        * "related" container */
+                       bpo_list = print_single_part(bpo_list, context, psetup, 
libbalsa_message_body_mp_related_root(body), no_first_sep,
+                               add_signature);
                } else {
                        bpo_list = scan_body(bpo_list, context, psetup, body->parts, no_first_sep);
                }


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