diff options
34 files changed, 725 insertions, 749 deletions
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index 4fa48a717b..5cd9a70f75 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -194,7 +194,7 @@ emcu_part_to_html (CamelSession *session, GString *part_id; EShell *shell; GtkWindow *window; - GSList *list; + GQueue queue = G_QUEUE_INIT; shell = e_shell_get_default (); window = e_shell_get_active_window (shell); @@ -207,13 +207,12 @@ emcu_part_to_html (CamelSession *session, part_id = g_string_sized_new (0); parser = e_mail_parser_new (session); - list = e_mail_parser_parse_part (parser, part, part_id, cancellable); - while (list != NULL) { - if (list->data != NULL) { - e_mail_part_list_add_part (part_list, list->data); - e_mail_part_unref (list->data); - } - list = g_slist_delete_link (list, list); + e_mail_parser_parse_part ( + parser, part, part_id, cancellable, &queue); + while (!g_queue_is_empty (&queue)) { + EMailPart *mail_part = g_queue_pop_head (&queue); + e_mail_part_list_add_part (part_list, mail_part); + e_mail_part_unref (mail_part); } g_string_free (part_id, TRUE); g_object_unref (parser); diff --git a/em-format/e-mail-parser-application-mbox.c b/em-format/e-mail-parser-application-mbox.c index fb901afdea..35eedf9a5e 100644 --- a/em-format/e-mail-parser-application-mbox.c +++ b/em-format/e-mail-parser-application-mbox.c @@ -60,24 +60,21 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "application/mbox", NULL }; -static GSList * +static gboolean empe_app_mbox_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMimeParser *mime_parser; CamelStream *mem_stream; camel_mime_parser_state_t state; gint old_len; gint messages; - GSList *parts; GError *error = NULL; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - /* Extract messages from the application/mbox part and * render them as a flat list of messages. */ @@ -103,14 +100,14 @@ empe_app_mbox_parse (EMailParserExtension *extension, camel_mime_parser_init_with_stream (mime_parser, mem_stream, &error); if (error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Error parsing MBOX part: %s"), error->message); g_object_unref (mem_stream); g_object_unref (mime_parser); g_error_free (error); - return parts; + return TRUE; } g_object_unref (mem_stream); @@ -121,11 +118,10 @@ empe_app_mbox_parse (EMailParserExtension *extension, messages = 0; state = camel_mime_parser_step (mime_parser, NULL, NULL); - parts = NULL; while (state == CAMEL_MIME_PARSER_STATE_FROM) { + GQueue work_queue = G_QUEUE_INIT; CamelMimeMessage *message; CamelMimePart *opart; - GSList *new_parts; message = camel_mime_message_new (); opart = CAMEL_MIME_PART (message); @@ -142,23 +138,22 @@ empe_app_mbox_parse (EMailParserExtension *extension, camel_medium_set_content (CAMEL_MEDIUM (opart), CAMEL_DATA_WRAPPER (message)); camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (opart), "message/rfc822"); - new_parts = e_mail_parser_parse_part_as ( - parser, opart, - part_id, "message/rfc822", cancellable); + e_mail_parser_parse_part_as ( + parser, opart, part_id, "message/rfc822", + cancellable, &work_queue); /* Wrap every message as attachment */ - new_parts = e_mail_parser_wrap_as_attachment ( - parser, opart, - new_parts, part_id, cancellable); + e_mail_parser_wrap_as_attachment ( + parser, opart, part_id, &work_queue); /* Inline all messages in mbox */ - if (new_parts && new_parts->data) { - EMailPart *p = new_parts->data; + if (!g_queue_is_empty (&work_queue)) { + EMailPart *p = g_queue_peek_head (&work_queue); p->force_inline = TRUE; } - parts = g_slist_concat (parts, new_parts); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, old_len); @@ -175,7 +170,7 @@ empe_app_mbox_parse (EMailParserExtension *extension, g_object_unref (mime_parser); - return parts; + return TRUE; } static guint32 diff --git a/em-format/e-mail-parser-application-smime.c b/em-format/e-mail-parser-application-smime.c index 9fbf24e3ff..919af9d1f2 100644 --- a/em-format/e-mail-parser-application-smime.c +++ b/em-format/e-mail-parser-application-smime.c @@ -65,28 +65,25 @@ static const gchar * parser_mime_types[] = { "application/xpkcs7mime", "application/x-pkcs7-signature", NULL }; -static GSList * +static gboolean empe_app_smime_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelCipherContext *context; CamelMimePart *opart; CamelCipherValidity *valid; GError *local_error = NULL; - GSList *parts, *iter; CamelContentType *ct; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - ct = camel_mime_part_get_content_type (part); if (camel_content_type_is (ct, "application", "pkcs7-signature") || camel_content_type_is (ct, "application", "xpkcs7-signature") || camel_content_type_is (ct, "application", "x-pkcs7-signature")) { - return g_slist_alloc (); + return TRUE; } context = camel_smime_context_new (e_mail_parser_get_session (parser)); @@ -99,58 +96,60 @@ empe_app_smime_parse (EMailParserExtension *extension, e_mail_part_preserve_charset_in_content_type (part, opart); if (local_error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Could not parse S/MIME message: %s"), local_error->message); g_error_free (local_error); } else { + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; gint len = part_id->len; g_string_append (part_id, ".encrypted"); - parts = e_mail_parser_parse_part ( - parser, opart, part_id, cancellable); + e_mail_parser_parse_part ( + parser, opart, part_id, cancellable, &work_queue); g_string_truncate (part_id, len); - /* Update validity flags of all the involved subp-arts */ - for (iter = parts; iter; iter = iter->next) { + head = g_queue_peek_head_link (&work_queue); - EMailPart *mail_part = iter->data; - if (!mail_part) - continue; + /* Update validity flags of all the involved subp-arts */ + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_ENCRYPTED | E_MAIL_PART_VALIDITY_SMIME); - } - /* Add a widget with details about the encryption, but only when - * the encrypted isn't itself secured, in that case it has created - * the button itself */ + e_queue_transfer (&work_queue, out_mail_parts); + + /* Add a widget with details about the encryption, but only + * when the encrypted isn't itself secured, in that case it + * has created the button itself. */ if (!e_mail_part_is_secured (opart)) { - GSList *button; EMailPart *mail_part; + g_string_append (part_id, ".encrypted.button"); - button = e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.widget.secure-button", - cancellable); - if (button && button->data) { - mail_part = button->data; + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.widget.secure-button", + cancellable, &work_queue); + + mail_part = g_queue_peek_head (&work_queue); + if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_ENCRYPTED | E_MAIL_PART_VALIDITY_SMIME); - } - parts = g_slist_concat (parts, button); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } @@ -161,7 +160,7 @@ empe_app_smime_parse (EMailParserExtension *extension, g_object_unref (opart); g_object_unref (context); - return parts; + return TRUE; } static guint32 diff --git a/em-format/e-mail-parser-attachment-bar.c b/em-format/e-mail-parser-attachment-bar.c index 5df1afa7a1..f8c45fb327 100644 --- a/em-format/e-mail-parser-attachment-bar.c +++ b/em-format/e-mail-parser-attachment-bar.c @@ -67,12 +67,13 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar *parser_mime_types[] = { "application/vnd.evolution.widget.attachment-bar", NULL }; -static GSList * +static gboolean empe_attachment_bar_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPartAttachmentBar *empab; gint len; @@ -80,13 +81,15 @@ empe_attachment_bar_parse (EMailParserExtension *extension, len = part_id->len; g_string_append (part_id, ".attachment-bar"); empab = (EMailPartAttachmentBar *) e_mail_part_subclass_new ( - part, part_id->str, sizeof (EMailPartAttachmentBar), - (GFreeFunc) mail_part_attachment_bar_free); + part, part_id->str, sizeof (EMailPartAttachmentBar), + (GFreeFunc) mail_part_attachment_bar_free); empab->parent.mime_type = g_strdup ("application/vnd.evolution.widget.attachment-bar"); empab->store = E_ATTACHMENT_STORE (e_attachment_store_new ()); g_string_truncate (part_id, len); - return g_slist_append (NULL, empab); + g_queue_push_tail (out_mail_parts, empab); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-extension.c b/em-format/e-mail-parser-extension.c index 72f1fd8445..df8fc54dcb 100644 --- a/em-format/e-mail-parser-extension.c +++ b/em-format/e-mail-parser-extension.c @@ -52,18 +52,20 @@ e_mail_parser_extension_default_init (EMailParserExtensionInterface *interface) * @part_id: a #GString to which parser will append ID of the parsed part. * @flags: #EMailParserFlags * @cancellable: (allow-none) A #GCancellable + * @out_mail_parts: a #GQueue to deposit #EMailPart instances * * A virtual function reimplemented in all mail parser extensions. The function - * decodes and parses the @mime_part, creating one or more #EMailPart<!-//>s. + * decodes and parses the @mime_part, appending one or more #EMailPart<!-//>s + * to the @out_mail_parts queue. * - * When the function is unable to parse the @mime_part (either because it's broken - * or because it is a different mimetype then the extension is specialized for), the - * function will return @NULL indicating the #EMailParser, that it should pick - * another extension. + * When the function is unable to parse the @mime_part (either because it's + * broken or because it is a different MIME type then the extension is + * specialized for), the function will return %FALSE to indicate to the + * #EMailParser that it should pick another extension. * - * When the @mime_part contains for example multipart/mixed of one RFC822 message - * with an attachment and of one image, then parser must make sure that the - * returned #GSList is correctly ordered: + * When the @mime_part contains for example multipart/mixed of one RFC822 + * message with an attachment and of one image, then parser must make sure + * that parts are appeded to @out_mail_parts in the correct order. * * part1.rfc822.plain_text * part1.rfc822.attachment @@ -71,25 +73,33 @@ e_mail_parser_extension_default_init (EMailParserExtensionInterface *interface) * * Implementation of this function must be thread-safe. * - * Return value: Returns #GSList of #EMailPart<!-//>s when the part was succesfully - * parsed, returns @NULL when the parser is not able to parse the part. + * Returns: %TRUE if the @mime_part was handled (even if no + * #EMailPart<!-//>s were added to @out_mail_parts), or + * %FALSE if the @mime_part was not handled */ -GSList * +gboolean e_mail_parser_extension_parse (EMailParserExtension *extension, - EMailParser *parser, - CamelMimePart *mime_part, - GString *part_id, - GCancellable *cancellable) + EMailParser *parser, + CamelMimePart *mime_part, + GString *part_id, + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailParserExtensionInterface *interface; - g_return_val_if_fail (E_IS_MAIL_PARSER_EXTENSION (extension), NULL); - g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL); + g_return_val_if_fail (E_IS_MAIL_PARSER_EXTENSION (extension), FALSE); + g_return_val_if_fail (E_IS_MAIL_PARSER (parser), FALSE); interface = E_MAIL_PARSER_EXTENSION_GET_INTERFACE (extension); - g_return_val_if_fail (interface->parse != NULL, NULL); + g_return_val_if_fail (interface->parse != NULL, FALSE); - return interface->parse (extension, parser, mime_part, part_id, cancellable); + /* Check for cancellation before calling the method. */ + if (g_cancellable_is_cancelled (cancellable)) + return FALSE; + + return interface->parse ( + extension, parser, mime_part, part_id, + cancellable, out_mail_parts); } guint32 diff --git a/em-format/e-mail-parser-extension.h b/em-format/e-mail-parser-extension.h index 101c1320dc..e5acece68e 100644 --- a/em-format/e-mail-parser-extension.h +++ b/em-format/e-mail-parser-extension.h @@ -68,11 +68,12 @@ typedef enum { struct _EMailParserExtensionInterface { EMailExtensionInterface parent_interface; - GSList * (*parse) (EMailParserExtension *extension, + gboolean (*parse) (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *mime_part, GString *part_id, - GCancellable *cancellable); + GCancellable *cancellable, + GQueue *out_mail_parts); guint32 (*get_flags) (EMailParserExtension *extension); @@ -80,11 +81,12 @@ struct _EMailParserExtensionInterface { GType e_mail_parser_extension_get_type (void) G_GNUC_CONST; -GSList * e_mail_parser_extension_parse (EMailParserExtension *extension, +gboolean e_mail_parser_extension_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *mime_part, GString *part_id, - GCancellable *cancellable); + GCancellable *cancellable, + GQueue *out_mail_parts); guint32 e_mail_parser_extension_get_flags (EMailParserExtension *extension); diff --git a/em-format/e-mail-parser-headers.c b/em-format/e-mail-parser-headers.c index c66563aef1..edb6de4407 100644 --- a/em-format/e-mail-parser-headers.c +++ b/em-format/e-mail-parser-headers.c @@ -88,19 +88,17 @@ empe_headers_bind_dom (EMailPart *part, g_free (uri); } -static GSList * +static gboolean empe_headers_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPart *mail_part; gint len; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - len = part_id->len; g_string_append (part_id, ".headers"); @@ -109,7 +107,9 @@ empe_headers_parse (EMailParserExtension *extension, mail_part->bind_func = empe_headers_bind_dom; g_string_truncate (part_id, len); - return g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-image.c b/em-format/e-mail-parser-image.c index b252714215..12242746f2 100644 --- a/em-format/e-mail-parser-image.c +++ b/em-format/e-mail-parser-image.c @@ -71,22 +71,21 @@ static const gchar *parser_mime_types[] = { "image/gif", "image/pjpeg", NULL }; -static GSList * +static gboolean empe_image_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { + GQueue work_queue = G_QUEUE_INIT; EMailPart *mail_part; const gchar *tmp; gchar *cid; gint len; CamelContentType *ct; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - tmp = camel_mime_part_get_content_id (part); if (tmp) { cid = g_strdup_printf ("cid:%s", tmp); @@ -107,13 +106,15 @@ empe_image_parse (EMailParserExtension *extension, g_string_truncate (part_id, len); - if (!cid) { - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, mail_part), - part_id, cancellable); - } + g_queue_push_tail (&work_queue, mail_part); + + if (cid == NULL) + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); - return g_slist_append (NULL, mail_part); + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-inlinepgp-encrypted.c b/em-format/e-mail-parser-inlinepgp-encrypted.c index 3a61a5eeff..ce3f372cc1 100644 --- a/em-format/e-mail-parser-inlinepgp-encrypted.c +++ b/em-format/e-mail-parser-inlinepgp-encrypted.c @@ -58,12 +58,13 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "application/x-inlinepgp-encrypted", NULL }; -static GSList * +static gboolean empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelCipherContext *cipher; CamelCipherValidity *valid; @@ -71,11 +72,9 @@ empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, CamelDataWrapper *dw; gchar *mime_type; gint len; + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; GError *local_error = NULL; - GSList *parts, *iter; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; cipher = camel_gpg_context_new (e_mail_parser_get_session (parser)); @@ -86,22 +85,21 @@ empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, cipher, part, opart, cancellable, &local_error); if (local_error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Could not parse PGP message: %s"), local_error->message); g_error_free (local_error); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as (parser, - part, part_id, - "application/vnd.evolution.source", - cancellable)); + e_mail_parser_parse_part_as (parser, + part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); g_object_unref (cipher); g_object_unref (opart); - return parts; + + return TRUE; } dw = camel_medium_get_content ((CamelMedium *) opart); @@ -122,18 +120,17 @@ empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, len = part_id->len; g_string_append (part_id, ".inlinepgp_encrypted"); - parts = e_mail_parser_parse_part_as ( - parser, opart, part_id, - camel_data_wrapper_get_mime_type (dw), cancellable); + e_mail_parser_parse_part_as ( + parser, opart, part_id, + camel_data_wrapper_get_mime_type (dw), + cancellable, &work_queue); g_string_truncate (part_id, len); - for (iter = parts; iter; iter = iter->next) { - EMailPart *mail_part; + head = g_queue_peek_head_link (&work_queue); - mail_part = iter->data; - if (!mail_part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, @@ -141,28 +138,29 @@ empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, E_MAIL_PART_VALIDITY_PGP); } + e_queue_transfer (&work_queue, out_mail_parts); + /* Add a widget with details about the encryption, but only when * the encrypted isn't itself secured, in that case it has created * the button itself */ if (!e_mail_part_is_secured (opart)) { - GSList *button; EMailPart *mail_part; + g_string_append (part_id, ".inlinepgp_encrypted.button"); - button = e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.widget.secure-button", - cancellable); - if (button && button->data) { - mail_part = button->data; + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.widget.secure-button", + cancellable, &work_queue); + mail_part = g_queue_peek_head (&work_queue); + if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_ENCRYPTED | E_MAIL_PART_VALIDITY_PGP); - } - parts = g_slist_concat (parts, button); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } @@ -172,7 +170,7 @@ empe_inlinepgp_encrypted_parse (EMailParserExtension *extension, g_object_unref (opart); g_object_unref (cipher); - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-inlinepgp-signed.c b/em-format/e-mail-parser-inlinepgp-signed.c index 23461299d9..723acc23cf 100644 --- a/em-format/e-mail-parser-inlinepgp-signed.c +++ b/em-format/e-mail-parser-inlinepgp-signed.c @@ -58,12 +58,13 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "application/x-inlinepgp-signed", NULL }; -static GSList * +static gboolean empe_inlinepgp_signed_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelStream *filtered_stream; CamelMimeFilterPgp *pgp_filter; @@ -73,14 +74,12 @@ empe_inlinepgp_signed_parse (EMailParserExtension *extension, CamelDataWrapper *dw; CamelMimePart *opart; CamelStream *ostream; + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; gchar *type; gint len; GError *local_error = NULL; GByteArray *ba; - GSList *parts, *iter; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; cipher = camel_gpg_context_new (e_mail_parser_get_session (parser)); @@ -89,22 +88,21 @@ empe_inlinepgp_signed_parse (EMailParserExtension *extension, cipher, part, cancellable, &local_error); if (local_error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Error verifying signature: %s"), local_error->message); g_error_free (local_error); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", - cancellable)); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); g_object_unref (cipher); - return parts; + + return TRUE; } /* Setup output stream */ @@ -147,15 +145,13 @@ empe_inlinepgp_signed_parse (EMailParserExtension *extension, len = part_id->len; g_string_append (part_id, ".inlinepgp_signed"); - parts = e_mail_parser_parse_part ( - parser, opart, part_id, cancellable); + e_mail_parser_parse_part ( + parser, opart, part_id, cancellable, &work_queue); - for (iter = parts; iter; iter = iter->next) { - EMailPart *mail_part; + head = g_queue_peek_head_link (&work_queue); - mail_part = iter->data; - if (!mail_part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, @@ -163,30 +159,31 @@ empe_inlinepgp_signed_parse (EMailParserExtension *extension, E_MAIL_PART_VALIDITY_PGP); } + e_queue_transfer (&work_queue, out_mail_parts); + g_string_truncate (part_id, len); /* Add a widget with details about the encryption, but only when * the encrypted isn't itself secured, in that case it has created * the button itself */ if (!e_mail_part_is_secured (opart)) { - GSList *button; EMailPart *mail_part; + g_string_append (part_id, ".inlinepgp_signed.button"); - button = e_mail_parser_parse_part_as ( + e_mail_parser_parse_part_as ( parser, part, part_id, "application/vnd.evolution.widget.secure-button", - cancellable); - if (button && button->data) { - mail_part = button->data; + cancellable, &work_queue); + mail_part = g_queue_peek_head (&work_queue); + if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_SIGNED | E_MAIL_PART_VALIDITY_PGP); - } - parts = g_slist_concat (parts, button); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } @@ -197,7 +194,7 @@ empe_inlinepgp_signed_parse (EMailParserExtension *extension, g_object_unref (ostream); g_object_unref (cipher); - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-message-deliverystatus.c b/em-format/e-mail-parser-message-deliverystatus.c index 3a86a9380e..f219a9745c 100644 --- a/em-format/e-mail-parser-message-deliverystatus.c +++ b/em-format/e-mail-parser-message-deliverystatus.c @@ -60,19 +60,18 @@ static const gchar * parser_mime_types[] = { "message/delivery-status", "message/disposition-notification", NULL }; -static GSList * +static gboolean empe_msg_deliverystatus_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { + GQueue work_queue = G_QUEUE_INIT; EMailPart *mail_part; gsize len; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - len = part_id->len; g_string_append (part_id, ".delivery-status"); mail_part = e_mail_part_new (part, part_id->str); @@ -80,11 +79,15 @@ empe_msg_deliverystatus_parse (EMailParserExtension *extension, g_string_truncate (part_id, len); + g_queue_push_tail (&work_queue, mail_part); + /* The only reason for having a separate parser for * message/delivery-status is to display the part as an attachment */ - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, mail_part), - part_id, cancellable); + e_mail_parser_wrap_as_attachment (parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-message-external.c b/em-format/e-mail-parser-message-external.c index 99b6b8bd57..5768e6e34c 100644 --- a/em-format/e-mail-parser-message-external.c +++ b/em-format/e-mail-parser-message-external.c @@ -58,12 +58,13 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "message/external-body", NULL }; -static GSList * +static gboolean empe_msg_external_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPart *mail_part; CamelMimePart *newpart; @@ -74,9 +75,6 @@ empe_msg_external_parse (EMailParserExtension *extension, gint len; gchar *mime_type; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - newpart = camel_mime_part_new (); /* needs to be cleaner */ @@ -177,7 +175,9 @@ addPart: mail_part->mime_type = mime_type; g_string_truncate (part_id, len); - return g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-message-rfc822.c b/em-format/e-mail-parser-message-rfc822.c index 4632c6e0eb..70bf8c89ed 100644 --- a/em-format/e-mail-parser-message-rfc822.c +++ b/em-format/e-mail-parser-message-rfc822.c @@ -62,14 +62,14 @@ static const gchar * parser_mime_types[] = { "message/rfc822", "message/news", NULL }; -static GSList * +static gboolean empe_msg_rfc822_parse (EMailParserExtension *extension, EMailParser *eparser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - GSList *parts = NULL; EMailPart *mail_part; gint len; CamelMimePart *message; @@ -81,13 +81,14 @@ empe_msg_rfc822_parse (EMailParserExtension *extension, len = part_id->len; g_string_append (part_id, ".rfc822"); - /* Create an empty PURI that will represent start of the RFC message */ + /* Create an empty PURI that will represent start of the RFC message */ mail_part = e_mail_part_new (part, part_id->str); mail_part->mime_type = g_strdup ("message/rfc822"); - parts = g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); - /* Sometime the _actual_ message is encapsulated in another CamelMimePart, - * sometimes the CamelMimePart actually represents the RFC822 message */ + /* Sometime the actual message is encapsulated in another + * CamelMimePart, sometimes the CamelMimePart itself represents + * the RFC822 message. */ ct = camel_mime_part_get_content_type (part); if (camel_content_type_is (ct, "message", "rfc822")) { new_stream = camel_stream_mem_new (); @@ -110,28 +111,29 @@ empe_msg_rfc822_parse (EMailParserExtension *extension, message = g_object_ref (part); } - parts = g_slist_concat (parts, e_mail_parser_parse_part_as ( - eparser, message, part_id, - "application/vnd.evolution.message", - cancellable)); + e_mail_parser_parse_part_as ( + eparser, message, part_id, + "application/vnd.evolution.message", + cancellable, out_mail_parts); g_object_unref (message); - /* Add another generic EMailPart that represents end of the RFC message. - * The em_format_write() function will skip all parts between the ".rfc822" - * part and ".rfc822.end" part as they will be rendered in an <iframe> */ + /* Add another generic EMailPart that represents end of the RFC + * message. The em_format_write() function will skip all parts + * between the ".rfc822" part and ".rfc822.end" part as they will + * be rendered in an <iframe>. */ g_string_append (part_id, ".end"); mail_part = e_mail_part_new (message, part_id->str); mail_part->is_hidden = TRUE; - parts = g_slist_append (parts, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); + g_string_truncate (part_id, len); - if (e_mail_part_is_attachment (message)) { - return e_mail_parser_wrap_as_attachment ( - eparser, message, parts, part_id, cancellable); - } + if (e_mail_part_is_attachment (message)) + e_mail_parser_wrap_as_attachment ( + eparser, message, part_id, out_mail_parts); - return parts; + return TRUE; } static guint32 diff --git a/em-format/e-mail-parser-message.c b/em-format/e-mail-parser-message.c index 7b6e6201d5..df7d4b3320 100644 --- a/em-format/e-mail-parser-message.c +++ b/em-format/e-mail-parser-message.c @@ -59,31 +59,28 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar *parser_mime_types[] = { "application/vnd.evolution.message", NULL }; -static GSList * +static gboolean empe_message_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - GSList *parts; CamelContentType *ct; gchar *mime_type; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - /* Headers */ - parts = g_slist_concat (NULL, e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.headers", - cancellable)); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.headers", + cancellable, out_mail_parts); /* Attachment Bar */ - parts = g_slist_concat (parts, e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.widget.attachment-bar", - cancellable)); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.widget.attachment-bar", + cancellable, out_mail_parts); ct = camel_mime_part_get_content_type (part); mime_type = camel_content_type_simple (ct); @@ -103,13 +100,13 @@ empe_message_parse (EMailParserExtension *extension, } /* Actual message body */ - parts = g_slist_concat (parts, e_mail_parser_parse_part_as ( - parser, part, part_id, mime_type, - cancellable)); + e_mail_parser_parse_part_as ( + parser, part, part_id, mime_type, + cancellable, out_mail_parts); g_free (mime_type); - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-multipart-alternative.c b/em-format/e-mail-parser-multipart-alternative.c index 74826da814..de4261bf0c 100644 --- a/em-format/e-mail-parser-multipart-alternative.c +++ b/em-format/e-mail-parser-multipart-alternative.c @@ -65,32 +65,28 @@ related_display_part_is_attachment (CamelMimePart *part) return display_part && e_mail_part_is_attachment (display_part); } -static GSList * +static gboolean empe_mp_alternative_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMultipart *mp; gint i, nparts, bestid = 0; CamelMimePart *best = NULL; - GSList *parts; EMailExtensionRegistry *reg; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - reg = e_mail_parser_get_extension_registry (parser); mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part); - if (!CAMEL_IS_MULTIPART (mp)) { + if (!CAMEL_IS_MULTIPART (mp)) return e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", - cancellable); - } + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); /* as per rfc, find the last part we know how to display */ nparts = camel_multipart_get_number (mp); @@ -103,7 +99,7 @@ empe_mp_alternative_parse (EMailParserExtension *extension, gsize content_size; if (g_cancellable_is_cancelled (cancellable)) - return NULL; + return TRUE; /* is it correct to use the passed in *part here? */ mpart = camel_multipart_get_part (mp, i); @@ -148,16 +144,18 @@ empe_mp_alternative_parse (EMailParserExtension *extension, g_string_append_printf (part_id, ".alternative.%d", bestid); - parts = e_mail_parser_parse_part ( - parser, best, part_id, cancellable); + e_mail_parser_parse_part ( + parser, best, part_id, + cancellable, out_mail_parts); g_string_truncate (part_id, len); } else { - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, "multipart/mixed", cancellable); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); } - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-multipart-appledouble.c b/em-format/e-mail-parser-multipart-appledouble.c index f8e1cf390f..297ded6243 100644 --- a/em-format/e-mail-parser-multipart-appledouble.c +++ b/em-format/e-mail-parser-multipart-appledouble.c @@ -52,26 +52,23 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "multipart/appledouble", NULL }; -static GSList * +static gboolean empe_mp_appledouble_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMultipart *mp; - GSList *parts; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part); if (!CAMEL_IS_MULTIPART (mp)) { - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", - cancellable); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); } else { CamelMimePart *mime_part; mime_part = camel_multipart_get_part (mp, 1); @@ -82,21 +79,21 @@ empe_mp_appledouble_parse (EMailParserExtension *extension, len = part_id->len; g_string_append_printf (part_id, ".appledouble.1"); - parts = e_mail_parser_parse_part ( - parser, mime_part, part_id, cancellable); + e_mail_parser_parse_part ( + parser, mime_part, part_id, + cancellable, out_mail_parts); g_string_truncate (part_id, len); } else { - - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", - cancellable); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); } } - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-multipart-digest.c b/em-format/e-mail-parser-multipart-digest.c index 2acd8ee614..70f5eebda0 100644 --- a/em-format/e-mail-parser-multipart-digest.c +++ b/em-format/e-mail-parser-multipart-digest.c @@ -56,31 +56,27 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "multipart/digest", NULL }; -static GSList * +static gboolean empe_mp_digest_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMultipart *mp; gint i, nparts, len; - GSList *parts; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part); - if (!CAMEL_IS_MULTIPART (mp)) { + if (!CAMEL_IS_MULTIPART (mp)) return e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", cancellable); - } + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); len = part_id->len; nparts = camel_multipart_get_number (mp); - parts = NULL; for (i = 0; i < nparts; i++) { CamelMimePart *subpart; CamelContentType *ct; @@ -99,43 +95,39 @@ empe_mp_digest_parse (EMailParserExtension *extension, if (ct && !camel_content_type_is (ct, "message", "rfc822")) { cts = camel_content_type_simple (ct); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, subpart, part_id, - cts, cancellable)); + e_mail_parser_parse_part_as ( + parser, subpart, part_id, cts, + cancellable, out_mail_parts); g_free (cts); } else { - GSList *new_parts; + GQueue work_queue = G_QUEUE_INIT; + EMailPart *mail_part; + + e_mail_parser_parse_part_as ( + parser, subpart, part_id, "message/rfc822", + cancellable, &work_queue); - new_parts = e_mail_parser_parse_part_as ( - parser, subpart, part_id, - "message/rfc822", cancellable); + mail_part = g_queue_peek_head (&work_queue); /* Force the message to be collapsable */ - if (new_parts && new_parts->data && - !E_MAIL_PART (new_parts->data)->is_attachment) { - new_parts = e_mail_parser_wrap_as_attachment ( - parser, subpart, new_parts, part_id, - cancellable); - } + if (mail_part != NULL && !mail_part->is_attachment) + e_mail_parser_wrap_as_attachment ( + parser, subpart, part_id, &work_queue); + + mail_part = g_queue_peek_head (&work_queue); /* Force the message to be expanded */ - if (new_parts) { - EMailPart *p = new_parts->data; - if (p) { - p->force_inline = TRUE; - } - } - - parts = g_slist_concat (parts, new_parts); + if (mail_part != NULL) + mail_part->force_inline = TRUE; + + e_queue_transfer (&work_queue, out_mail_parts); } g_string_truncate (part_id, len); } - return parts; + return TRUE; } static guint32 diff --git a/em-format/e-mail-parser-multipart-encrypted.c b/em-format/e-mail-parser-multipart-encrypted.c index db417fabbf..fedef393ef 100644 --- a/em-format/e-mail-parser-multipart-encrypted.c +++ b/em-format/e-mail-parser-multipart-encrypted.c @@ -28,6 +28,7 @@ #include <glib/gi18n-lib.h> #include <camel/camel.h> +#include <libedataserver/libedataserver.h> typedef struct _EMailParserMultipartEncrypted { GObject parent; @@ -54,56 +55,50 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "multipart/encrypted", NULL }; -static GSList * +static gboolean empe_mp_encrypted_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelCipherContext *context; const gchar *protocol; CamelMimePart *opart; CamelCipherValidity *valid; CamelMultipartEncrypted *mpe; + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; GError *local_error = NULL; - GSList *parts; gint len; - GSList *iter; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; mpe = (CamelMultipartEncrypted *) camel_medium_get_content ((CamelMedium *) part); if (!CAMEL_IS_MULTIPART_ENCRYPTED (mpe)) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Could not parse MIME message. " "Displaying as source.")); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution/source", - cancellable)); - - return parts; + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution/source", + cancellable, out_mail_parts); + + return TRUE; } /* Currently we only handle RFC2015-style PGP encryption. */ protocol = camel_content_type_param ( ((CamelDataWrapper *) mpe)->mime_type, "protocol"); if (!protocol || g_ascii_strcasecmp (protocol, "application/pgp-encrypted") != 0) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Unsupported encryption type for multipart/encrypted")); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "multipart/mixed", cancellable)); - return parts; + return TRUE; } context = camel_gpg_context_new (e_mail_parser_get_session (parser)); @@ -115,40 +110,34 @@ empe_mp_encrypted_parse (EMailParserExtension *extension, e_mail_part_preserve_charset_in_content_type (part, opart); if (local_error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Could not parse PGP/MIME message: %s"), local_error->message); - - g_error_free (local_error); - - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "multipart/mixed", cancellable)); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); g_object_unref (opart); g_object_unref (context); + g_error_free (local_error); - return parts; + return TRUE; } len = part_id->len; g_string_append (part_id, ".encrypted"); - parts = e_mail_parser_parse_part ( - parser, opart, part_id, cancellable); + e_mail_parser_parse_part ( + parser, opart, part_id, cancellable, &work_queue); g_string_truncate (part_id, len); - /* Update validity of all encrypted sub-parts */ - for (iter = parts; iter; iter = iter->next) { - EMailPart *mail_part; + head = g_queue_peek_head_link (&work_queue); - mail_part = iter->data; - if (!mail_part) - continue; + /* Update validity of all encrypted sub-parts */ + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, @@ -156,28 +145,30 @@ empe_mp_encrypted_parse (EMailParserExtension *extension, E_MAIL_PART_VALIDITY_PGP); } + e_queue_transfer (&work_queue, out_mail_parts); + /* Add a widget with details about the encryption, but only when * the decrypted part isn't itself secured, in that case it has * created the button itself. */ if (!e_mail_part_is_secured (opart)) { - GSList *button; EMailPart *mail_part; + g_string_append (part_id, ".encrypted.button"); - button = e_mail_parser_parse_part_as ( + e_mail_parser_parse_part_as ( parser, part, part_id, "application/vnd.evolution.widget.secure-button", - cancellable); - if (button && button->data) { - mail_part = button->data; + cancellable, &work_queue); + + mail_part = g_queue_peek_head (&work_queue); + if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_ENCRYPTED | E_MAIL_PART_VALIDITY_PGP); - } - parts = g_slist_concat (parts, button); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } @@ -188,7 +179,7 @@ empe_mp_encrypted_parse (EMailParserExtension *extension, g_object_unref (opart); g_object_unref (context); - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-multipart-mixed.c b/em-format/e-mail-parser-multipart-mixed.c index 69882739d9..f416ffda24 100644 --- a/em-format/e-mail-parser-multipart-mixed.c +++ b/em-format/e-mail-parser-multipart-mixed.c @@ -59,79 +59,73 @@ static const gchar * parser_mime_types[] = { "multipart/mixed", "multipart/*", NULL }; -static GSList * +static gboolean empe_mp_mixed_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMultipart *mp; gint i, nparts, len; - GSList *parts; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part); - if (!CAMEL_IS_MULTIPART (mp)) { - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", cancellable); - return parts; - } + if (!CAMEL_IS_MULTIPART (mp)) + return e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); len = part_id->len; - parts = NULL; nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts; i++) { + GQueue work_queue = G_QUEUE_INIT; + EMailPart *mail_part; CamelMimePart *subpart; CamelContentType *ct; - GSList *new_parts; subpart = camel_multipart_get_part (mp, i); g_string_append_printf (part_id, ".mixed.%d", i); - new_parts = e_mail_parser_parse_part ( - parser, subpart, part_id, cancellable); + e_mail_parser_parse_part ( + parser, subpart, part_id, cancellable, &work_queue); + + mail_part = g_queue_peek_head (&work_queue); ct = camel_mime_part_get_content_type (subpart); - /* Display parts with CID as attachments (unless they already are - * attachments) */ - if (new_parts && new_parts->data && - (E_MAIL_PART (new_parts->data)->cid != NULL) && - !E_MAIL_PART (new_parts->data)->is_attachment) { + /* Display parts with CID as attachments + * (unless they already are attachments). */ + if (mail_part != NULL && + mail_part->cid != NULL && + !mail_part->is_attachment) { - parts = g_slist_concat ( - parts, - e_mail_parser_wrap_as_attachment ( - parser, subpart, new_parts, - part_id, cancellable)); + e_mail_parser_wrap_as_attachment ( + parser, subpart, part_id, &work_queue); /* Force messages to be expandable */ - } else if (!new_parts || + } else if (mail_part == NULL || (camel_content_type_is (ct, "message", "rfc822") && - new_parts && new_parts->data && - !E_MAIL_PART (new_parts->data)->is_attachment)) { - - parts = g_slist_concat ( - parts, - e_mail_parser_wrap_as_attachment ( - parser, subpart, new_parts, - part_id, cancellable)); - if (parts && parts->data) - E_MAIL_PART (parts->data)->force_inline = TRUE; - } else { - parts = g_slist_concat (parts, new_parts); + mail_part != NULL && !mail_part->is_attachment)) { + + e_mail_parser_wrap_as_attachment ( + parser, subpart, part_id, &work_queue); + + mail_part = g_queue_peek_head (&work_queue); + + if (mail_part != NULL) + mail_part->force_inline = TRUE; } + e_queue_transfer (&work_queue, out_mail_parts); + g_string_truncate (part_id, len); } - return parts; + return TRUE; } static guint32 diff --git a/em-format/e-mail-parser-multipart-related.c b/em-format/e-mail-parser-multipart-related.c index e72b61e26c..0a368ea0c8 100644 --- a/em-format/e-mail-parser-multipart-related.c +++ b/em-format/e-mail-parser-multipart-related.c @@ -57,79 +57,75 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar * parser_mime_types[] = { "multipart/related", NULL }; -static GSList * +static gboolean empe_mp_related_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMultipart *mp; CamelMimePart *body_part, *display_part = NULL; gint i, nparts, partidlen, displayid = 0; - GSList *parts; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part); - if (!CAMEL_IS_MULTIPART (mp)) { + if (!CAMEL_IS_MULTIPART (mp)) return e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", cancellable); - } + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); display_part = e_mail_part_get_related_display_part (part, &displayid); - if (display_part == NULL) { + if (display_part == NULL) return e_mail_parser_parse_part_as ( - parser, part, part_id, "multipart/mixed", - cancellable); - } + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); /* The to-be-displayed part goes first */ partidlen = part_id->len; g_string_append_printf (part_id, ".related.%d", displayid); - parts = e_mail_parser_parse_part ( - parser, display_part, part_id, cancellable); + e_mail_parser_parse_part ( + parser, display_part, part_id, cancellable, out_mail_parts); g_string_truncate (part_id, partidlen); /* Process the related parts */ nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts; i++) { - GSList *list, *iter; + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; + body_part = camel_multipart_get_part (mp, i); - list = NULL; if (body_part == display_part) continue; g_string_append_printf (part_id, ".related.%d", i); - list = e_mail_parser_parse_part ( - parser, body_part, part_id, cancellable); + e_mail_parser_parse_part ( + parser, body_part, part_id, + cancellable, &work_queue); g_string_truncate (part_id, partidlen); - for (iter = list; iter; iter = iter->next) { - EMailPart *mail_part; + head = g_queue_peek_head_link (&work_queue); - mail_part = iter->data; - if (!mail_part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; /* Don't render the part on it's own! */ if (mail_part->cid != NULL) mail_part->is_hidden = TRUE; } - parts = g_slist_concat (parts, list); + e_queue_transfer (&work_queue, out_mail_parts); } - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-multipart-signed.c b/em-format/e-mail-parser-multipart-signed.c index b7d395ab05..60fac35c7f 100644 --- a/em-format/e-mail-parser-multipart-signed.c +++ b/em-format/e-mail-parser-multipart-signed.c @@ -28,6 +28,7 @@ #include <glib/gi18n-lib.h> #include <camel/camel.h> +#include <libedataserver/libedataserver.h> typedef struct _EMailParserMultipartSigned { GObject parent; @@ -56,33 +57,30 @@ static const gchar * parser_mime_types[] = { "multipart/signed", "application/pgp-signature", NULL }; -static GSList * +static gboolean empe_mp_signed_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelMimePart *cpart; CamelMultipartSigned *mps; CamelCipherContext *cipher = NULL; CamelSession *session; guint32 validity_type; - GSList *parts; CamelCipherValidity *valid; GError *local_error = NULL; gint i, nparts, len; gboolean secured; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - /* If the part is application/pgp-signature sub-part then skip it. */ if (!CAMEL_IS_MULTIPART (part)) { CamelContentType *ct; ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (part)); if (camel_content_type_is (ct, "application", "pgp-signature")) { - return g_slist_alloc (); + return TRUE; } } @@ -92,18 +90,16 @@ empe_mp_signed_parse (EMailParserExtension *extension, cpart = camel_multipart_get_part ( (CamelMultipart *) mps, CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Could not parse MIME message. " "Displaying as source.")); + e_mail_parser_parse_part_as ( + parser, part, part_id, + "application/vnd.evolution.source", + cancellable, out_mail_parts); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "application/vnd.evolution.source", - cancellable)); - return parts; + return TRUE; } session = e_mail_parser_get_session (parser); @@ -127,95 +123,89 @@ empe_mp_signed_parse (EMailParserExtension *extension, } if (cipher == NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Unsupported signature format")); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "multipart/mixed", cancellable)); - - return parts; + return TRUE; } valid = camel_cipher_context_verify_sync ( cipher, part, cancellable, &local_error); if (local_error != NULL) { - parts = e_mail_parser_error ( - parser, cancellable, + e_mail_parser_error ( + parser, out_mail_parts, _("Error verifying signature: %s"), local_error->message); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, out_mail_parts); + g_object_unref (cipher); g_error_free (local_error); - parts = g_slist_concat ( - parts, - e_mail_parser_parse_part_as ( - parser, part, part_id, - "multipart/mixed", cancellable)); - - g_object_unref (cipher); - return parts; + return TRUE; } nparts = camel_multipart_get_number (CAMEL_MULTIPART (mps)); secured = FALSE; len = part_id->len; - parts = NULL; for (i = 0; i < nparts; i++) { + GQueue work_queue = G_QUEUE_INIT; + GList *head, *link; CamelMimePart *subpart; - GSList *mail_parts, *iter; + subpart = camel_multipart_get_part (CAMEL_MULTIPART (mps), i); g_string_append_printf (part_id, ".signed.%d", i); - mail_parts = e_mail_parser_parse_part ( - parser, subpart, part_id, cancellable); + e_mail_parser_parse_part ( + parser, subpart, part_id, cancellable, &work_queue); g_string_truncate (part_id, len); if (!secured) secured = e_mail_part_is_secured (subpart); - for (iter = mail_parts; iter; iter = iter->next) { - EMailPart *mail_part; + head = g_queue_peek_head_link (&work_queue); - mail_part = iter->data; - if (!mail_part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, validity_type | E_MAIL_PART_VALIDITY_SIGNED); } - parts = g_slist_concat (parts, mail_parts); + e_queue_transfer (&work_queue, out_mail_parts); } /* Add a widget with details about the encryption, but only when - * the encrypted isn't itself secured, in that case it has created - * the button itself */ + * the encrypted isn't itself secured, in that case it has created + * the button itself. */ if (!secured) { - GSList *button; + GQueue work_queue = G_QUEUE_INIT; EMailPart *mail_part; + g_string_append (part_id, ".signed.button"); - button = e_mail_parser_parse_part_as ( + e_mail_parser_parse_part_as ( parser, part, part_id, "application/vnd.evolution.widget.secure-button", - cancellable); - if (button && button->data) { - mail_part = button->data; + cancellable, &work_queue); + mail_part = g_queue_peek_head (&work_queue); + + if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, validity_type | E_MAIL_PART_VALIDITY_SIGNED); - } - parts = g_slist_concat (parts, button); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } @@ -224,7 +214,7 @@ empe_mp_signed_parse (EMailParserExtension *extension, g_object_unref (cipher); - return parts; + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-secure-button.c b/em-format/e-mail-parser-secure-button.c index 92a0f61958..cb4282cef0 100644 --- a/em-format/e-mail-parser-secure-button.c +++ b/em-format/e-mail-parser-secure-button.c @@ -54,12 +54,13 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar *parser_mime_types[] = { "application/vnd.evolution.widget.secure-button", NULL }; -static GSList * +static gboolean empe_secure_button_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPart *mail_part; gint len; @@ -70,7 +71,9 @@ empe_secure_button_parse (EMailParserExtension *extension, mail_part->mime_type = g_strdup ("application/vnd.evolution.widget.secure-button"); g_string_truncate (part_id, len); - return g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-source.c b/em-format/e-mail-parser-source.c index db08144fa2..ee563acf9f 100644 --- a/em-format/e-mail-parser-source.c +++ b/em-format/e-mail-parser-source.c @@ -54,19 +54,17 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar *parser_mime_types[] = { "application/vnd.evolution.source", NULL }; -static GSList * +static gboolean empe_source_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPart *mail_part; gint len; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - len = part_id->len; g_string_append (part_id, ".source"); @@ -74,7 +72,9 @@ empe_source_parse (EMailParserExtension *extension, mail_part->mime_type = g_strdup ("application/vnd.evolution.source"); g_string_truncate (part_id, len); - return g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); + + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-text-enriched.c b/em-format/e-mail-parser-text-enriched.c index c23130763c..34a64c38f0 100644 --- a/em-format/e-mail-parser-text-enriched.c +++ b/em-format/e-mail-parser-text-enriched.c @@ -57,21 +57,20 @@ static const gchar *parser_mime_types[] = { "text/richtext", "text/enriched", NULL }; -static GSList * +static gboolean empe_text_enriched_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { + GQueue work_queue = G_QUEUE_INIT; EMailPart *mail_part; const gchar *tmp; gint len; CamelContentType *ct; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - len = part_id->len; g_string_append (part_id, ".text_enriched"); @@ -88,13 +87,15 @@ empe_text_enriched_parse (EMailParserExtension *extension, g_string_truncate (part_id, len); - if (e_mail_part_is_attachment (part)) { - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, mail_part), - part_id, cancellable); - } + g_queue_push_tail (&work_queue, mail_part); + + if (e_mail_part_is_attachment (part)) + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); - return g_slist_append (NULL, mail_part); + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-text-html.c b/em-format/e-mail-parser-text-html.c index b824931e09..a28a8ff5f0 100644 --- a/em-format/e-mail-parser-text-html.c +++ b/em-format/e-mail-parser-text-html.c @@ -57,22 +57,21 @@ G_DEFINE_TYPE_EXTENDED ( static const gchar *parser_mime_types[] = { "text/html", NULL }; -static GSList * +static gboolean empe_text_html_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - EMailPart *empart; + GQueue work_queue = G_QUEUE_INIT; + EMailPart *mail_part; const gchar *location; gchar *cid = NULL; const gchar *base; gint len; - if (g_cancellable_is_cancelled (cancellable)) - return NULL; - cid = NULL; base = camel_medium_get_header (CAMEL_MEDIUM (part), "content-base"); location = camel_mime_part_get_content_location (part); @@ -93,18 +92,20 @@ empe_text_html_parse (EMailParserExtension *extension, len = part_id->len; g_string_append (part_id, ".text_html"); - empart = e_mail_part_new (part, part_id->str); - empart->mime_type = g_strdup ("text/html"); - empart->cid = cid; + mail_part = e_mail_part_new (part, part_id->str); + mail_part->mime_type = g_strdup ("text/html"); + mail_part->cid = cid; g_string_truncate (part_id, len); - if (e_mail_part_is_attachment (part)) { - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, empart), - part_id, cancellable); - } + g_queue_push_head (&work_queue, mail_part); + + if (e_mail_part_is_attachment (part)) + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); - return g_slist_append (NULL, empart); + return TRUE; } static const gchar ** diff --git a/em-format/e-mail-parser-text-plain.c b/em-format/e-mail-parser-text-plain.c index bdfcd15e5d..4c9c0b36a5 100644 --- a/em-format/e-mail-parser-text-plain.c +++ b/em-format/e-mail-parser-text-plain.c @@ -80,32 +80,30 @@ part_is_empty (CamelMimePart *part) return TRUE; } -static GSList * +static gboolean process_part (EMailParser *parser, GString *part_id, gint part_number, CamelMimePart *part, gboolean is_attachment, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelContentType *type; EMailPart *empart; gint s_len = part_id->len; - GSList *parts; - if (part_is_empty (part)) { - return g_slist_alloc (); - } + if (part_is_empty (part)) + return TRUE; type = camel_mime_part_get_content_type (part); if (!camel_content_type_is (type, "text", "*")) { - - parts = e_mail_parser_parse_part ( - parser, CAMEL_MIME_PART (part), - part_id, cancellable); - return parts; + e_mail_parser_parse_part ( + parser, CAMEL_MIME_PART (part), part_id, + cancellable, out_mail_parts); } else if (!camel_content_type_is (type, "text", "calendar")) { + GQueue work_queue = G_QUEUE_INIT; g_string_append_printf (part_id, ".plain_text.%d", part_number); @@ -114,37 +112,35 @@ process_part (EMailParser *parser, g_string_truncate (part_id, s_len); - if (is_attachment) { - - return e_mail_parser_wrap_as_attachment ( - parser, part, - g_slist_append (NULL, empart), - part_id, cancellable); + g_queue_push_tail (&work_queue, empart); - } + if (is_attachment) + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); - return g_slist_append (NULL, empart); - } + e_queue_transfer (&work_queue, out_mail_parts); - g_string_append_printf (part_id, ".inline.%d", part_number); + } else { + g_string_append_printf (part_id, ".inline.%d", part_number); - parts = e_mail_parser_parse_part ( - parser, CAMEL_MIME_PART (part), - part_id, cancellable); + e_mail_parser_parse_part ( + parser, CAMEL_MIME_PART (part), part_id, + cancellable, out_mail_parts); - g_string_truncate (part_id, s_len); + g_string_truncate (part_id, s_len); + } - return parts; + return TRUE; } -static GSList * +static gboolean empe_text_plain_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - GSList *parts; CamelStream *filtered_stream, *null; CamelMultipart *mp; CamelDataWrapper *dw; @@ -154,13 +150,11 @@ empe_text_plain_parse (EMailParserExtension *extension, gboolean charset_added = FALSE; const gchar *snoop_type = NULL; gboolean is_attachment; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; + gint n_parts_added = 0; dw = camel_medium_get_content ((CamelMedium *) part); if (!dw) - return NULL; + return FALSE; /* This scans the text part for inline-encoded data, creates * a multipart of all the parts inside it. */ @@ -206,7 +200,7 @@ empe_text_plain_parse (EMailParserExtension *extension, return process_part ( parser, part_id, 0, part, e_mail_part_is_attachment (part), - cancellable); + cancellable, out_mail_parts); } mp = e_mail_inline_filter_get_multipart (inline_filter); @@ -220,7 +214,6 @@ empe_text_plain_parse (EMailParserExtension *extension, /* We handle our made-up multipart here, so we don't recursively call ourselves */ count = camel_multipart_get_number (mp); - parts = NULL; is_attachment = ((count == 1) && (e_mail_part_is_attachment (part))); @@ -230,17 +223,15 @@ empe_text_plain_parse (EMailParserExtension *extension, if (!newpart) continue; - parts = g_slist_concat ( - parts, - process_part ( - parser, part_id, i, - newpart, is_attachment, - cancellable)); + n_parts_added += process_part ( + parser, part_id, i, + newpart, is_attachment, + cancellable, out_mail_parts); } g_object_unref (mp); - return parts; + return n_parts_added; } static const gchar ** diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c index 8e5ccd4ef8..55e6eef47f 100644 --- a/em-format/e-mail-parser.c +++ b/em-format/e-mail-parser.c @@ -62,11 +62,11 @@ mail_parser_run (EMailParser *parser, { EMailExtensionRegistry *reg; CamelMimeMessage *message; - EMailPart *part; + EMailPart *mail_part; GQueue *parsers; + GQueue mail_part_queue = G_QUEUE_INIT; GList *iter; GString *part_id; - GSList *list_of_parts; message = e_mail_part_list_get_message (part_list); @@ -79,18 +79,19 @@ mail_parser_run (EMailParser *parser, parsers = e_mail_extension_registry_get_for_mime_type ( reg, "message/*"); - /* parsers == NULL means, that the internal Evolution parser - * extensions were not loaded. Something is terribly wrong. */ + /* No parsers means the internal Evolution parser + * extensions were not loaded. Something is terribly wrong! */ g_return_if_fail (parsers != NULL); part_id = g_string_new (".message"); - part = e_mail_part_new (CAMEL_MIME_PART (message), ".message"); - e_mail_part_list_add_part (part_list, part); - e_mail_part_unref (part); + mail_part = e_mail_part_new (CAMEL_MIME_PART (message), ".message"); + e_mail_part_list_add_part (part_list, mail_part); + e_mail_part_unref (mail_part); for (iter = parsers->head; iter; iter = iter->next) { EMailParserExtension *extension; + gboolean message_handled; if (g_cancellable_is_cancelled (cancellable)) break; @@ -99,24 +100,19 @@ mail_parser_run (EMailParser *parser, if (!extension) continue; - list_of_parts = e_mail_parser_extension_parse ( + message_handled = e_mail_parser_extension_parse ( extension, parser, CAMEL_MIME_PART (message), - part_id, cancellable); + part_id, cancellable, &mail_part_queue); - if (list_of_parts != NULL) + if (message_handled) break; } - while (list_of_parts != NULL) { - part = list_of_parts->data; - if (part != NULL) { - e_mail_part_list_add_part (part_list, part); - e_mail_part_unref (part); - } - - list_of_parts = g_slist_delete_link ( - list_of_parts, list_of_parts); + while (!g_queue_is_empty (&mail_part_queue)) { + mail_part = g_queue_pop_head (&mail_part_queue); + e_mail_part_list_add_part (part_list, mail_part); + e_mail_part_unref (mail_part); } g_string_free (part_id, TRUE); @@ -428,15 +424,16 @@ e_mail_parser_parse_finish (EMailParser *parser, return g_object_ref (part_list); } -GSList * +gboolean e_mail_parser_parse_part (EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { CamelContentType *ct; gchar *mime_type; - GSList *list; + gint n_parts_queued = 0; ct = camel_mime_part_get_content_type (part); if (!ct) { @@ -448,32 +445,31 @@ e_mail_parser_parse_part (EMailParser *parser, g_free (tmp); } - list = e_mail_parser_parse_part_as ( - parser, part, part_id, mime_type, cancellable); + n_parts_queued = e_mail_parser_parse_part_as ( + parser, part, part_id, mime_type, + cancellable, out_mail_parts); if (ct) { g_free (mime_type); } - return list; + return n_parts_queued; } -GSList * +gboolean e_mail_parser_parse_part_as (EMailParser *parser, CamelMimePart *part, GString *part_id, const gchar *mime_type, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { GQueue *parsers; GList *iter; EMailExtensionRegistry *reg; EMailParserClass *parser_class; - GSList *part_list = NULL; gchar *as_mime_type; - - if (g_cancellable_is_cancelled (cancellable)) - return NULL; + gboolean mime_part_handled = FALSE; if (mime_type) as_mime_type = g_ascii_strdown (mime_type, -1); @@ -491,9 +487,10 @@ e_mail_parser_parse_part_as (EMailParser *parser, if (as_mime_type) g_free (as_mime_type); - if (!parsers) { - return e_mail_parser_wrap_as_attachment ( - parser, part, NULL, part_id, cancellable); + if (parsers == NULL) { + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, out_mail_parts); + return TRUE; } for (iter = parsers->head; iter; iter = iter->next) { @@ -503,19 +500,20 @@ e_mail_parser_parse_part_as (EMailParser *parser, if (!extension) continue; - part_list = e_mail_parser_extension_parse ( - extension, parser, part, part_id, cancellable); + mime_part_handled = e_mail_parser_extension_parse ( + extension, parser, part, part_id, + cancellable, out_mail_parts); - if (part_list) + if (mime_part_handled) break; } - return part_list; + return mime_part_handled; } -GSList * +void e_mail_parser_error (EMailParser *parser, - GCancellable *cancellable, + GQueue *out_mail_parts, const gchar *format, ...) { @@ -525,8 +523,9 @@ e_mail_parser_error (EMailParser *parser, gchar *uri; va_list ap; - g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL); - g_return_val_if_fail (format != NULL, NULL); + g_return_if_fail (E_IS_MAIL_PARSER (parser)); + g_return_if_fail (out_mail_parts != NULL); + g_return_if_fail (format != NULL); va_start (ap, format); errmsg = g_strdup_vprintf (format, ap); @@ -551,7 +550,7 @@ e_mail_parser_error (EMailParser *parser, g_free (uri); g_object_unref (part); - return g_slist_append (NULL, mail_part); + g_queue_push_tail (out_mail_parts, mail_part); } static void @@ -581,14 +580,14 @@ load_attachment_idle (EAttachment *attachment) return FALSE; } -GSList * +void e_mail_parser_wrap_as_attachment (EMailParser *parser, CamelMimePart *part, - GSList *parts, GString *part_id, - GCancellable *cancellable) + GQueue *parts_queue) { EMailPartAttachment *empa; + EMailPart *first_part; const gchar *snoop_mime_type, *cid; GQueue *extensions; CamelContentType *ct; @@ -644,7 +643,12 @@ e_mail_parser_wrap_as_attachment (EMailParser *parser, e_mail_part_is_inline (part, extensions)); empa->snoop_mime_type = snoop_mime_type; empa->attachment = e_attachment_new (); - empa->attachment_view_part_id = parts ? g_strdup (E_MAIL_PART (parts->data)->id) : NULL; + + first_part = g_queue_peek_head (parts_queue); + if (first_part != NULL) { + empa->attachment_view_part_id = g_strdup (first_part->id); + first_part->is_hidden = TRUE; + } cid = camel_mime_part_get_content_id (part); if (cid) @@ -692,13 +696,10 @@ e_mail_parser_wrap_as_attachment (EMailParser *parser, g_object_unref (fileinfo); } - if (parts && parts->data) { - E_MAIL_PART (parts->data)->is_hidden = TRUE; - } - g_string_truncate (part_id, part_id_len); - return g_slist_prepend (parts, empa); + /* Push to head, not tail. */ + g_queue_push_head (parts_queue, empa); } CamelSession * diff --git a/em-format/e-mail-parser.h b/em-format/e-mail-parser.h index 202e28d267..77818b86e6 100644 --- a/em-format/e-mail-parser.h +++ b/em-format/e-mail-parser.h @@ -80,28 +80,29 @@ EMailPartList * e_mail_parser_parse_finish (EMailParser *parser, GAsyncResult *result, GError **error); -GSList * e_mail_parser_parse_part (EMailParser *parser, +gboolean e_mail_parser_parse_part (EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable); + GCancellable *cancellable, + GQueue *out_mail_parts); -GSList * e_mail_parser_parse_part_as (EMailParser *parser, +gboolean e_mail_parser_parse_part_as (EMailParser *parser, CamelMimePart *part, GString *part_id, const gchar *mime_type, - GCancellable *cancellable); - -GSList * e_mail_parser_error (EMailParser *parser, GCancellable *cancellable, + GQueue *out_mail_parts); + +void e_mail_parser_error (EMailParser *parser, + GQueue *out_mail_parts, const gchar *format, ...) G_GNUC_PRINTF (3, 4); -GSList * e_mail_parser_wrap_as_attachment +void e_mail_parser_wrap_as_attachment (EMailParser *parser, CamelMimePart *part, - GSList *parts, GString *part_id, - GCancellable *cancellable); + GQueue *parts_queue); CamelSession * e_mail_parser_get_session (EMailParser *parser); diff --git a/modules/audio-inline/e-mail-parser-audio-inline.c b/modules/audio-inline/e-mail-parser-audio-inline.c index 5509306118..ca87693fe4 100644 --- a/modules/audio-inline/e-mail-parser-audio-inline.c +++ b/modules/audio-inline/e-mail-parser-audio-inline.c @@ -101,15 +101,18 @@ mail_part_audio_inline_free (EMailPart *mail_part) } } -static GSList * +static gint empe_audio_inline_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_queue) { EMailPartAudioInline *mail_part; + GQueue work_queue = G_QUEUE_INIT; gint len; + gint n_parts_added = 0; len = part_id->len; g_string_append (part_id, ".org-gnome-audio-inline-button-panel"); @@ -117,16 +120,22 @@ empe_audio_inline_parse (EMailParserExtension *extension, d (printf ("audio inline formatter: format classid %s\n", part_id->str)); mail_part = (EMailPartAudioInline *) e_mail_part_subclass_new ( - part, part_id->str, sizeof (EMailPartAudioInline), - (GFreeFunc) mail_part_audio_inline_free); + part, part_id->str, sizeof (EMailPartAudioInline), + (GFreeFunc) mail_part_audio_inline_free); mail_part->parent.mime_type = camel_content_type_simple ( - camel_mime_part_get_content_type (part)); + camel_mime_part_get_content_type (part)); mail_part->parent.is_attachment = TRUE; g_string_truncate (part_id, len); - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, mail_part), - part_id, cancellable); + g_queue_push_tail (&work_queue, mail_part); + n_parts_added++; + + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_queue); + + return TRUE; } static guint32 diff --git a/modules/itip-formatter/e-mail-parser-itip.c b/modules/itip-formatter/e-mail-parser-itip.c index 56bbd53da1..505842807a 100644 --- a/modules/itip-formatter/e-mail-parser-itip.c +++ b/modules/itip-formatter/e-mail-parser-itip.c @@ -180,12 +180,13 @@ bind_itip_view (EMailPart *part, /*******************************************************************************/ -static GSList * +static gboolean empe_itip_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EShell *shell; GSettings *settings; @@ -195,7 +196,7 @@ empe_itip_parse (EMailParserExtension *extension, GByteArray *byte_array; gint len; const CamelContentDisposition *disposition; - GSList *parts; + GQueue work_queue = G_QUEUE_INIT; len = part_id->len; g_string_append_printf (part_id, ".itip"); @@ -234,18 +235,20 @@ empe_itip_parse (EMailParserExtension *extension, g_object_unref (stream); - parts = g_slist_append (NULL, itip_part); + g_queue_push_tail (&work_queue, itip_part); disposition = camel_mime_part_get_content_disposition (part); if (disposition && (g_strcmp0 (disposition->disposition, "attachment") == 0)) { - parts = e_mail_parser_wrap_as_attachment ( - parser, part, parts, part_id, cancellable); + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); } + e_queue_transfer (&work_queue, out_mail_parts); + g_string_truncate (part_id, len); - return parts; + return TRUE; } static guint32 diff --git a/modules/prefer-plain/e-mail-parser-prefer-plain.c b/modules/prefer-plain/e-mail-parser-prefer-plain.c index 66ff32106c..296369ed32 100644 --- a/modules/prefer-plain/e-mail-parser-prefer-plain.c +++ b/modules/prefer-plain/e-mail-parser-prefer-plain.c @@ -99,18 +99,19 @@ enum { PROP_SHOW_SUPPRESSED }; -static GSList * +static void make_part_attachment (EMailParser *parser, CamelMimePart *part, GString *part_id, gboolean force_html, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - GSList *parts; - if (camel_content_type_is (camel_mime_part_get_content_type (part), "text", "html")) { + GQueue work_queue = G_QUEUE_INIT; EMailPart *mail_part; gint len; + /* always show HTML as attachments and not inline */ camel_mime_part_set_disposition (part, "attachment"); @@ -126,9 +127,12 @@ make_part_attachment (EMailParser *parser, mail_part->mime_type = g_strdup ("text/html"); g_string_truncate (part_id, len); - parts = e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, mail_part), - part_id, cancellable); + g_queue_push_tail (&work_queue, mail_part); + + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); } else if (force_html && CAMEL_IS_MIME_MESSAGE (part)) { /* message was asked to be formatted as text/html; @@ -137,52 +141,51 @@ make_part_attachment (EMailParser *parser, CamelDataWrapper *content; content = camel_medium_get_content (CAMEL_MEDIUM (part)); - g_return_val_if_fail (content != NULL, NULL); + g_return_if_fail (content != NULL); new_part = camel_mime_part_new (); camel_medium_set_content (CAMEL_MEDIUM (new_part), content); - parts = e_mail_parser_parse_part ( - parser, new_part, part_id, cancellable); + e_mail_parser_parse_part ( + parser, new_part, part_id, + cancellable, out_mail_parts); g_object_unref (new_part); } else { - parts = e_mail_parser_parse_part ( - parser, part, part_id, cancellable); + e_mail_parser_parse_part ( + parser, part, part_id, cancellable, out_mail_parts); } - - return parts; } static void -hide_parts (GSList *parts) +hide_parts (GQueue *work_queue) { - GSList *iter; + GList *head, *link; - for (iter = parts; iter; iter = g_slist_next (iter)) { - EMailPart *p = iter->data; + head = g_queue_peek_head_link (work_queue); - if (!p) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; - p->is_hidden = TRUE; + mail_part->is_hidden = TRUE; } } -static GSList * +static gboolean empe_prefer_plain_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailParserPreferPlain *emp_pp; CamelMultipart *mp; gint i, nparts, partidlen; - GSList *parts; CamelContentType *ct; gboolean has_calendar = FALSE; - GSList *plain_text_parts = NULL; + GQueue plain_text_parts = G_QUEUE_INIT; + GQueue work_queue = G_QUEUE_INIT; emp_pp = (EMailParserPreferPlain *) extension; @@ -194,36 +197,35 @@ empe_prefer_plain_parse (EMailParserExtension *extension, /* Prevent recursion, fall back to next (real text/html) parser */ if (strstr (part_id->str, ".alternative-prefer-plain.") != NULL) - return NULL; + return FALSE; /* Not enforcing text/plain, so use real parser */ if (emp_pp->mode != ONLY_PLAIN) - return NULL; + return FALSE; /* Enforcing text/plain, but got only HTML part, so add it * as attachment, to not show empty message preview, which * is confusing. */ - return make_part_attachment ( - parser, part, part_id, - FALSE, cancellable); + make_part_attachment ( + parser, part, part_id, FALSE, + cancellable, out_mail_parts); + + return TRUE; } - parts = NULL; partidlen = part_id->len; mp = (CamelMultipart *) camel_medium_get_content (CAMEL_MEDIUM (part)); - if (!CAMEL_IS_MULTIPART (mp)) { + if (!CAMEL_IS_MULTIPART (mp)) return e_mail_parser_parse_part_as ( parser, part, part_id, - "application/vnd.evolution.source", cancellable); - } + "application/vnd.evolution.source", + cancellable, out_mail_parts); nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts; i++) { - CamelMimePart *sp; - GSList *sparts = NULL; sp = camel_multipart_get_part (mp, i); ct = camel_mime_part_get_content_type (sp); @@ -232,61 +234,52 @@ empe_prefer_plain_parse (EMailParserExtension *extension, g_string_append_printf (part_id, ".alternative-prefer-plain.%d", i); if (camel_content_type_is (ct, "text", "html")) { - if (emp_pp->mode != PREFER_HTML) { if (emp_pp->show_suppressed) { - sparts = make_part_attachment ( - parser, sp, part_id, - FALSE, cancellable); + make_part_attachment ( + parser, sp, part_id, FALSE, + cancellable, &work_queue); } } else { - sparts = e_mail_parser_parse_part ( - parser, sp, part_id, cancellable); + e_mail_parser_parse_part ( + parser, sp, part_id, + cancellable, &work_queue); } - parts = g_slist_concat (parts, sparts); - continue; - } - - if (camel_content_type_is (ct, "text", "plain")) { - - sparts = e_mail_parser_parse_part ( - parser, sp, part_id, cancellable); - - plain_text_parts = g_slist_concat (plain_text_parts, sparts); - continue; - } + } else if (camel_content_type_is (ct, "text", "plain")) { + e_mail_parser_parse_part ( + parser, sp, part_id, + cancellable, &plain_text_parts); /* Always show calendar part! */ - if (camel_content_type_is (ct, "text", "calendar") || + } else if (camel_content_type_is (ct, "text", "calendar") || camel_content_type_is (ct, "text", "x-calendar")) { - /* Hide everything else, displaying native calendar part only */ - hide_parts (parts); + /* Hide everything else, displaying + * native calendar part only. */ + hide_parts (&work_queue); - sparts = e_mail_parser_parse_part ( - parser, sp, part_id, cancellable); + e_mail_parser_parse_part ( + parser, sp, part_id, cancellable, &work_queue); - parts = g_slist_concat (parts, sparts); has_calendar = TRUE; - continue; - } /* Multiparts can represent a text/html with inline images or so */ - if (camel_content_type_is (ct, "multipart", "*")) { - GSList *iter; + } else if (camel_content_type_is (ct, "multipart", "*")) { + GQueue inner_queue = G_QUEUE_INIT; + GList *head, *link; gboolean has_html = FALSE; - sparts = e_mail_parser_parse_part ( - parser, sp, part_id, cancellable); + e_mail_parser_parse_part ( + parser, sp, part_id, cancellable, &inner_queue); + + head = g_queue_peek_head_link (&inner_queue); /* Check whether the multipart contains a text/html part */ - for (iter = sparts; iter; iter = g_slist_next (iter)) { - EMailPart *p = iter->data; - if (!p) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; - if (strstr (p->id, ".text_html") != NULL) { + if (strstr (mail_part->id, ".text_html") != NULL) { has_html = TRUE; break; } @@ -294,41 +287,41 @@ empe_prefer_plain_parse (EMailParserExtension *extension, if (has_html && (emp_pp->mode != PREFER_HTML)) { if (emp_pp->show_suppressed) { - sparts = e_mail_parser_wrap_as_attachment ( - parser, sp, sparts, part_id, - cancellable); + e_mail_parser_wrap_as_attachment ( + parser, sp, part_id, + &inner_queue); } else { - hide_parts (sparts); + hide_parts (&inner_queue); } } - parts = g_slist_concat (parts, sparts); - continue; - } + e_queue_transfer (&inner_queue, &work_queue); /* Parse everything else as an attachment */ - sparts = e_mail_parser_parse_part ( - parser, sp, part_id, cancellable); - parts = g_slist_concat ( - parts, - e_mail_parser_wrap_as_attachment ( - parser, sp, sparts, part_id, - cancellable)); + } else { + GQueue inner_queue = G_QUEUE_INIT; + + e_mail_parser_parse_part ( + parser, sp, part_id, + cancellable, &inner_queue); + e_mail_parser_wrap_as_attachment ( + parser, sp, part_id, &inner_queue); + + e_queue_transfer (&inner_queue, &work_queue); + } } /* Don't hide the plain text if there's nothing else to display */ - if (has_calendar || (nparts > 1 && emp_pp->mode == PREFER_HTML)) { - hide_parts (plain_text_parts); - } + if (has_calendar || (nparts > 1 && emp_pp->mode == PREFER_HTML)) + hide_parts (&plain_text_parts); - if (plain_text_parts) { - /* plain_text parts should be always first */ - parts = g_slist_concat (plain_text_parts, parts); - } + /* plain_text parts should be always first */ + e_queue_transfer (&plain_text_parts, out_mail_parts); + e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, partidlen); - return parts; + return TRUE; } static const gchar ** diff --git a/modules/text-highlight/e-mail-parser-text-highlight.c b/modules/text-highlight/e-mail-parser-text-highlight.c index 69aa1ccff2..eb56162a3d 100644 --- a/modules/text-highlight/e-mail-parser-text-highlight.c +++ b/modules/text-highlight/e-mail-parser-text-highlight.c @@ -58,21 +58,20 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED ( E_TYPE_MAIL_PARSER_EXTENSION, e_mail_parser_parser_extension_interface_init)); -static GSList * +static gboolean empe_text_highlight_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { - GSList *parts; - gint len; CamelContentType *ct; + gint len; /* Prevent recursion */ - if (strstr (part_id->str, ".text-highlight") != NULL) { - return NULL; - } + if (strstr (part_id->str, ".text-highlight") != NULL) + return FALSE; /* Don't parse text/html if it's not an attachment */ ct = camel_mime_part_get_content_type (part); @@ -80,9 +79,8 @@ empe_text_highlight_parse (EMailParserExtension *extension, const CamelContentDisposition *disp; disp = camel_mime_part_get_content_disposition (part); - if (!disp || (g_strcmp0 (disp->disposition, "attachment") != 0)) { - return NULL; - } + if (!disp || (g_strcmp0 (disp->disposition, "attachment") != 0)) + return FALSE; } len = part_id->len; @@ -90,12 +88,14 @@ empe_text_highlight_parse (EMailParserExtension *extension, /* All source codes and scripts are in general plain texts, * so let text/plain parser handle it. */ - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, "text/plain", cancellable); + + e_mail_parser_parse_part_as ( + parser, part, part_id, "text/plain", + cancellable, out_mail_parts); g_string_truncate (part_id, len); - return parts; + return TRUE; } static const gchar ** diff --git a/modules/tnef-attachment/e-mail-parser-tnef-attachment.c b/modules/tnef-attachment/e-mail-parser-tnef-attachment.c index 3de54e627f..a0342aaa37 100644 --- a/modules/tnef-attachment/e-mail-parser-tnef-attachment.c +++ b/modules/tnef-attachment/e-mail-parser-tnef-attachment.c @@ -114,12 +114,13 @@ sanitize_filename (const gchar *filename) } } -static GSList * +static gboolean empe_tnef_attachment_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { gchar *tmpdir, *name; CamelStream *out; @@ -130,30 +131,30 @@ empe_tnef_attachment_parse (EMailParserExtension *extension, CamelDataWrapper *content; gint len; TNEFStruct tnef; - GSList *parts; + GQueue work_queue = G_QUEUE_INIT; tmpdir = e_mkdtemp ("tnef-attachment-XXXXXX"); if (tmpdir == NULL) - return NULL; + return FALSE; name = g_build_filename (tmpdir, ".evo-attachment.tnef", NULL); out = camel_stream_fs_new_with_name (name, O_RDWR | O_CREAT, 0666, NULL); if (out == NULL) { g_free (name); - return NULL; + return FALSE; } content = camel_medium_get_content ((CamelMedium *) part); if (content == NULL) { g_free (name); g_object_unref (out); - return NULL; + return FALSE; } if (camel_data_wrapper_decode_to_stream_sync (content, out, NULL, NULL) == -1 || camel_stream_close (out, NULL, NULL) == -1) { g_object_unref (out); g_free (name); - return NULL; + return FALSE; } g_object_unref (out); @@ -172,7 +173,7 @@ empe_tnef_attachment_parse (EMailParserExtension *extension, if (dir == NULL) { g_object_unref (out); g_free (name); - return NULL; + return FALSE; } mainpart = camel_mime_part_new (); @@ -226,7 +227,6 @@ empe_tnef_attachment_parse (EMailParserExtension *extension, len = part_id->len; g_string_append_printf (part_id, ".tnef"); - parts = NULL; if (camel_multipart_get_number (mp) > 0) { CamelMimePart *part = camel_mime_part_new (); @@ -235,18 +235,20 @@ empe_tnef_attachment_parse (EMailParserExtension *extension, (CamelMedium *) part, CAMEL_DATA_WRAPPER (mp)); - parts = e_mail_parser_parse_part_as ( - parser, part, part_id, - "multipart/mixed", cancellable); + e_mail_parser_parse_part_as ( + parser, part, part_id, "multipart/mixed", + cancellable, &work_queue); g_object_unref (part); } g_string_truncate (part_id, len); - if (parts) - parts = e_mail_parser_wrap_as_attachment ( - parser, part, parts, part_id, cancellable); + if (!g_queue_is_empty (&work_queue)) + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); g_object_unref (mp); g_object_unref (mainpart); @@ -254,7 +256,7 @@ empe_tnef_attachment_parse (EMailParserExtension *extension, g_free (name); g_free (tmpdir); - return parts; + return TRUE; } static const gchar ** diff --git a/modules/vcard-inline/e-mail-parser-vcard-inline.c b/modules/vcard-inline/e-mail-parser-vcard-inline.c index 319775b6eb..84f4f2f538 100644 --- a/modules/vcard-inline/e-mail-parser-vcard-inline.c +++ b/modules/vcard-inline/e-mail-parser-vcard-inline.c @@ -328,39 +328,46 @@ decode_vcard (EMailPartVCardInline *vcard_part, g_object_unref (stream); } -static GSList * +static gboolean empe_vcard_inline_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, - GCancellable *cancellable) + GCancellable *cancellable, + GQueue *out_mail_parts) { EMailPartVCardInline *vcard_part; + GQueue work_queue = G_QUEUE_INIT; gint len; len = part_id->len; g_string_append (part_id, ".org-gnome-vcard-inline-display"); vcard_part = (EMailPartVCardInline *) e_mail_part_subclass_new ( - part, part_id->str, sizeof (EMailPartVCardInline), - (GFreeFunc) mail_part_vcard_inline_free); + part, part_id->str, sizeof (EMailPartVCardInline), + (GFreeFunc) mail_part_vcard_inline_free); vcard_part->parent.mime_type = camel_content_type_simple ( - camel_mime_part_get_content_type (part)); + camel_mime_part_get_content_type (part)); vcard_part->parent.bind_func = (EMailPartDOMBindFunc) bind_dom; vcard_part->parent.is_attachment = TRUE; vcard_part->formatter = g_object_new ( - EAB_TYPE_CONTACT_FORMATTER, - "display-mode", EAB_CONTACT_DISPLAY_RENDER_COMPACT, - "render-maps", FALSE, NULL); + EAB_TYPE_CONTACT_FORMATTER, + "display-mode", EAB_CONTACT_DISPLAY_RENDER_COMPACT, + "render-maps", FALSE, NULL); g_object_ref (part); decode_vcard (vcard_part, part); g_string_truncate (part_id, len); - return e_mail_parser_wrap_as_attachment ( - parser, part, g_slist_append (NULL, vcard_part), - part_id, cancellable); + g_queue_push_tail (&work_queue, vcard_part); + + e_mail_parser_wrap_as_attachment ( + parser, part, part_id, &work_queue); + + e_queue_transfer (&work_queue, out_mail_parts); + + return TRUE; } static guint32 |