diff options
author | Milan Crha <mcrha@redhat.com> | 2011-03-02 22:12:02 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2011-03-02 22:13:40 +0800 |
commit | 2533e52b8cf543eed874d220a3f039eebe67253e (patch) | |
tree | 20b018e5f1b86200982fd7bb324aef3358469070 | |
parent | a0854ec1a6591ea10ba7915f37684f78f476fcd4 (diff) | |
download | gsoc2013-evolution-2533e52b8cf543eed874d220a3f039eebe67253e.tar.gz gsoc2013-evolution-2533e52b8cf543eed874d220a3f039eebe67253e.tar.zst gsoc2013-evolution-2533e52b8cf543eed874d220a3f039eebe67253e.zip |
Do not leak attachments in a mail view
-rw-r--r-- | em-format/em-format.c | 10 | ||||
-rw-r--r-- | em-format/em-format.h | 2 | ||||
-rw-r--r-- | mail/e-mail-attachment-bar.c | 1 | ||||
-rw-r--r-- | mail/em-format-html-display.c | 103 | ||||
-rw-r--r-- | mail/em-format-html-display.h | 4 | ||||
-rw-r--r-- | plugins/mail-to-task/mail-to-task.c | 1 | ||||
-rw-r--r-- | widgets/misc/e-attachment-paned.c | 1 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.c | 36 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.h | 1 |
9 files changed, 145 insertions, 14 deletions
diff --git a/em-format/em-format.c b/em-format/em-format.c index 23573331c0..59ae409912 100644 --- a/em-format/em-format.c +++ b/em-format/em-format.c @@ -150,6 +150,7 @@ emf_finalize (GObject *object) g_free (emf->charset); g_free (emf->default_charset); g_string_free (emf->part_id, TRUE); + g_free (emf->current_message_part_id); g_free (emf->uid); if (emf->pending_uri_table != NULL) @@ -240,6 +241,7 @@ emf_format_clone (EMFormat *emf, emf->message = msg; } + emf->current_message_part_id = g_strdup ("root-message"); g_string_truncate (emf->part_id, 0); if (folder != NULL) /* TODO build some string based on the folder name/location? */ @@ -365,6 +367,7 @@ emf_init (EMFormat *emf) g_queue_init (&emf->header_list); em_format_default_headers (emf); emf->part_id = g_string_new(""); + emf->current_message_part_id = NULL; emf->validity_found = 0; shell = e_shell_get_default (); @@ -2075,12 +2078,16 @@ emf_message_rfc822 (EMFormat *emf, CamelDataWrapper *dw = camel_medium_get_content ((CamelMedium *)part); const EMFormatHandler *handle; gint len; + gchar *parent_message_part_id; if (!CAMEL_IS_MIME_MESSAGE (dw)) { em_format_format_source (emf, stream, part, cancellable); return; } + parent_message_part_id = emf->current_message_part_id; + emf->current_message_part_id = g_strdup (emf->part_id->str); + len = emf->part_id->len; g_string_append_printf(emf->part_id, ".rfc822"); @@ -2091,6 +2098,9 @@ emf_message_rfc822 (EMFormat *emf, handle, cancellable, FALSE); g_string_truncate (emf->part_id, len); + + g_free (emf->current_message_part_id); + emf->current_message_part_id = parent_message_part_id; } static void diff --git a/em-format/em-format.h b/em-format/em-format.h index 64336a9aa8..b1f0746fed 100644 --- a/em-format/em-format.h +++ b/em-format/em-format.h @@ -198,6 +198,8 @@ struct _EMFormat { /* Current part ID prefix for identifying parts directly. */ GString *part_id; + /* part_id of the currently processing message (when the message has message-attachments) */ + gchar *current_message_part_id; /* If empty, then all. */ GQueue header_list; diff --git a/mail/e-mail-attachment-bar.c b/mail/e-mail-attachment-bar.c index 22f27fac20..0a5a3271fe 100644 --- a/mail/e-mail-attachment-bar.c +++ b/mail/e-mail-attachment-bar.c @@ -185,6 +185,7 @@ mail_attachment_bar_dispose (GObject *object) priv = E_MAIL_ATTACHMENT_BAR (object)->priv; if (priv->model != NULL) { + e_attachment_store_remove_all (E_ATTACHMENT_STORE (priv->model)); g_object_unref (priv->model); priv->model = NULL; } diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index fc1281cfc8..e654e87449 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -65,7 +65,7 @@ #define d(x) struct _EMFormatHTMLDisplayPrivate { - GtkWidget *attachment_view; /* weak reference */ + GHashTable *attachment_views; /* weak reference; message_part_id->EAttachmentView */ }; struct _smime_pobject { @@ -106,6 +106,7 @@ static void efhd_attachment_frame (EMFormat *emf, CamelStream *stream, EMFormatP static void efhd_message_add_bar (EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info); static gboolean efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject); static gboolean efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *object); +static void efhd_free_attach_puri_data (EMFormatPURI *puri); struct _attach_puri { EMFormatPURI puri; @@ -125,6 +126,7 @@ struct _attach_puri { /* Attachment */ EAttachment *attachment; + gchar *attachment_view_part_id; /* image stuff */ gint fit_width; @@ -378,6 +380,28 @@ efhd_xpkcs7mime_button (EMFormatHTML *efh, return TRUE; } +static gboolean +remove_attachment_view_cb (gpointer message_part_id, gpointer attachment_view, gpointer gone_attachment_view) +{ + return attachment_view == gone_attachment_view; +} + +static void +efhd_attachment_view_gone_cb (gpointer efh, GObject *gone_attachment_view) +{ + EMFormatHTMLDisplay *efhd = EM_FORMAT_HTML_DISPLAY (efh); + + g_return_if_fail (efhd != NULL); + + g_hash_table_foreach_remove (efhd->priv->attachment_views, remove_attachment_view_cb, gone_attachment_view); +} + +static void +weak_unref_attachment_view_cb (gpointer message_part_id, gpointer attachment_view, gpointer efh) +{ + g_object_weak_unref (G_OBJECT (attachment_view), efhd_attachment_view_gone_cb, efh); +} + static void efhd_format_clone (EMFormat *emf, CamelFolder *folder, @@ -386,6 +410,14 @@ efhd_format_clone (EMFormat *emf, EMFormat *src, GCancellable *cancellable) { + EMFormatHTMLDisplay *efhd; + + efhd = EM_FORMAT_HTML_DISPLAY (emf); + g_return_if_fail (efhd != NULL); + + g_hash_table_foreach (efhd->priv->attachment_views, weak_unref_attachment_view_cb, efhd); + g_hash_table_remove_all (efhd->priv->attachment_views); + if (emf != src) EM_FORMAT_HTML (emf)->header_wrap_flags = 0; @@ -408,6 +440,8 @@ efhd_format_attachment (EMFormat *emf, classid = g_strdup_printf ("attachment%s", emf->part_id->str); info = (struct _attach_puri *) em_format_add_puri ( emf, sizeof (*info), classid, part, efhd_attachment_frame); + info->puri.free = efhd_free_attach_puri_data; + info->attachment_view_part_id = g_strdup (emf->current_message_part_id); em_format_html_add_pobject ( EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject), classid, part, efhd_attachment_button); @@ -479,6 +513,8 @@ efhd_format_optional (EMFormat *emf, classid = g_strdup_printf ("optional%s", emf->part_id->str); info = (struct _attach_puri *) em_format_add_puri ( emf, sizeof (*info), classid, part, efhd_attachment_frame); + info->puri.free = efhd_free_attach_puri_data; + info->attachment_view_part_id = g_strdup (emf->current_message_part_id); em_format_html_add_pobject ( EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject), classid, part, efhd_attachment_optional); @@ -595,14 +631,35 @@ efhd_format_secure (EMFormat *emf, } static void +efhd_finalize (GObject *object) +{ + EMFormatHTMLDisplay *efhd; + + efhd = EM_FORMAT_HTML_DISPLAY (object); + g_return_if_fail (efhd != NULL); + + if (efhd->priv->attachment_views) { + g_hash_table_foreach (efhd->priv->attachment_views, weak_unref_attachment_view_cb, efhd); + g_hash_table_destroy (efhd->priv->attachment_views); + efhd->priv->attachment_views = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void efhd_class_init (EMFormatHTMLDisplayClass *class) { + GObjectClass *object_class; EMFormatClass *format_class; EMFormatHTMLClass *format_html_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EMFormatHTMLDisplayPrivate)); + object_class = G_OBJECT_CLASS (class); + object_class->finalize = efhd_finalize; + format_class = EM_FORMAT_CLASS (class); format_class->format_clone = efhd_format_clone; format_class->format_attachment = efhd_format_attachment; @@ -623,6 +680,7 @@ efhd_init (EMFormatHTMLDisplay *efhd) web_view = em_format_html_get_web_view (EM_FORMAT_HTML (efhd)); efhd->priv = G_TYPE_INSTANCE_GET_PRIVATE (efhd, EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayPrivate); + efhd->priv->attachment_views = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); e_mail_display_set_formatter ( E_MAIL_DISPLAY (web_view), EM_FORMAT_HTML (efhd)); @@ -841,7 +899,7 @@ efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObj parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - view = em_format_html_display_get_attachment_view (efhd); + view = em_format_html_display_get_attachment_view (efhd, info->attachment_view_part_id); gtk_widget_show (GTK_WIDGET (view)); store = e_attachment_view_get_store (view); @@ -894,6 +952,12 @@ efhd_attachment_frame (EMFormat *emf, } static void +set_size_request_cb (gpointer message_part_id, gpointer widget, gpointer width) +{ + gtk_widget_set_size_request (widget, GPOINTER_TO_INT (width), -1); +} + +static void efhd_bar_resize (EMFormatHTML *efh, GtkAllocation *event) { @@ -912,8 +976,7 @@ efhd_bar_resize (EMFormatHTML *efh, width = allocation.width - 12; if (width > 0) { - widget = priv->attachment_view; - gtk_widget_set_size_request (widget, width, -1); + g_hash_table_foreach (priv->attachment_views, set_size_request_cb, GINT_TO_POINTER (width)); } } @@ -933,7 +996,9 @@ efhd_add_bar (EMFormatHTML *efh, widget = e_mail_attachment_bar_new (); gtk_container_add (GTK_CONTAINER (eb), widget); - priv->attachment_view = widget; + + g_hash_table_insert (priv->attachment_views, g_strdup (EM_FORMAT (efh)->current_message_part_id), widget); + g_object_weak_ref (G_OBJECT (widget), efhd_attachment_view_gone_cb, efh); gtk_widget_hide (widget); g_signal_connect_swapped ( @@ -1086,10 +1151,34 @@ efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPO return TRUE; } +static void +efhd_free_attach_puri_data (EMFormatPURI *puri) +{ + struct _attach_puri *info = (struct _attach_puri *) puri; + + g_return_if_fail (puri != NULL); + + if (info->attachment) { + g_object_unref (info->attachment); + info->attachment = NULL; + } + + g_free (info->attachment_view_part_id); + info->attachment_view_part_id = NULL; +} + +/* returned object owned by html_display, thus do not unref it */ EAttachmentView * -em_format_html_display_get_attachment_view (EMFormatHTMLDisplay *html_display) +em_format_html_display_get_attachment_view (EMFormatHTMLDisplay *html_display, const gchar *message_part_id) { + gpointer aview; + g_return_val_if_fail (EM_IS_FORMAT_HTML_DISPLAY (html_display), NULL); + g_return_val_if_fail (message_part_id != NULL, NULL); + + /* it should be added in efhd_add_bar() with this message_part_id */ + aview = g_hash_table_lookup (html_display->priv->attachment_views, message_part_id); + g_return_val_if_fail (aview != NULL, NULL); - return E_ATTACHMENT_VIEW (html_display->priv->attachment_view); + return E_ATTACHMENT_VIEW (aview); } diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h index 089b361592..ec29698d46 100644 --- a/mail/em-format-html-display.h +++ b/mail/em-format-html-display.h @@ -69,8 +69,8 @@ EMFormatHTMLDisplay * em_format_html_display_new (void); EAttachmentView * em_format_html_display_get_attachment_view - (EMFormatHTMLDisplay *html_display); - + (EMFormatHTMLDisplay *html_display, + const gchar *message_part_id); G_END_DECLS #endif /* EM_FORMAT_HTML_DISPLAY_H */ diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c index 794badc969..558489578a 100644 --- a/plugins/mail-to-task/mail-to-task.c +++ b/plugins/mail-to-task/mail-to-task.c @@ -384,6 +384,7 @@ set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message) /* XXX Does this take ownership of the list? */ e_cal_component_set_attachment_list (comp, uri_list); + e_attachment_store_remove_all (store); g_object_unref (destination); g_object_unref (store); } diff --git a/widgets/misc/e-attachment-paned.c b/widgets/misc/e-attachment-paned.c index 21d736b50b..73773f25a1 100644 --- a/widgets/misc/e-attachment-paned.c +++ b/widgets/misc/e-attachment-paned.c @@ -221,6 +221,7 @@ attachment_paned_dispose (GObject *object) priv = E_ATTACHMENT_PANED (object)->priv; if (priv->model != NULL) { + e_attachment_store_remove_all (E_ATTACHMENT_STORE (priv->model)); g_object_unref (priv->model); priv->model = NULL; } diff --git a/widgets/misc/e-attachment-store.c b/widgets/misc/e-attachment-store.c index 392dfe6fc7..e1794d653c 100644 --- a/widgets/misc/e-attachment-store.c +++ b/widgets/misc/e-attachment-store.c @@ -108,11 +108,7 @@ attachment_store_get_property (GObject *object, static void attachment_store_dispose (GObject *object) { - EAttachmentStorePrivate *priv; - - priv = E_ATTACHMENT_STORE (object)->priv; - - g_hash_table_remove_all (priv->attachment_index); + e_attachment_store_remove_all (E_ATTACHMENT_STORE (object)); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_attachment_store_parent_class)->dispose (object); @@ -327,6 +323,36 @@ e_attachment_store_remove_attachment (EAttachmentStore *store, } void +e_attachment_store_remove_all (EAttachmentStore *store) +{ + GList *list, *iter; + + g_return_if_fail (E_IS_ATTACHMENT_STORE (store)); + + if (!g_hash_table_size (store->priv->attachment_index)) + return; + + g_object_freeze_notify (G_OBJECT (store)); + + list = e_attachment_store_get_attachments (store); + for (iter = list; iter; iter = iter->next) { + EAttachment *attachment = iter->data; + + e_attachment_cancel (attachment); + g_hash_table_remove (store->priv->attachment_index, iter->data); + } + + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); + + gtk_list_store_clear (GTK_LIST_STORE (store)); + + g_object_notify (G_OBJECT (store), "num-attachments"); + g_object_notify (G_OBJECT (store), "total-size"); + g_object_thaw_notify (G_OBJECT (store)); +} + +void e_attachment_store_add_to_multipart (EAttachmentStore *store, CamelMultipart *multipart, const gchar *default_charset) diff --git a/widgets/misc/e-attachment-store.h b/widgets/misc/e-attachment-store.h index 49980ea3b1..a7839aca71 100644 --- a/widgets/misc/e-attachment-store.h +++ b/widgets/misc/e-attachment-store.h @@ -80,6 +80,7 @@ void e_attachment_store_add_attachment gboolean e_attachment_store_remove_attachment (EAttachmentStore *store, EAttachment *attachment); +void e_attachment_store_remove_all (EAttachmentStore *store); void e_attachment_store_add_to_multipart (EAttachmentStore *store, CamelMultipart *multipart, |