[evolution] Bug #690092 - Crash under format_full_headers()



commit 0d96f08f9f0400ab9202f1dcdbaca1d891a41ac8
Author: Milan Crha <mcrha redhat com>
Date:   Wed Mar 6 19:37:37 2013 +0100

    Bug #690092 - Crash under format_full_headers()

 em-format/e-mail-formatter-headers.c       |   27 ++++---
 em-format/e-mail-formatter-print-headers.c |    8 +-
 em-format/e-mail-formatter-quote-headers.c |   20 +++--
 em-format/e-mail-formatter-utils.c         |    8 +-
 em-format/e-mail-formatter.c               |  114 +++++++++++++++++++++++++--
 em-format/e-mail-formatter.h               |    4 +
 mail/e-mail-printer.c                      |    8 +-
 7 files changed, 153 insertions(+), 36 deletions(-)
---
diff --git a/em-format/e-mail-formatter-headers.c b/em-format/e-mail-formatter-headers.c
index 7a3a723..ef86c21 100644
--- a/em-format/e-mail-formatter-headers.c
+++ b/em-format/e-mail-formatter-headers.c
@@ -56,7 +56,7 @@ format_short_headers (EMailFormatter *formatter,
 {
        const gchar *charset;
        CamelContentType *ct;
-       const gchar *hdr_charset;
+       gchar *hdr_charset;
        gchar *evolution_imagesdir;
        gchar *subject = NULL;
        struct _camel_header_address *addrs = NULL;
@@ -70,9 +70,9 @@ format_short_headers (EMailFormatter *formatter,
        ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
        charset = camel_content_type_param (ct, "charset");
        charset = camel_iconv_charset_name (charset);
-       hdr_charset = e_mail_formatter_get_charset (formatter) ?
-                       e_mail_formatter_get_charset (formatter) :
-                       e_mail_formatter_get_default_charset (formatter);
+       hdr_charset = e_mail_formatter_dup_charset (formatter);
+       if (!hdr_charset)
+               hdr_charset = e_mail_formatter_dup_default_charset (formatter);
 
        evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
        from = g_string_new ("");
@@ -112,6 +112,8 @@ format_short_headers (EMailFormatter *formatter,
                header = header->next;
        }
 
+       g_free (hdr_charset);
+
        is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
        if (is_rtl) {
                g_string_append_printf (
@@ -241,7 +243,7 @@ format_full_headers (EMailFormatter *formatter,
        gsize face_header_len = 0;
        gchar *header_sender = NULL, *header_from = NULL, *name;
        gboolean mail_from_delegate = FALSE;
-       const gchar *hdr_charset;
+       gchar *hdr_charset;
        gchar *evolution_imagesdir;
 
        if (g_cancellable_is_cancelled (cancellable))
@@ -250,9 +252,9 @@ format_full_headers (EMailFormatter *formatter,
        ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
        charset = camel_content_type_param (ct, "charset");
        charset = camel_iconv_charset_name (charset);
-       hdr_charset = e_mail_formatter_get_charset (formatter) ?
-                       e_mail_formatter_get_charset (formatter) :
-                       e_mail_formatter_get_default_charset (formatter);
+       hdr_charset = e_mail_formatter_dup_charset (formatter);
+       if (!hdr_charset)
+               hdr_charset = e_mail_formatter_dup_default_charset (formatter);
 
        evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
 
@@ -305,6 +307,8 @@ format_full_headers (EMailFormatter *formatter,
                header = header->next;
        }
 
+       g_free (hdr_charset);
+
        if (header_sender && header_from && mail_from_delegate) {
                gchar *bold_sender, *bold_from;
 
@@ -352,11 +356,12 @@ format_full_headers (EMailFormatter *formatter,
                        header = header->next;
                }
        } else {
+               GQueue *headers_queue;
                GList *link;
                gint mailer_shown = FALSE;
 
-               link = g_queue_peek_head_link (
-                               (GQueue *) e_mail_formatter_get_headers (formatter));
+               headers_queue = e_mail_formatter_dup_headers (formatter);
+               link = g_queue_peek_head_link (headers_queue);
 
                while (link != NULL) {
                        EMailFormatterHeader *h = link->data;
@@ -427,6 +432,8 @@ format_full_headers (EMailFormatter *formatter,
 
                        link = g_list_next (link);
                }
+
+               g_queue_free_full (headers_queue, (GDestroyNotify) e_mail_formatter_header_free);
        }
 
        g_string_append (buffer, "</table></td>");
diff --git a/em-format/e-mail-formatter-print-headers.c b/em-format/e-mail-formatter-print-headers.c
index fb19559..a79dfa1 100644
--- a/em-format/e-mail-formatter-print-headers.c
+++ b/em-format/e-mail-formatter-print-headers.c
@@ -61,7 +61,7 @@ emfpe_headers_format (EMailFormatterExtension *extension,
        const gchar *buf;
        gint attachments_count;
        gchar *part_id_prefix;
-       const GQueue *headers;
+       GQueue *headers_queue;
        GQueue queue = G_QUEUE_INIT;
        GList *head, *link;
 
@@ -76,8 +76,8 @@ emfpe_headers_format (EMailFormatterExtension *extension,
                "<table border=\"0\" cellspacing=\"5\" "
                "cellpadding=\"0\" class=\"printing-header\">\n");
 
-       headers = e_mail_formatter_get_headers (formatter);
-       for (link = headers->head; link != NULL; link = g_list_next (link)) {
+       headers_queue = e_mail_formatter_dup_headers (formatter);
+       for (link = headers_queue->head; link != NULL; link = g_list_next (link)) {
                EMailFormatterHeader *header = link->data;
                raw_header.name = header->name;
 
@@ -113,6 +113,8 @@ emfpe_headers_format (EMailFormatterExtension *extension,
                }
        }
 
+       g_queue_free_full (headers_queue, (GDestroyNotify) e_mail_formatter_header_free);
+
         /* Get prefix of this PURI */
        part_id_prefix = g_strndup (part->id, g_strrstr (part->id, ".") - part->id);
 
diff --git a/em-format/e-mail-formatter-quote-headers.c b/em-format/e-mail-formatter-quote-headers.c
index 20e97fd..4a29d84 100644
--- a/em-format/e-mail-formatter-quote-headers.c
+++ b/em-format/e-mail-formatter-quote-headers.c
@@ -121,15 +121,19 @@ emfqe_format_header (EMailFormatter *formatter,
        if (addrspec) {
                struct _camel_header_address *addrs;
                GString *html;
+               gchar *charset;
 
                if (!(txt = camel_medium_get_header (part, name)))
                        return;
 
+               charset = e_mail_formatter_dup_charset (formatter);
+               if (!charset)
+                       charset = e_mail_formatter_dup_default_charset (formatter);
+
                buf = camel_header_unfold (txt);
-               addrs = camel_header_address_decode (
-                       txt, e_mail_formatter_get_charset (formatter) ?
-                       e_mail_formatter_get_charset (formatter) :
-                       e_mail_formatter_get_default_charset (formatter));
+               addrs = camel_header_address_decode (txt, charset);
+               g_free (charset);
+
                if (addrs == NULL) {
                        g_free (buf);
                        return;
@@ -189,7 +193,7 @@ emqfe_headers_format (EMailFormatterExtension *extension,
        const gchar *charset;
        GList *iter;
        GString *buffer;
-       const GQueue *default_headers;
+       GQueue *headers_queue;
 
        if (!part)
                return FALSE;
@@ -201,8 +205,8 @@ emqfe_headers_format (EMailFormatterExtension *extension,
        buffer = g_string_new ("");
 
         /* dump selected headers */
-       default_headers = e_mail_formatter_get_headers (formatter);
-       for (iter = default_headers->head; iter; iter = iter->next) {
+       headers_queue = e_mail_formatter_dup_headers (formatter);
+       for (iter = headers_queue->head; iter; iter = iter->next) {
                struct _camel_header_raw *raw_header;
                EMailFormatterHeader *h = iter->data;
                guint32 flags;
@@ -222,6 +226,8 @@ emqfe_headers_format (EMailFormatterExtension *extension,
                }
        }
 
+       g_queue_free_full (headers_queue, (GDestroyNotify) e_mail_formatter_header_free);
+
        g_string_append (buffer, "<br>\n");
 
        camel_stream_write_string (stream, buffer->str, cancellable, NULL);
diff --git a/em-format/e-mail-formatter-utils.c b/em-format/e-mail-formatter-utils.c
index 5fdb885..a2e0d43 100644
--- a/em-format/e-mail-formatter-utils.c
+++ b/em-format/e-mail-formatter-utils.c
@@ -299,19 +299,21 @@ e_mail_formatter_format_header (EMailFormatter *formatter,
                struct _camel_header_address *addrs;
                GString *html;
                gchar *img;
-               const gchar *charset;
+               gchar *charset;
 
-               charset = e_mail_formatter_get_charset (formatter);
+               charset = e_mail_formatter_dup_charset (formatter);
                if (charset == NULL)
-                       charset = e_mail_formatter_get_default_charset (formatter);
+                       charset = e_mail_formatter_dup_default_charset (formatter);
 
                buf = camel_header_unfold (header->value);
                addrs = camel_header_address_decode (buf, charset);
                if (addrs == NULL) {
+                       g_free (charset);
                        g_free (buf);
                        return;
                }
 
+               g_free (charset);
                g_free (buf);
 
                html = g_string_new ("");
diff --git a/em-format/e-mail-formatter.c b/em-format/e-mail-formatter.c
index dc3cb89..2e89f69 100644
--- a/em-format/e-mail-formatter.c
+++ b/em-format/e-mail-formatter.c
@@ -51,6 +51,8 @@ struct _EMailFormatterPrivate {
        guint show_real_date    : 1;
         guint animate_images    : 1;
 
+       GMutex property_lock;
+
        gchar *charset;
        gchar *default_charset;
 
@@ -304,16 +306,16 @@ e_mail_formatter_get_property (GObject *object,
                        return;
 
                case PROP_CHARSET:
-                       g_value_set_string (
+                       g_value_take_string (
                                value,
-                               e_mail_formatter_get_charset (
+                               e_mail_formatter_dup_charset (
                                E_MAIL_FORMATTER (object)));
                        return;
 
                case PROP_DEFAULT_CHARSET:
-                       g_value_set_string (
+                       g_value_take_string (
                                value,
-                               e_mail_formatter_get_default_charset (
+                               e_mail_formatter_dup_default_charset (
                                E_MAIL_FORMATTER (object)));
                        return;
        }
@@ -344,6 +346,8 @@ e_mail_formatter_finalize (GObject *object)
                priv->header_list = NULL;
        }
 
+       g_mutex_clear (&priv->property_lock);
+
        /* Chain up to parent's finalize() */
        G_OBJECT_CLASS (e_mail_formatter_parent_class)->finalize (object);
 }
@@ -717,6 +721,7 @@ e_mail_formatter_init (EMailFormatter *formatter)
 {
        formatter->priv = E_MAIL_FORMATTER_GET_PRIVATE (formatter);
 
+       g_mutex_init (&formatter->priv->property_lock);
        formatter->priv->header_list = g_queue_new ();
        e_mail_formatter_set_default_headers (formatter);
 }
@@ -1289,14 +1294,31 @@ e_mail_formatter_get_charset (EMailFormatter *formatter)
        return formatter->priv->charset;
 }
 
+gchar *
+e_mail_formatter_dup_charset (EMailFormatter *formatter)
+{
+       gchar *charset;
+
+       g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+       g_mutex_lock (&formatter->priv->property_lock);
+       charset = g_strdup (e_mail_formatter_get_charset (formatter));
+       g_mutex_unlock (&formatter->priv->property_lock);
+
+       return charset;
+}
+
 void
 e_mail_formatter_set_charset (EMailFormatter *formatter,
                               const gchar *charset)
 {
        g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
 
-       if (g_strcmp0 (formatter->priv->charset, charset) == 0)
+       g_mutex_lock (&formatter->priv->property_lock);
+       if (g_strcmp0 (formatter->priv->charset, charset) == 0) {
+               g_mutex_unlock (&formatter->priv->property_lock);
                return;
+       }
 
        g_free (formatter->priv->charset);
 
@@ -1306,6 +1328,8 @@ e_mail_formatter_set_charset (EMailFormatter *formatter,
                formatter->priv->charset = g_strdup (charset);
        }
 
+       g_mutex_unlock (&formatter->priv->property_lock);
+
        g_object_notify (G_OBJECT (formatter), "charset");
 }
 
@@ -1317,6 +1341,20 @@ e_mail_formatter_get_default_charset (EMailFormatter *formatter)
        return formatter->priv->default_charset;
 }
 
+gchar *
+e_mail_formatter_dup_default_charset (EMailFormatter *formatter)
+{
+       gchar *default_charset;
+
+       g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+       g_mutex_lock (&formatter->priv->property_lock);
+       default_charset = g_strdup (e_mail_formatter_get_default_charset (formatter));
+       g_mutex_unlock (&formatter->priv->property_lock);
+
+       return default_charset;
+}
+
 void
 e_mail_formatter_set_default_charset (EMailFormatter *formatter,
                                       const gchar *default_charset)
@@ -1324,12 +1362,18 @@ e_mail_formatter_set_default_charset (EMailFormatter *formatter,
        g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
        g_return_if_fail (default_charset && *default_charset);
 
-       if (g_strcmp0 (formatter->priv->default_charset, default_charset) == 0)
+       g_mutex_lock (&formatter->priv->property_lock);
+
+       if (g_strcmp0 (formatter->priv->default_charset, default_charset) == 0) {
+               g_mutex_unlock (&formatter->priv->property_lock);
                return;
+       }
 
        g_free (formatter->priv->default_charset);
        formatter->priv->default_charset = g_strdup (default_charset);
 
+       g_mutex_unlock (&formatter->priv->property_lock);
+
        g_object_notify (G_OBJECT (formatter), "default-charset");
 }
 
@@ -1366,6 +1410,46 @@ e_mail_formatter_get_headers (EMailFormatter *formatter)
 }
 
 /**
+ * e_mail_formatter_dup_headers:
+ * @formatter: an #EMailFormatter
+ *
+ * Returns copy of a list of currently set headers.
+ *
+ * Returns: (transfer-full): A new #GQueue of currently set headers; the pointer should
+ *    be freed when no longer needed with command:
+ *    g_queue_free_full (queue, (GDestroyNotify) e_mail_formatter_header_free);
+ */
+GQueue *
+e_mail_formatter_dup_headers (EMailFormatter *formatter)
+{
+       GQueue *header_list;
+       GList *link;
+
+       g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+       g_mutex_lock (&formatter->priv->property_lock);
+
+       header_list = g_queue_new ();
+       for (link = g_queue_peek_head_link ((GQueue *) e_mail_formatter_get_headers (formatter));
+            link;
+            link = g_list_next (link)) {
+               EMailFormatterHeader *h = link->data, *copy;
+
+               if (!h)
+                       continue;
+
+               copy = e_mail_formatter_header_new (h->name, h->value);
+               copy->flags = h->flags;
+
+               g_queue_push_tail (header_list, copy);
+       }
+
+       g_mutex_unlock (&formatter->priv->property_lock);
+
+       return header_list;
+}
+
+/**
  * e_mail_formatter_clear_headers:
  * @formatter: an #EMailFormatter
  *
@@ -1379,9 +1463,13 @@ e_mail_formatter_clear_headers (EMailFormatter *formatter)
 
        g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
 
+       g_mutex_lock (&formatter->priv->property_lock);
+
        while ((header = g_queue_pop_head (formatter->priv->header_list)) != NULL) {
                e_mail_formatter_header_free (header);
        }
+
+       g_mutex_unlock (&formatter->priv->property_lock);
 }
 
 /**
@@ -1432,7 +1520,10 @@ e_mail_formatter_add_header (EMailFormatter *formatter,
 
        h = e_mail_formatter_header_new (name, value);
        h->flags = flags;
+
+       g_mutex_lock (&formatter->priv->property_lock);
        g_queue_push_tail (formatter->priv->header_list, h);
+       g_mutex_unlock (&formatter->priv->property_lock);
 
        g_signal_emit (formatter, signals[NEED_REDRAW], 0, NULL);
 }
@@ -1447,15 +1538,18 @@ e_mail_formatter_add_header_struct (EMailFormatter *formatter,
        e_mail_formatter_add_header (formatter, header->name, header->value, header->flags);
 }
 
-void e_mail_formatter_remove_header (EMailFormatter *formatter,
-                                    const gchar *name,
-                                    const gchar *value)
+void
+e_mail_formatter_remove_header (EMailFormatter *formatter,
+                               const gchar *name,
+                               const gchar *value)
 {
        GList *iter = NULL;
 
        g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
        g_return_if_fail (name && *name);
 
+       g_mutex_lock (&formatter->priv->property_lock);
+
        iter = g_queue_peek_head_link (formatter->priv->header_list);
        while (iter) {
                EMailFormatterHeader *header = iter->data;
@@ -1485,6 +1579,8 @@ void e_mail_formatter_remove_header (EMailFormatter *formatter,
                e_mail_formatter_header_free (iter->data);
                g_queue_delete_link (formatter->priv->header_list, iter);
        }
+
+       g_mutex_unlock (&formatter->priv->property_lock);
 }
 
 void
diff --git a/em-format/e-mail-formatter.h b/em-format/e-mail-formatter.h
index c850969..93e5268 100644
--- a/em-format/e-mail-formatter.h
+++ b/em-format/e-mail-formatter.h
@@ -217,16 +217,20 @@ void              e_mail_formatter_set_show_real_date
                                                 gboolean show_real_date);
 
 const gchar *  e_mail_formatter_get_charset    (EMailFormatter *formatter);
+gchar *                e_mail_formatter_dup_charset    (EMailFormatter *formatter);
 void           e_mail_formatter_set_charset    (EMailFormatter *formatter,
                                                 const gchar *charset);
 
 const gchar *  e_mail_formatter_get_default_charset
                                                (EMailFormatter *formatter);
+gchar *                e_mail_formatter_dup_default_charset
+                                               (EMailFormatter *formatter);
 void           e_mail_formatter_set_default_charset
                                                (EMailFormatter *formatter,
                                                 const gchar *charset);
 
 const GQueue * e_mail_formatter_get_headers    (EMailFormatter *formatter);
+GQueue *       e_mail_formatter_dup_headers    (EMailFormatter *formatter);
 
 void           e_mail_formatter_clear_headers  (EMailFormatter *formatter);
 
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 4df136e..475f49a 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -649,6 +649,7 @@ emp_set_parts_list (EMailPrinter *emp,
        CamelMediumHeader *header;
        CamelMimeMessage *message;
        GArray *headers;
+       GQueue *headers_queue;
        gint i;
        GtkTreeIter last_known = { 0 };
 
@@ -667,6 +668,7 @@ emp_set_parts_list (EMailPrinter *emp,
        if (!headers)
                return;
 
+       headers_queue = e_mail_formatter_dup_headers (E_MAIL_FORMATTER (emp->priv->formatter));
        for (i = 0; i < headers->len; i++) {
                GtkTreeIter iter;
                GList *found_header;
@@ -675,10 +677,7 @@ emp_set_parts_list (EMailPrinter *emp,
                header = &g_array_index (headers, CamelMediumHeader, i);
                emfh = e_mail_formatter_header_new (header->name, header->value);
 
-               found_header = g_queue_find_custom (
-                               (GQueue *) e_mail_formatter_get_headers (
-                                       E_MAIL_FORMATTER (emp->priv->formatter)),
-                               emfh, (GCompareFunc) emp_header_name_equal);
+               found_header = g_queue_find_custom (headers_queue, emfh, (GCompareFunc) 
emp_header_name_equal);
 
                if (!found_header) {
                        emfh->flags |= E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN;
@@ -702,6 +701,7 @@ emp_set_parts_list (EMailPrinter *emp,
                        COLUMN_HEADER_STRUCT, emfh, -1);
        }
 
+       g_queue_free_full (headers_queue, (GDestroyNotify) e_mail_formatter_header_free);
        camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
 }
 


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