Commit 91822b42 authored by Matthew Barnes's avatar Matthew Barnes
Browse files

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.
parent 2f0d83cf
......@@ -194,6 +194,7 @@ emcu_part_to_html (CamelSession *session,
GString *part_id;
EShell *shell;
GtkWindow *window;
GSList *list;
shell = e_shell_get_default ();
window = e_shell_get_active_window (shell);
......@@ -202,22 +203,31 @@ emcu_part_to_html (CamelSession *session,
mem = (CamelStreamMem *) camel_stream_mem_new ();
camel_stream_mem_set_byte_array (mem, buf);
part_list = e_mail_part_list_new ();
part_list = e_mail_part_list_new (NULL, NULL, NULL);
part_id = g_string_sized_new (0);
parser = e_mail_parser_new (session);
part_list->list = e_mail_parser_parse_part (parser, part, part_id, cancellable);
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);
}
g_string_free (part_id, TRUE);
g_object_unref (parser);
formatter = e_mail_formatter_quote_new (NULL, E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG);
e_mail_formatter_set_style (formatter,
gtk_widget_get_style (GTK_WIDGET (window)),
gtk_widget_get_state (GTK_WIDGET (window)));
formatter = e_mail_formatter_quote_new (
NULL, E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG);
e_mail_formatter_set_style (
formatter,
gtk_widget_get_style (GTK_WIDGET (window)),
gtk_widget_get_state (GTK_WIDGET (window)));
e_mail_formatter_format_sync (
formatter, part_list, (CamelStream *) mem,
0, E_MAIL_FORMATTER_MODE_PRINTING, cancellable);
0, E_MAIL_FORMATTER_MODE_PRINTING, cancellable);
g_object_unref (formatter);
g_object_unref (part_list);
......
......@@ -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 (
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;