diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2012-12-05 21:19:04 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2012-12-08 03:01:04 +0800 |
commit | 91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8 (patch) | |
tree | 1c06f36fa153eee0779cdfa1be1a24f62e93787d /em-format | |
parent | 2f0d83cf74b94d5e6272c07179df6e6c7a929789 (diff) | |
download | gsoc2013-evolution-91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8.tar.gz gsoc2013-evolution-91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8.tar.zst gsoc2013-evolution-91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8.zip |
Make EMailPartList thread-safe.
Exposing data members in the public struct is unwise, especially when
EMailPartList is used from multiple threads. Instead keep the members
private and provide a set of thread-safe functions to manipulate them.
Diffstat (limited to 'em-format')
-rw-r--r-- | em-format/e-mail-formatter-attachment.c | 48 | ||||
-rw-r--r-- | em-format/e-mail-formatter-message-rfc822.c | 97 | ||||
-rw-r--r-- | em-format/e-mail-formatter-print-headers.c | 33 | ||||
-rw-r--r-- | em-format/e-mail-formatter-print.c | 16 | ||||
-rw-r--r-- | em-format/e-mail-formatter-quote-attachment.c | 16 | ||||
-rw-r--r-- | em-format/e-mail-formatter-quote-message-rfc822.c | 47 | ||||
-rw-r--r-- | em-format/e-mail-formatter-quote.c | 23 | ||||
-rw-r--r-- | em-format/e-mail-formatter-text-html.c | 4 | ||||
-rw-r--r-- | em-format/e-mail-formatter-text-plain.c | 4 | ||||
-rw-r--r-- | em-format/e-mail-formatter-utils.c | 6 | ||||
-rw-r--r-- | em-format/e-mail-formatter-utils.h | 4 | ||||
-rw-r--r-- | em-format/e-mail-formatter.c | 18 | ||||
-rw-r--r-- | em-format/e-mail-parser.c | 66 | ||||
-rw-r--r-- | em-format/e-mail-part-list.c | 355 | ||||
-rw-r--r-- | em-format/e-mail-part-list.h | 40 |
15 files changed, 530 insertions, 247 deletions
diff --git a/em-format/e-mail-formatter-attachment.c b/em-format/e-mail-formatter-attachment.c index e8660fc0b8..8d049deddc 100644 --- a/em-format/e-mail-formatter-attachment.c +++ b/em-format/e-mail-formatter-attachment.c @@ -69,26 +69,28 @@ static const gchar *formatter_mime_types[] = { "application/vnd.evolution.attach NULL }; static EAttachmentStore * -find_attachment_store (GSList *parts, +find_attachment_store (EMailPartList *part_list, const gchar *start_id) { + EAttachmentStore *store = NULL; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; gchar *tmp, *pos; EMailPart *part; gchar *id; + e_mail_part_list_queue_parts (part_list, NULL, &queue); + + head = g_queue_peek_head_link (&queue); + id = g_strconcat (start_id, ".attachment-bar", NULL); tmp = g_strdup (id); part = NULL; do { - GSList *iter; - d (printf ("Looking up attachment bar as %s\n", id)); - for (iter = parts; iter; iter = iter->next) { - EMailPart *p = iter->data; - - if (!p) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *p = link->data; if (g_strcmp0 (p->id, id) == 0) { part = p; @@ -110,11 +112,13 @@ find_attachment_store (GSList *parts, g_free (id); g_free (tmp); - if (part) { - return ((EMailPartAttachmentBar *) part)->store; - } + if (part != NULL) + store = ((EMailPartAttachmentBar *) part)->store; - return NULL; + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + + return store; } static gboolean @@ -157,7 +161,7 @@ emfe_attachment_format (EMailFormatterExtension *extension, } } - store = find_attachment_store (context->part_list->list, part->id); + store = find_attachment_store (context->part_list, part->id); if (store) { GList *attachments = e_attachment_store_get_attachments (store); if (!g_list_find (attachments, empa->attachment)) { @@ -277,17 +281,19 @@ emfe_attachment_format (EMailFormatterExtension *extension, content_stream = camel_stream_mem_new (); ok = FALSE; if (empa->attachment_view_part_id != NULL) { + EMailPart *attachment_view_part; - GSList *att_parts; - - att_parts = e_mail_part_list_get_iter ( - context->part_list->list, + attachment_view_part = e_mail_part_list_ref_part ( + context->part_list, empa->attachment_view_part_id); - if (att_parts && att_parts->data) { + if (attachment_view_part != NULL) { ok = e_mail_formatter_format_as ( - formatter, context, att_parts->data, - content_stream, NULL, cancellable); + formatter, context, + attachment_view_part, + content_stream, NULL, + cancellable); + e_mail_part_unref (attachment_view_part); } } else { @@ -353,7 +359,7 @@ emfe_attachment_get_widget (EMailFormatterExtension *extension, g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAttachment), NULL); empa = (EMailPartAttachment *) part; - store = find_attachment_store (context->list, part->id); + store = find_attachment_store (context, part->id); widget = e_attachment_button_new (); g_object_set_data (G_OBJECT (widget), "uri", part->id); e_attachment_button_set_attachment ( diff --git a/em-format/e-mail-formatter-message-rfc822.c b/em-format/e-mail-formatter-message-rfc822.c index 78dfe3f45d..06f7e49603 100644 --- a/em-format/e-mail-formatter-message-rfc822.c +++ b/em-format/e-mail-formatter-message-rfc822.c @@ -74,7 +74,8 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, return FALSE; if (context->mode == E_MAIL_FORMATTER_MODE_RAW) { - GSList *iter; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; gchar *header, *end; header = e_mail_formatter_get_html_header (formatter); @@ -84,35 +85,36 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, /* Print content of the message normally */ context->mode = E_MAIL_FORMATTER_MODE_NORMAL; - iter = e_mail_part_list_get_iter ( - context->part_list->list, part->id); + e_mail_part_list_queue_parts ( + context->part_list, part->id, &queue); + + /* Discard the first EMailPart. */ + if (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + + head = g_queue_peek_head_link (&queue); end = g_strconcat (part->id, ".end", NULL); - for (iter = g_slist_next (iter); iter; iter = g_slist_next (iter)) { - EMailPart * p = iter->data; - if (!p) - continue; + + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *p = link->data; /* Check for nested rfc822 messages */ if (g_str_has_suffix (p->id, ".rfc822")) { gchar *sub_end = g_strconcat (p->id, ".end", NULL); - while (iter) { - p = iter->data; - if (!p) { - iter = iter->next; - continue; - } + while (link != NULL) { + p = link->data; - if (g_strcmp0 (p->id, sub_end) == 0) { + if (g_strcmp0 (p->id, sub_end) == 0) break; - } - iter = iter->next; + link = g_list_next (link); } g_free (sub_end); continue; } + if ((g_strcmp0 (p->id, end) == 0)) break; @@ -122,35 +124,41 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, e_mail_formatter_format_as ( formatter, context, p, stream, NULL, cancellable); - } g_free (end); + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + context->mode = E_MAIL_FORMATTER_MODE_RAW; camel_stream_write_string (stream, "</body></html>", cancellable, NULL); } else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) { - - GSList *iter; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; gchar *end; /* Part is EMailPartAttachment */ - iter = e_mail_part_list_get_iter ( - context->part_list->list, part->id); - iter = g_slist_next (iter); + e_mail_part_list_queue_parts ( + context->part_list, part->id, &queue); + + /* Discard the first EMailPart. */ + if (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); - if (!iter || !iter->next || !iter->data) + if (g_queue_is_empty (&queue)) return FALSE; - part = iter->data; + part = g_queue_pop_head (&queue); end = g_strconcat (part->id, ".end", NULL); + e_mail_part_unref (part); - for (iter = iter->next; iter; iter = g_slist_next (iter)) { - EMailPart * p = iter->data; - if (!p) - continue; + head = g_queue_peek_head_link (&queue); + + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *p = link->data; /* Skip attachment bar */ if (g_str_has_suffix (part->id, ".attachment-bar")) @@ -160,18 +168,13 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, if (g_str_has_suffix (p->id, ".rfc822")) { gchar *sub_end = g_strconcat (p->id, ".end", NULL); - while (iter) { - p = iter->data; - if (!p) { - iter = iter->next; - continue; - } + while (link != NULL) { + p = link->data; - if (g_strcmp0 (p->id, sub_end) == 0) { + if (g_strcmp0 (p->id, sub_end) == 0) break; - } - iter = iter->next; + link = g_list_next (link); } g_free (sub_end); continue; @@ -190,24 +193,22 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, g_free (end); + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + } else { + EMailPart *p; CamelFolder *folder; const gchar *message_uid; gchar *str; gchar *uri; - EMailPart *p; - GSList *iter; - - iter = e_mail_part_list_get_iter ( - context->part_list->list, part->id); - if (!iter || !iter->next) + p = e_mail_part_list_ref_part (context->part_list, part->id); + if (p == NULL) return FALSE; - p = iter->data; - - folder = context->part_list->folder; - message_uid = context->part_list->message_uid; + folder = e_mail_part_list_get_folder (context->part_list); + message_uid = e_mail_part_list_get_message_uid (context->part_list); uri = e_mail_part_build_uri ( folder, message_uid, @@ -235,6 +236,8 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension, g_free (str); g_free (uri); + + e_mail_part_unref (p); } return TRUE; diff --git a/em-format/e-mail-formatter-print-headers.c b/em-format/e-mail-formatter-print-headers.c index 8cda0e598f..03ba7b2ccd 100644 --- a/em-format/e-mail-formatter-print-headers.c +++ b/em-format/e-mail-formatter-print-headers.c @@ -74,11 +74,11 @@ emfpe_headers_format (EMailFormatterExtension *extension, GString *str, *tmp; gchar *subject; const gchar *buf; - GSList *parts_iter; - GList *iter; gint attachments_count; gchar *part_id_prefix; const GQueue *headers; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; buf = camel_medium_get_header (CAMEL_MEDIUM (part->part), "subject"); subject = camel_header_decode_string (buf, "UTF-8"); @@ -92,9 +92,8 @@ emfpe_headers_format (EMailFormatterExtension *extension, "cellpadding=\"0\" class=\"printing-header\">\n"); headers = e_mail_formatter_get_headers (formatter); - for (iter = headers->head; iter; iter = iter->next) { - - EMailFormatterHeader *header = iter->data; + for (link = headers->head; link != NULL; link = g_list_next (link)) { + EMailFormatterHeader *header = link->data; raw_header.name = header->name; /* Skip 'Subject' header, it's already displayed. */ @@ -111,7 +110,7 @@ emfpe_headers_format (EMailFormatterExtension *extension, CamelMimeMessage *message; const gchar *header_value; - message = context->part_list->message; + message = e_mail_part_list_get_message (context->part_list); header_value = camel_medium_get_header ( CAMEL_MEDIUM (message), header->name); @@ -135,12 +134,14 @@ emfpe_headers_format (EMailFormatterExtension *extension, /* Add encryption/signature header */ raw_header.name = _("Security"); tmp = g_string_new (""); - /* Find first secured part. */ - for (parts_iter = context->part_list->list; parts_iter; parts_iter = parts_iter->next) { - EMailPart *mail_part = parts_iter->data; - if (mail_part == NULL) - continue; + e_mail_part_list_queue_parts (context->part_list, NULL, &queue); + + head = g_queue_peek_head_link (&queue); + + /* Find first secured part. */ + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; if (!mail_part->validities) continue; @@ -185,11 +186,8 @@ emfpe_headers_format (EMailFormatterExtension *extension, /* Count attachments and display the number as a header */ attachments_count = 0; - for (parts_iter = context->part_list->list; parts_iter; parts_iter = parts_iter->next) { - - EMailPart *mail_part = parts_iter->data; - if (!mail_part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *mail_part = link->data; if (!g_str_has_prefix (mail_part->id, part_id_prefix)) continue; @@ -210,6 +208,9 @@ emfpe_headers_format (EMailFormatterExtension *extension, g_free (raw_header.value); } + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + g_string_append (str, "</table>"); camel_stream_write_string (stream, str->str, cancellable, NULL); diff --git a/em-format/e-mail-formatter-print.c b/em-format/e-mail-formatter-print.c index 9a57c1f6b5..62e4693cc4 100644 --- a/em-format/e-mail-formatter-print.c +++ b/em-format/e-mail-formatter-print.c @@ -99,7 +99,8 @@ mail_formatter_print_run (EMailFormatter *formatter, CamelStream *stream, GCancellable *cancellable) { - GSList *list, *link; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; GSList *attachments; context->mode = E_MAIL_FORMATTER_MODE_PRINTING; @@ -116,18 +117,18 @@ mail_formatter_print_run (EMailFormatter *formatter, cancellable, NULL); attachments = NULL; - list = context->part_list->list; - for (link = list; link != NULL ; link = g_slist_next (link)) { + e_mail_part_list_queue_parts (context->part_list, NULL, &queue); + + head = g_queue_peek_head_link (&queue); + + for (link = head; link != NULL ; link = g_list_next (link)) { EMailPart *part = link->data; gboolean ok; if (g_cancellable_is_cancelled (cancellable)) break; - if (part == NULL) - continue; - if (part->is_hidden && !part->is_error) { if (g_str_has_suffix (part->id, ".rfc822")) { link = e_mail_formatter_find_rfc822_end_iter (link); @@ -161,6 +162,9 @@ mail_formatter_print_run (EMailFormatter *formatter, } } + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + write_attachments_list (formatter, context, attachments, stream, cancellable); g_slist_free (attachments); diff --git a/em-format/e-mail-formatter-quote-attachment.c b/em-format/e-mail-formatter-quote-attachment.c index 5f88d97bff..822c93fc2b 100644 --- a/em-format/e-mail-formatter-quote-attachment.c +++ b/em-format/e-mail-formatter-quote-attachment.c @@ -71,21 +71,18 @@ emfqe_attachment_format (EMailFormatterExtension *extension, gchar *text, *html; guint32 text_format_flags; EMailPartAttachment *empa; - EMailPart *att_part; - GSList *iter; + EMailPart *attachment_view_part; empa = E_MAIL_PART_ATTACHMENT (part); if (!empa->attachment_view_part_id) return FALSE; - iter = e_mail_part_list_get_iter ( - context->part_list->list, empa->attachment_view_part_id); - if (!iter || !iter->data) + attachment_view_part = e_mail_part_list_ref_part ( + context->part_list, empa->attachment_view_part_id); + if (attachment_view_part == NULL) return FALSE; - att_part = iter->data; - camel_stream_write_string (stream, "<br><br>", cancellable, NULL); text_format_flags = @@ -110,7 +107,8 @@ emfqe_attachment_format (EMailFormatterExtension *extension, "<blockquote type=cite>\n", cancellable, NULL); e_mail_formatter_format_as ( - formatter, context, att_part, stream, NULL, cancellable); + formatter, context, attachment_view_part, + stream, NULL, cancellable); camel_stream_write_string ( stream, @@ -118,6 +116,8 @@ emfqe_attachment_format (EMailFormatterExtension *extension, "<DATA class=\"ClueFlow\" clear=\"orig\">-->", cancellable, NULL); + e_mail_part_unref (attachment_view_part); + return TRUE; } diff --git a/em-format/e-mail-formatter-quote-message-rfc822.c b/em-format/e-mail-formatter-quote-message-rfc822.c index 037b5b4b71..2bb8de9eb2 100644 --- a/em-format/e-mail-formatter-quote-message-rfc822.c +++ b/em-format/e-mail-formatter-quote-message-rfc822.c @@ -70,7 +70,8 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension, CamelStream *stream, GCancellable *cancellable) { - GSList *iter; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; gchar *header, *end; EMailFormatterQuoteContext *qc = (EMailFormatterQuoteContext *) context; @@ -81,16 +82,20 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension, camel_stream_write_string (stream, header, cancellable, NULL); g_free (header); - iter = e_mail_part_list_get_iter (context->part_list->list, part->id); - if (!iter) { + e_mail_part_list_queue_parts (context->part_list, part->id, &queue); + + if (g_queue_is_empty (&queue)) return FALSE; - } + + /* Discard the first EMailPart. */ + e_mail_part_unref (g_queue_pop_head (&queue)); + + head = g_queue_peek_head (&queue); end = g_strconcat (part->id, ".end", NULL); - for (iter = g_slist_next (iter); iter; iter = g_slist_next (iter)) { - EMailPart * p = iter->data; - if (!p) - continue; + + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *p = link->data; /* Skip attachment bar */ if (g_str_has_suffix (p->id, ".attachment-bar")) @@ -111,28 +116,18 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension, if (g_str_has_suffix (p->id, ".rfc822")) { gchar *sub_end = g_strconcat (p->id, ".end", NULL); - while (iter) { - p = iter->data; - if (!p) { - iter = g_slist_next (iter); - if (!iter) { - break; - } - continue; - } - - if (g_strcmp0 (p->id, sub_end) == 0) { - break; - } + while (link != NULL) { + p = link->data; - iter = g_slist_next (iter); - if (!iter) { + if (g_strcmp0 (p->id, sub_end) == 0) break; - } + + link = g_list_next (link); } g_free (sub_end); continue; } + if ((g_strcmp0 (p->id, end) == 0)) break; @@ -142,11 +137,13 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension, e_mail_formatter_format_as ( formatter, context, p, stream, NULL, cancellable); - } g_free (end); + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + camel_stream_write_string (stream, "</body></html>", cancellable, NULL); return TRUE; diff --git a/em-format/e-mail-formatter-quote.c b/em-format/e-mail-formatter-quote.c index fcd2a06b48..3cd0121b72 100644 --- a/em-format/e-mail-formatter-quote.c +++ b/em-format/e-mail-formatter-quote.c @@ -50,7 +50,8 @@ mail_formatter_quote_run (EMailFormatter *formatter, EMailFormatterQuote *qf; EMailFormatterQuoteContext *qf_context; GSettings *settings; - GSList *list, *link; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; if (g_cancellable_is_cancelled (cancellable)) return; @@ -87,13 +88,12 @@ mail_formatter_quote_run (EMailFormatter *formatter, "<blockquote type=cite>\n", cancellable, NULL); } - list = context->part_list->list; + e_mail_part_list_queue_parts (context->part_list, NULL, &queue); - for (link = list; link != NULL; link = g_slist_next (link)) { - EMailPart *part = link->data; + head = g_queue_peek_head_link (&queue); - if (!part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; if (g_str_has_suffix (part->id, ".headers") && !(qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS)) { @@ -105,17 +105,11 @@ mail_formatter_quote_run (EMailFormatter *formatter, while (link != NULL) { EMailPart *p = link->data; - if (p == NULL) { - link = g_slist_next (link); - if (link == NULL) - break; - continue; - } if (g_strcmp0 (p->id, end) == 0) break; - link = g_slist_next (link); + link = g_list_next (link); if (link == NULL) break; } @@ -132,6 +126,9 @@ mail_formatter_quote_run (EMailFormatter *formatter, part->mime_type, cancellable); } + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + if (qf->priv->flags & E_MAIL_FORMATTER_QUOTE_FLAG_CITE) { camel_stream_write_string ( stream, "</blockquote><!--+GtkHTML:" diff --git a/em-format/e-mail-formatter-text-html.c b/em-format/e-mail-formatter-text-html.c index 2b6fccd127..eef51d4bad 100644 --- a/em-format/e-mail-formatter-text-html.c +++ b/em-format/e-mail-formatter-text-html.c @@ -312,8 +312,8 @@ emfe_text_html_format (EMailFormatterExtension *extension, const gchar *message_uid; gchar *uri, *str; - folder = context->part_list->folder; - message_uid = context->part_list->message_uid; + folder = e_mail_part_list_get_folder (context->part_list); + message_uid = e_mail_part_list_get_message_uid (context->part_list); uri = e_mail_part_build_uri ( folder, message_uid, diff --git a/em-format/e-mail-formatter-text-plain.c b/em-format/e-mail-formatter-text-plain.c index 74e7f2dc3b..c5770f017a 100644 --- a/em-format/e-mail-formatter-text-plain.c +++ b/em-format/e-mail-formatter-text-plain.c @@ -150,8 +150,8 @@ emfe_text_plain_format (EMailFormatterExtension *extension, const gchar *message_uid; gchar *uri, *str; - folder = context->part_list->folder; - message_uid = context->part_list->message_uid; + folder = e_mail_part_list_get_folder (context->part_list); + message_uid = e_mail_part_list_get_message_uid (context->part_list); uri = e_mail_part_build_uri ( folder, message_uid, diff --git a/em-format/e-mail-formatter-utils.c b/em-format/e-mail-formatter-utils.c index 7c01f323bb..11dcc0e10b 100644 --- a/em-format/e-mail-formatter-utils.c +++ b/em-format/e-mail-formatter-utils.c @@ -419,15 +419,15 @@ e_mail_formatter_format_header (EMailFormatter *formatter, g_free (str_field); } -GSList * -e_mail_formatter_find_rfc822_end_iter (GSList *iter) +GList * +e_mail_formatter_find_rfc822_end_iter (GList *iter) { EMailPart *part; gchar *end; part = iter->data; end = g_strconcat (part->id, ".end", NULL); - for (; iter != NULL; iter = g_slist_next (iter)) { + for (; iter != NULL; iter = g_list_next (iter)) { part = iter->data; if (!part) continue; diff --git a/em-format/e-mail-formatter-utils.h b/em-format/e-mail-formatter-utils.h index e89c3f42b4..381b805917 100644 --- a/em-format/e-mail-formatter-utils.h +++ b/em-format/e-mail-formatter-utils.h @@ -48,8 +48,8 @@ gchar * e_mail_formatter_format_address (EMailFormatter *formatter, void e_mail_formatter_canon_header_name (gchar *name); -GSList * e_mail_formatter_find_rfc822_end_iter - (GSList *rfc822_start_iter); +GList * e_mail_formatter_find_rfc822_end_iter + (GList *rfc822_start_iter); gchar * e_mail_formatter_parse_html_mnemonics (const gchar *label, diff --git a/em-format/e-mail-formatter.c b/em-format/e-mail-formatter.c index f878841836..c3a20855a6 100644 --- a/em-format/e-mail-formatter.c +++ b/em-format/e-mail-formatter.c @@ -366,26 +366,25 @@ mail_formatter_run (EMailFormatter *formatter, CamelStream *stream, GCancellable *cancellable) { - GSList *list, *link; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; gchar *hdr; hdr = e_mail_formatter_get_html_header (formatter); camel_stream_write_string (stream, hdr, cancellable, NULL); g_free (hdr); - list = context->part_list->list; + e_mail_part_list_queue_parts (context->part_list, NULL, &queue); - for (link = list; link != NULL; link = g_slist_next (link)) { + head = g_queue_peek_head_link (&queue); + for (link = head; link != NULL; link = g_list_next (link)) { EMailPart *part = link->data; gboolean ok; if (g_cancellable_is_cancelled (cancellable)) break; - if (part == NULL) - continue; - if (part->is_hidden && !part->is_error) { if (g_str_has_suffix (part->id, ".rfc822")) { link = e_mail_formatter_find_rfc822_end_iter (link); @@ -446,10 +445,10 @@ mail_formatter_run (EMailFormatter *formatter, do { part = link->data; - if (part && g_str_has_suffix (part->id, ".rfc822.end")) + if (g_str_has_suffix (part->id, ".rfc822.end")) break; - link = g_slist_next (link); + link = g_list_next (link); } while (link != NULL); if (link == NULL) @@ -458,6 +457,9 @@ mail_formatter_run (EMailFormatter *formatter, } } + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + camel_stream_write_string (stream, "</body></html>", cancellable, NULL); } diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c index 6e0791e0d9..8e5ccd4ef8 100644 --- a/em-format/e-mail-parser.c +++ b/em-format/e-mail-parser.c @@ -61,10 +61,14 @@ mail_parser_run (EMailParser *parser, GCancellable *cancellable) { EMailExtensionRegistry *reg; + CamelMimeMessage *message; EMailPart *part; GQueue *parsers; GList *iter; GString *part_id; + GSList *list_of_parts; + + message = e_mail_part_list_get_message (part_list); reg = e_mail_parser_get_extension_registry (parser); @@ -81,8 +85,11 @@ mail_parser_run (EMailParser *parser, part_id = g_string_new (".message"); - for (iter = parsers->head; iter; iter = iter->next) { + part = e_mail_part_new (CAMEL_MIME_PART (message), ".message"); + e_mail_part_list_add_part (part_list, part); + e_mail_part_unref (part); + for (iter = parsers->head; iter; iter = iter->next) { EMailParserExtension *extension; if (g_cancellable_is_cancelled (cancellable)) @@ -92,18 +99,25 @@ mail_parser_run (EMailParser *parser, if (!extension) continue; - part_list->list = e_mail_parser_extension_parse ( + list_of_parts = e_mail_parser_extension_parse ( extension, parser, - CAMEL_MIME_PART (part_list->message), + CAMEL_MIME_PART (message), part_id, cancellable); - if (part_list->list != NULL) + if (list_of_parts != NULL) break; } - part = e_mail_part_new ( - CAMEL_MIME_PART (part_list->message), ".message"); - part_list->list = g_slist_prepend (part_list->list, part); + 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); + } g_string_free (part_id, TRUE); } @@ -282,32 +296,30 @@ e_mail_parser_parse_sync (EMailParser *parser, g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL); g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL); - part_list = e_mail_part_list_new (); - - if (folder != NULL) - part_list->folder = g_object_ref (folder); - - part_list->message_uid = g_strdup (message_uid); - part_list->message = g_object_ref (message); + part_list = e_mail_part_list_new (message, message_uid, folder); mail_parser_run (parser, part_list, cancellable); if (camel_debug_start ("emformat:parser")) { - GSList *iter; + GQueue queue = G_QUEUE_INIT; printf ( "%s finished with EMailPartList:\n", G_OBJECT_TYPE_NAME (parser)); - for (iter = part_list->list; iter; iter = iter->next) { - EMailPart *part = iter->data; - if (!part) continue; + e_mail_part_list_queue_parts (part_list, NULL, &queue); + + while (!g_queue_is_empty (&queue)) { + EMailPart *part = g_queue_pop_head (&queue); + printf ( " id: %s | cid: %s | mime_type: %s | " "is_hidden: %d | is_attachment: %d\n", part->id, part->cid, part->mime_type, part->is_hidden ? 1 : 0, part->is_attachment ? 1 : 0); + + e_mail_part_unref (part); } camel_debug_end (); @@ -355,11 +367,7 @@ e_mail_parser_parse (EMailParser *parser, g_return_if_fail (E_IS_MAIL_PARSER (parser)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); - part_list = e_mail_part_list_new (); - part_list->message = g_object_ref (message); - part_list->message_uid = g_strdup (message_uid); - if (folder != NULL) - part_list->folder = g_object_ref (folder); + part_list = e_mail_part_list_new (message, message_uid, folder); simple = g_simple_async_result_new ( G_OBJECT (parser), callback, @@ -393,21 +401,25 @@ e_mail_parser_parse_finish (EMailParser *parser, part_list = g_simple_async_result_get_op_res_gpointer (simple); if (camel_debug_start ("emformat:parser")) { - GSList *iter; + GQueue queue = G_QUEUE_INIT; printf ( "%s finished with EMailPartList:\n", G_OBJECT_TYPE_NAME (parser)); - for (iter = part_list->list; iter; iter = iter->next) { - EMailPart *part = iter->data; - if (!part) continue; + e_mail_part_list_queue_parts (part_list, NULL, &queue); + + while (!g_queue_is_empty (&queue)) { + EMailPart *part = g_queue_pop_head (&queue); + printf ( " id: %s | cid: %s | mime_type: %s | " "is_hidden: %d | is_attachment: %d\n", part->id, part->cid, part->mime_type, part->is_hidden ? 1 : 0, part->is_attachment ? 1 : 0); + + e_mail_part_unref (part); } camel_debug_end (); diff --git a/em-format/e-mail-part-list.c b/em-format/e-mail-part-list.c index 38beeea6e2..641a88c947 100644 --- a/em-format/e-mail-part-list.c +++ b/em-format/e-mail-part-list.c @@ -20,36 +20,167 @@ #include "e-mail-part-list.h" +#define E_MAIL_PART_LIST_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_PART_LIST, EMailPartListPrivate)) + +struct _EMailPartListPrivate { + CamelFolder *folder; + CamelMimeMessage *message; + gchar *message_uid; + + GQueue queue; + GMutex queue_lock; +}; + +enum { + PROP_0, + PROP_FOLDER, + PROP_MESSAGE, + PROP_MESSAGE_UID +}; + G_DEFINE_TYPE (EMailPartList, e_mail_part_list, G_TYPE_OBJECT) static CamelObjectBag *registry = NULL; G_LOCK_DEFINE_STATIC (registry); static void -unref_mail_part (gpointer user_data) +mail_part_list_set_folder (EMailPartList *part_list, + CamelFolder *folder) { - if (user_data) - e_mail_part_unref (user_data); + g_return_if_fail (part_list->priv->folder == NULL); + + /* The folder property is optional. */ + if (folder != NULL) { + g_return_if_fail (CAMEL_IS_FOLDER (folder)); + part_list->priv->folder = g_object_ref (folder); + } } static void -e_mail_part_list_finalize (GObject *object) +mail_part_list_set_message (EMailPartList *part_list, + CamelMimeMessage *message) { - EMailPartList *part_list = E_MAIL_PART_LIST (object); + g_return_if_fail (part_list->priv->message == NULL); - g_clear_object (&part_list->folder); - g_clear_object (&part_list->message); + /* The message property is optional. */ + if (message != NULL) { + g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); + part_list->priv->message = g_object_ref (message); + } +} + +static void +mail_part_list_set_message_uid (EMailPartList *part_list, + const gchar *message_uid) +{ + g_return_if_fail (part_list->priv->message_uid == NULL); - if (part_list->list) { - g_slist_free_full (part_list->list, unref_mail_part); - part_list->list = NULL; + /* The message_uid property is optional. */ + part_list->priv->message_uid = g_strdup (message_uid); +} + +static void +mail_part_list_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER: + mail_part_list_set_folder ( + E_MAIL_PART_LIST (object), + g_value_get_object (value)); + return; + + case PROP_MESSAGE: + mail_part_list_set_message ( + E_MAIL_PART_LIST (object), + g_value_get_object (value)); + return; + + case PROP_MESSAGE_UID: + mail_part_list_set_message_uid ( + E_MAIL_PART_LIST (object), + g_value_get_string (value)); + return; } - if (part_list->message_uid) { - g_free (part_list->message_uid); - part_list->message_uid = NULL; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_part_list_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER: + g_value_set_object ( + value, + e_mail_part_list_get_folder ( + E_MAIL_PART_LIST (object))); + return; + + case PROP_MESSAGE: + g_value_set_object ( + value, + e_mail_part_list_get_message ( + E_MAIL_PART_LIST (object))); + return; + + case PROP_MESSAGE_UID: + g_value_set_string ( + value, + e_mail_part_list_get_message_uid ( + E_MAIL_PART_LIST (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_part_list_dispose (GObject *object) +{ + EMailPartListPrivate *priv; + + priv = E_MAIL_PART_LIST_GET_PRIVATE (object); + + if (priv->folder != NULL) { + g_object_unref (priv->folder); + priv->folder = NULL; } + if (priv->message != NULL) { + g_object_unref (priv->message); + priv->message = NULL; + } + + g_mutex_lock (&priv->queue_lock); + while (!g_queue_is_empty (&priv->queue)) + e_mail_part_unref (g_queue_pop_head (&priv->queue)); + g_mutex_unlock (&priv->queue_lock); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_part_list_parent_class)->dispose (object); +} + +static void +mail_part_list_finalize (GObject *object) +{ + EMailPartListPrivate *priv; + + priv = E_MAIL_PART_LIST_GET_PRIVATE (object); + + g_free (priv->message_uid); + + g_warn_if_fail (g_queue_is_empty (&priv->queue)); + g_mutex_clear (&priv->queue_lock); + + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_mail_part_list_parent_class)->finalize (object); } @@ -58,78 +189,206 @@ e_mail_part_list_class_init (EMailPartListClass *class) { GObjectClass *object_class; + g_type_class_add_private (class, sizeof (EMailPartListPrivate)); + object_class = G_OBJECT_CLASS (class); - object_class->finalize = e_mail_part_list_finalize; + object_class->set_property = mail_part_list_set_property; + object_class->get_property = mail_part_list_get_property; + object_class->dispose = mail_part_list_dispose; + object_class->finalize = mail_part_list_finalize; + + g_object_class_install_property ( + object_class, + PROP_FOLDER, + g_param_spec_object ( + "folder", + "Folder", + NULL, + CAMEL_TYPE_FOLDER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_MESSAGE, + g_param_spec_object ( + "message", + "Message", + NULL, + CAMEL_TYPE_MIME_MESSAGE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_MESSAGE_UID, + g_param_spec_string ( + "message-uid", + "Message UID", + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } static void e_mail_part_list_init (EMailPartList *part_list) { + part_list->priv = E_MAIL_PART_LIST_GET_PRIVATE (part_list); + g_mutex_init (&part_list->priv->queue_lock); } EMailPartList * -e_mail_part_list_new () +e_mail_part_list_new (CamelMimeMessage *message, + const gchar *message_uid, + CamelFolder *folder) +{ + if (message != NULL) + g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL); + + if (folder != NULL) + g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL); + + return g_object_new ( + E_TYPE_MAIL_PART_LIST, + "message", message, + "message-uid", message_uid, + "folder", folder, NULL); +} + +CamelFolder * +e_mail_part_list_get_folder (EMailPartList *part_list) +{ + g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL); + + return part_list->priv->folder; +} + +CamelMimeMessage * +e_mail_part_list_get_message (EMailPartList *part_list) +{ + g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL); + + return part_list->priv->message; +} + +const gchar * +e_mail_part_list_get_message_uid (EMailPartList *part_list) { - return g_object_new (E_TYPE_MAIL_PART_LIST, NULL); + g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL); + + return part_list->priv->message_uid; +} + +void +e_mail_part_list_add_part (EMailPartList *part_list, + EMailPart *part) +{ + g_return_if_fail (E_IS_MAIL_PART_LIST (part_list)); + g_return_if_fail (part != NULL); + + g_mutex_lock (&part_list->priv->queue_lock); + + g_queue_push_tail ( + &part_list->priv->queue, + e_mail_part_ref (part)); + + g_mutex_unlock (&part_list->priv->queue_lock); } EMailPart * -e_mail_part_list_find_part (EMailPartList *part_list, - const gchar *id) +e_mail_part_list_ref_part (EMailPartList *part_list, + const gchar *part_id) { - GSList *iter; + EMailPart *match = NULL; + GList *head, *link; gboolean by_cid; g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL); - g_return_val_if_fail (id && *id, NULL); + g_return_val_if_fail (part_id != NULL, NULL); - by_cid = (g_str_has_prefix (id, "cid:") || g_str_has_prefix (id, "CID:")); + by_cid = (g_ascii_strncasecmp (part_id, "cid:", 4) == 0); - for (iter = part_list->list; iter; iter = iter->next) { + g_mutex_lock (&part_list->priv->queue_lock); - EMailPart *part = iter->data; - if (!part) - continue; + head = g_queue_peek_head_link (&part_list->priv->queue); + + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; - if ((by_cid && (g_strcmp0 (part->cid, id) == 0)) || - (!by_cid && (g_strcmp0 (part->id, id) == 0))) - return part; + if (by_cid && (g_strcmp0 (part->cid, part_id) == 0)) { + match = e_mail_part_ref (part); + break; + } + + if (!by_cid && (g_strcmp0 (part->id, part_id) == 0)) { + match = e_mail_part_ref (part); + break; + } } - return NULL; + g_mutex_unlock (&part_list->priv->queue_lock); + + return match; } /** - * e_mail_part_list_get_iter: - * @part_list: a #GSList of #EMailPart - * @id: id of #EMailPart to lookup + * e_mail_part_list_queue_parts: + * @part_list: an #EMailPartList + * @part_id: the #EMailPart ID to begin queueing from, or %NULL + * @result_queue: a #GQueue in which to deposit #EMailPart instances * - * Returns iter of an #EMailPart within the @part_list. + * Populates @result_queue with a sequence of #EMailPart instances beginning + * with the part having @part_id. If @part_id is %NULL, the entire sequence + * of #EMailPart instances is queued. * - * Return Value: a #GSList sublist. The list is owned by #EMailPartList and - * must not be freed or altered. - */ -GSList * -e_mail_part_list_get_iter (GSList *list, - const gchar *id) + * Each #EMailPart is referenced for thread-safety and should be unreferenced + * with e_mail_part_unref(). + * + * Returns: the number of parts added to @result_queue + **/ +guint +e_mail_part_list_queue_parts (EMailPartList *part_list, + const gchar *part_id, + GQueue *result_queue) { - GSList *iter; + GList *link; + guint parts_queued = 0; + + g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), FALSE); + g_return_val_if_fail (result_queue != NULL, FALSE); - g_return_val_if_fail (list != NULL, NULL); - g_return_val_if_fail (id && *id, NULL); + g_mutex_lock (&part_list->priv->queue_lock); - for (iter = list; iter; iter = iter->next) { + link = g_queue_peek_head_link (&part_list->priv->queue); - EMailPart *part = iter->data; - if (!part) + if (part_id != NULL) { + for (; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; + + if (g_strcmp0 (part->id, part_id) == 0) + break; + } + } + + /* We skip the loop entirely if link is NULL. */ + for (; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; + + if (part == NULL) continue; - if (g_strcmp0 (part->id, id) == 0) - return iter; + g_queue_push_tail (result_queue, e_mail_part_ref (part)); + parts_queued++; } - return NULL; + g_mutex_unlock (&part_list->priv->queue_lock); + + return parts_queued; } /** diff --git a/em-format/e-mail-part-list.h b/em-format/e-mail-part-list.h index c6f952eab3..3694075100 100644 --- a/em-format/e-mail-part-list.h +++ b/em-format/e-mail-part-list.h @@ -16,8 +16,8 @@ * */ -#ifndef E_MAIL_PART_LIST_H_ -#define E_MAIL_PART_LIST_H_ +#ifndef E_MAIL_PART_LIST_H +#define E_MAIL_PART_LIST_H #include <camel/camel.h> #include <em-format/e-mail-part.h> @@ -45,35 +45,37 @@ G_BEGIN_DECLS typedef struct _EMailPartList EMailPartList; typedef struct _EMailPartListClass EMailPartListClass; +typedef struct _EMailPartListPrivate EMailPartListPrivate; struct _EMailPartList { GObject parent; - - CamelMimeMessage *message; - CamelFolder *folder; - gchar *message_uid; - - /* GSList of EMailPart's */ - GSList *list; + EMailPartListPrivate *priv; }; struct _EMailPartListClass { GObjectClass parent_class; }; -EMailPartList * e_mail_part_list_new (void); - -GType e_mail_part_list_get_type (void); - -EMailPart * e_mail_part_list_find_part (EMailPartList *part_list, - const gchar *id); - -GSList * e_mail_part_list_get_iter (GSList *list, - const gchar *id); +GType e_mail_part_list_get_type (void) G_GNUC_CONST; +EMailPartList * e_mail_part_list_new (CamelMimeMessage *message, + const gchar *message_uid, + CamelFolder *folder); +CamelFolder * e_mail_part_list_get_folder (EMailPartList *part_list); +CamelMimeMessage * + e_mail_part_list_get_message (EMailPartList *part_list); +const gchar * e_mail_part_list_get_message_uid + (EMailPartList *part_list); +void e_mail_part_list_add_part (EMailPartList *part_list, + EMailPart *part); +EMailPart * e_mail_part_list_ref_part (EMailPartList *part_list, + const gchar *part_id); +guint e_mail_part_list_queue_parts (EMailPartList *part_list, + const gchar *part_id, + GQueue *result_queue); CamelObjectBag * e_mail_part_list_get_registry (void); G_END_DECLS -#endif /* E_MAIL_PART_LIST_H_ */ +#endif /* E_MAIL_PART_LIST_H */ |