aboutsummaryrefslogtreecommitdiffstats
path: root/em-format
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-12-05 21:19:04 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-12-08 03:01:04 +0800
commit91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8 (patch)
tree1c06f36fa153eee0779cdfa1be1a24f62e93787d /em-format
parent2f0d83cf74b94d5e6272c07179df6e6c7a929789 (diff)
downloadgsoc2013-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.c48
-rw-r--r--em-format/e-mail-formatter-message-rfc822.c97
-rw-r--r--em-format/e-mail-formatter-print-headers.c33
-rw-r--r--em-format/e-mail-formatter-print.c16
-rw-r--r--em-format/e-mail-formatter-quote-attachment.c16
-rw-r--r--em-format/e-mail-formatter-quote-message-rfc822.c47
-rw-r--r--em-format/e-mail-formatter-quote.c23
-rw-r--r--em-format/e-mail-formatter-text-html.c4
-rw-r--r--em-format/e-mail-formatter-text-plain.c4
-rw-r--r--em-format/e-mail-formatter-utils.c6
-rw-r--r--em-format/e-mail-formatter-utils.h4
-rw-r--r--em-format/e-mail-formatter.c18
-rw-r--r--em-format/e-mail-parser.c66
-rw-r--r--em-format/e-mail-part-list.c355
-rw-r--r--em-format/e-mail-part-list.h40
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 */