[evolution/gnome-3-26] Bug 789648 - Problem viewing .eml attachment



commit 8c1d84744da3ba068c7fd4d3f52539336bf91d3e
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 2 12:04:07 2017 +0100

    Bug 789648 - Problem viewing .eml attachment

 src/em-format/e-mail-parser-application-mbox.c |   94 +++++++++++++++---------
 src/em-format/e-mail-parser-multipart-mixed.c  |   64 +++++++++++++++-
 src/em-format/e-mail-parser.c                  |   76 +++++++++++++++-----
 src/em-format/e-mail-parser.h                  |    5 +
 4 files changed, 182 insertions(+), 57 deletions(-)
---
diff --git a/src/em-format/e-mail-parser-application-mbox.c b/src/em-format/e-mail-parser-application-mbox.c
index c4e9ecd..38dc1ee 100644
--- a/src/em-format/e-mail-parser-application-mbox.c
+++ b/src/em-format/e-mail-parser-application-mbox.c
@@ -40,6 +40,47 @@ static const gchar *parser_mime_types[] = {
        NULL
 };
 
+static void
+empe_app_mbox_add_message (EMailParser *parser,
+                          CamelMimeMessage *message,
+                          gint nth_message,
+                          GString *part_id,
+                          GCancellable *cancellable,
+                          GQueue *out_mail_parts)
+{
+       GQueue work_queue = G_QUEUE_INIT;
+       CamelMimePart *opart;
+       gint old_len;
+
+       old_len = part_id->len;
+
+       g_string_append_printf (part_id, ".mbox.%d", nth_message);
+
+       opart = camel_mime_part_new ();
+       camel_medium_set_content (CAMEL_MEDIUM (opart), CAMEL_DATA_WRAPPER (message));
+       camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (opart), "message/rfc822");
+
+       e_mail_parser_parse_part_as (
+               parser, opart, part_id, "message/rfc822",
+               cancellable, &work_queue);
+
+       /* Wrap every message as attachment */
+       e_mail_parser_wrap_as_attachment (parser, opart, part_id, &work_queue);
+
+       /* Inline all messages in mbox */
+       if (!g_queue_is_empty (&work_queue)) {
+               EMailPart *pp = g_queue_peek_head (&work_queue);
+
+               pp->force_inline = TRUE;
+       }
+
+       e_queue_transfer (&work_queue, out_mail_parts);
+
+       g_string_truncate (part_id, old_len);
+
+       g_object_unref (opart);
+}
+
 static gboolean
 empe_app_mbox_parse (EMailParserExtension *extension,
                      EMailParser *parser,
@@ -51,7 +92,6 @@ empe_app_mbox_parse (EMailParserExtension *extension,
        CamelMimeParser *mime_parser;
        CamelStream *mem_stream;
        CamelMimeParserState state;
-       gint old_len;
        gint messages;
        GError *error = NULL;
 
@@ -90,67 +130,51 @@ empe_app_mbox_parse (EMailParserExtension *extension,
                return TRUE;
        }
 
-       g_object_unref (mem_stream);
-
-       old_len = part_id->len;
-
        /* Extract messages from the mbox. */
        messages = 0;
        state = camel_mime_parser_step (mime_parser, NULL, NULL);
 
        while (state == CAMEL_MIME_PARSER_STATE_FROM) {
-               GQueue work_queue = G_QUEUE_INIT;
                CamelMimeMessage *message;
-               CamelMimePart *opart;
 
                message = camel_mime_message_new ();
-               opart = CAMEL_MIME_PART (message);
 
                if (!camel_mime_part_construct_from_parser_sync (
-                       opart, mime_parser, NULL, NULL)) {
+                       CAMEL_MIME_PART (message), mime_parser, NULL, NULL)) {
                        g_object_unref (message);
                        break;
                }
 
-               g_string_append_printf (part_id, ".mbox.%d", messages);
+               empe_app_mbox_add_message (parser, message, messages, part_id, cancellable, out_mail_parts);
+               messages++;
 
-               opart = camel_mime_part_new ();
-               camel_medium_set_content (CAMEL_MEDIUM (opart), CAMEL_DATA_WRAPPER (message));
-               camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (opart), "message/rfc822");
+               g_object_unref (message);
 
-               e_mail_parser_parse_part_as (
-                       parser, opart, part_id, "message/rfc822",
-                       cancellable, &work_queue);
+               /* Skip past CAMEL_MIME_PARSER_STATE_FROM_END. */
+               camel_mime_parser_step (mime_parser, NULL, NULL);
 
-               /* Wrap every message as attachment */
-               e_mail_parser_wrap_as_attachment (
-                       parser, opart, part_id, &work_queue);
+               state = camel_mime_parser_step (mime_parser, NULL, NULL);
+       }
 
-               /* Inline all messages in mbox */
-               if (!g_queue_is_empty (&work_queue)) {
-                       EMailPart *p = g_queue_peek_head (&work_queue);
+       if (!messages) {
+               CamelMimeMessage *message;
 
-                       p->force_inline = TRUE;
-               }
+               g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, cancellable, NULL);
 
-               e_queue_transfer (&work_queue, out_mail_parts);
+               message = camel_mime_message_new ();
 
-               g_string_truncate (part_id, old_len);
+               if (camel_data_wrapper_construct_from_stream_sync (CAMEL_DATA_WRAPPER (message), mem_stream, 
NULL, NULL)) {
+                       empe_app_mbox_add_message (parser, message, messages, part_id, cancellable, 
out_mail_parts);
+                       messages++;
+               }
 
                g_object_unref (message);
-               g_object_unref (opart);
-
-               /* Skip past CAMEL_MIME_PARSER_STATE_FROM_END. */
-               camel_mime_parser_step (mime_parser, NULL, NULL);
-
-               state = camel_mime_parser_step (mime_parser, NULL, NULL);
-
-               messages++;
        }
 
        g_object_unref (mime_parser);
+       g_object_unref (mem_stream);
 
-       return TRUE;
+       return messages > 0;
 }
 
 static void
diff --git a/src/em-format/e-mail-parser-multipart-mixed.c b/src/em-format/e-mail-parser-multipart-mixed.c
index cc6a023..6d3aefe 100644
--- a/src/em-format/e-mail-parser-multipart-mixed.c
+++ b/src/em-format/e-mail-parser-multipart-mixed.c
@@ -140,12 +140,65 @@ empe_mp_mixed_parse (EMailParserExtension *extension,
 
                g_string_append_printf (part_id, ".mixed.%d", i);
 
-               handled = e_mail_parser_parse_part (
-                       parser, subpart, part_id, cancellable, &work_queue);
+               handled = FALSE;
+               ct = camel_mime_part_get_content_type (subpart);
+               if (ct)
+                       ct = camel_content_type_ref (ct);
+
+               if (!e_mail_parser_get_parsers_for_part (parser, subpart)) {
+                       const gchar *snoop_type;
+                       CamelContentType *snoop_ct = NULL;
+
+                       snoop_type = e_mail_part_snoop_type (subpart);
+                       if (snoop_type)
+                               snoop_ct = camel_content_type_decode (snoop_type);
+
+                       if (snoop_ct && snoop_ct->type && snoop_ct->subtype && (
+                           !ct || g_ascii_strcasecmp (snoop_ct->type, ct->type) != 0 ||
+                           g_ascii_strcasecmp (snoop_ct->subtype, ct->subtype) != 0)) {
+                               CamelStream *mem_stream;
+
+                               mem_stream = camel_stream_mem_new ();
+                               if (camel_data_wrapper_decode_to_stream_sync (
+                                       camel_medium_get_content (CAMEL_MEDIUM (subpart)),
+                                       mem_stream, cancellable, NULL)) {
+                                       CamelMimePart *opart;
+                                       CamelDataWrapper *dw;
+
+                                       g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, cancellable, 
NULL);
+
+                                       opart = camel_mime_part_new ();
+
+                                       dw = camel_data_wrapper_new ();
+                                       camel_data_wrapper_set_mime_type (dw, snoop_type);
+                                       if (camel_data_wrapper_construct_from_stream_sync (dw, mem_stream, 
cancellable, NULL)) {
+                                               camel_medium_set_content (CAMEL_MEDIUM (opart), dw);
+                                               camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (opart), 
snoop_type);
+
+                                               handled = e_mail_parser_parse_part (parser, opart, part_id, 
cancellable, &work_queue);
+                                               if (handled) {
+                                                       camel_content_type_unref (ct);
+                                                       ct = camel_content_type_ref (snoop_ct);
+                                               }
+                                       }
 
-               mail_part = g_queue_peek_head (&work_queue);
+                                       g_object_unref (opart);
+                                       g_object_unref (dw);
+                               }
 
-               ct = camel_mime_part_get_content_type (subpart);
+                               g_object_unref (mem_stream);
+                       }
+
+                       if (snoop_ct)
+                               camel_content_type_unref (snoop_ct);
+               }
+
+               if (!handled) {
+                       handled = e_mail_parser_parse_part (
+                               parser, subpart, part_id, cancellable, &work_queue);
+               }
+
+               mail_part = g_queue_peek_head (&work_queue);
 
                /* Display parts with CID as attachments
                 * (unless they already are attachments).
@@ -178,6 +231,9 @@ empe_mp_mixed_parse (EMailParserExtension *extension,
                e_queue_transfer (&work_queue, out_mail_parts);
 
                g_string_truncate (part_id, len);
+
+               if (ct)
+                       camel_content_type_unref (ct);
        }
 
        return TRUE;
diff --git a/src/em-format/e-mail-parser.c b/src/em-format/e-mail-parser.c
index 1cbbe32..a9a0849 100644
--- a/src/em-format/e-mail-parser.c
+++ b/src/em-format/e-mail-parser.c
@@ -494,6 +494,63 @@ e_mail_parser_parse_finish (EMailParser *parser,
        return g_object_ref (part_list);
 }
 
+GQueue *
+e_mail_parser_get_parsers_for_part (EMailParser *parser,
+                                   CamelMimePart *part)
+{
+       CamelContentType *ct;
+       gchar *mime_type;
+       GQueue *parsers;
+
+       g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
+
+       ct = camel_mime_part_get_content_type (part);
+       if (!ct) {
+               mime_type = (gchar *) "application/vnd.evolution.error";
+       } else {
+               gchar *tmp;
+               tmp = camel_content_type_simple (ct);
+               mime_type = g_ascii_strdown (tmp, -1);
+               g_free (tmp);
+       }
+
+       parsers = e_mail_parser_get_parsers (parser, mime_type);
+
+       if (ct)
+               g_free (mime_type);
+
+       return parsers;
+}
+
+GQueue *
+e_mail_parser_get_parsers (EMailParser *parser,
+                          const gchar *mime_type)
+{
+       EMailExtensionRegistry *reg;
+       EMailParserClass *parser_class;
+       gchar *as_mime_type;
+       GQueue *parsers;
+
+       g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+       if (mime_type)
+               as_mime_type = g_ascii_strdown (mime_type, -1);
+       else
+               as_mime_type = NULL;
+
+       parser_class = E_MAIL_PARSER_GET_CLASS (parser);
+       reg = E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
+
+       parsers = e_mail_extension_registry_get_for_mime_type (reg, as_mime_type);
+       if (!parsers)
+               parsers = e_mail_extension_registry_get_fallback (reg, as_mime_type);
+
+       g_free (as_mime_type);
+
+       return parsers;
+}
+
 gboolean
 e_mail_parser_parse_part (EMailParser *parser,
                           CamelMimePart *part,
@@ -536,26 +593,9 @@ e_mail_parser_parse_part_as (EMailParser *parser,
 {
        GQueue *parsers;
        GList *iter;
-       EMailExtensionRegistry *reg;
-       EMailParserClass *parser_class;
-       gchar *as_mime_type;
        gboolean mime_part_handled = FALSE;
 
-       if (mime_type)
-               as_mime_type = g_ascii_strdown (mime_type, -1);
-       else
-               as_mime_type = NULL;
-
-       parser_class = E_MAIL_PARSER_GET_CLASS (parser);
-       reg = E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
-
-       parsers = e_mail_extension_registry_get_for_mime_type (reg, as_mime_type);
-       if (!parsers) {
-               parsers = e_mail_extension_registry_get_fallback (reg, as_mime_type);
-       }
-
-       if (as_mime_type)
-               g_free (as_mime_type);
+       parsers = e_mail_parser_get_parsers (parser, mime_type);
 
        if (parsers == NULL) {
                e_mail_parser_wrap_as_attachment (
diff --git a/src/em-format/e-mail-parser.h b/src/em-format/e-mail-parser.h
index 1d0c447..9a6ccd3 100644
--- a/src/em-format/e-mail-parser.h
+++ b/src/em-format/e-mail-parser.h
@@ -79,6 +79,11 @@ EMailPartList *      e_mail_parser_parse_finish      (EMailParser *parser,
                                                 GAsyncResult *result,
                                                 GError **error);
 
+GQueue *       e_mail_parser_get_parsers_for_part
+                                               (EMailParser *parser,
+                                                CamelMimePart *part);
+GQueue *       e_mail_parser_get_parsers       (EMailParser *parser,
+                                                const gchar *mime_type);
 gboolean       e_mail_parser_parse_part        (EMailParser *parser,
                                                 CamelMimePart *part,
                                                 GString *part_id,


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