From 91e0ec52dfbf24a381fe1fdabd05338b10c17ed2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 26 Mar 2001 15:47:08 +0000 Subject: Make fake content-id URLs be guaranteed unique: the old way (with %p on * mail-format.c (get_cid): Make fake content-id URLs be guaranteed unique: the old way (with %p on the CamelMimePart *) would generate duplicates if memory was freed and re-allocated the right way. * mail-display.c (pixbuf_gen_idle, etc): Make the thumbnail cache global rather than per-MailDisplay, since content-ids ought to be globally unique. Also, don't leak content-id strings when the pixbuf generation fails, and remove pixbufs from the cache after 5 minutes. svn path=/trunk/; revision=8944 --- mail/ChangeLog | 11 +++++++++++ mail/mail-display.c | 50 ++++++++++++++++++++++++++++++-------------------- mail/mail-format.c | 5 +++-- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 1d96a3f937..f2ba5e62ff 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,5 +1,16 @@ 2001-03-26 Dan Winship + * mail-format.c (get_cid): Make fake content-id URLs be guaranteed + unique: the old way (with %p on the CamelMimePart *) would + generate duplicates if memory was freed and re-allocated the right + way. + + * mail-display.c (pixbuf_gen_idle, etc): Make the thumbnail cache + global rather than per-MailDisplay, since content-ids ought to be + globally unique. Also, don't leak content-id strings when the + pixbuf generation fails, and remove pixbufs from the cache after 5 + minutes. + * component-factory.c (mail_load_storages): Simplify a bit using camel_session_get_provider. diff --git a/mail/mail-display.c b/mail/mail-display.c index df3ead97db..97ebfe94b7 100644 --- a/mail/mail-display.c +++ b/mail/mail-display.c @@ -45,7 +45,6 @@ static GtkObjectClass *mail_display_parent_class; struct _PixbufLoader { - MailDisplay *md; CamelDataWrapper *wrapper; /* The data */ CamelStream *mstream; GdkPixbufLoader *loader; @@ -56,6 +55,7 @@ struct _PixbufLoader { GtkWidget *pixmap; guint32 destroy_id; }; +static GHashTable *thumbnail_cache = NULL; /*----------------------------------------------------------------------* * Callbacks @@ -411,6 +411,19 @@ pixbuf_for_mime_type (const char *mime_type) return pixbuf; } +static gboolean +pixbuf_uncache (gpointer key) +{ + GdkPixbuf *pixbuf; + + printf ("uncaching %s\n", key); + pixbuf = g_hash_table_lookup (thumbnail_cache, key); + gdk_pixbuf_unref (pixbuf); + g_hash_table_remove (thumbnail_cache, key); + g_free (key); + return FALSE; +} + static gint pixbuf_gen_idle (struct _PixbufLoader *pbl) { @@ -418,10 +431,11 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) gboolean error = FALSE; char tmp[4096]; int len, width, height, ratio; + gpointer orig_key; /* Get the pixbuf from the cache */ - mini = g_hash_table_lookup (pbl->md->thumbnail_cache, pbl->cid); - if (mini) { + if (g_hash_table_lookup_extended (thumbnail_cache, pbl->cid, + &orig_key, (gpointer *)&mini)) { width = gdk_pixbuf_get_width (mini); height = gdk_pixbuf_get_height (mini); @@ -429,6 +443,10 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) BONOBO_UI_TOOLBAR_ICON (pbl->pixmap), mini); gtk_widget_set_usize (pbl->pixmap, width, height); + /* Restart the cache-cleaning timer */ + g_source_remove_by_user_data (orig_key); + g_timeout_add (5 * 60 * 1000, pixbuf_uncache, orig_key); + if (pbl->loader) { gdk_pixbuf_loader_close (pbl->loader); gtk_object_destroy (GTK_OBJECT (pbl->loader)); @@ -436,12 +454,14 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) } gtk_signal_disconnect (GTK_OBJECT (pbl->eb), pbl->destroy_id); g_free (pbl->type); + g_free (pbl->cid); g_free (pbl); return FALSE; } /* Not in cache, so get a pixbuf from the wrapper */ + if (!GTK_IS_WIDGET (pbl->pixmap)) { /* Widget has died */ if (pbl->mstream) @@ -453,6 +473,7 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) } g_free (pbl->type); + g_free (pbl->cid); g_free (pbl); return FALSE; } @@ -498,11 +519,11 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) gdk_pixbuf_unref (pixbuf); bonobo_ui_toolbar_icon_set_pixbuf ( BONOBO_UI_TOOLBAR_ICON (pbl->pixmap), mini); + gtk_widget_set_usize (pbl->pixmap, 24, 24); /* Add the pixbuf to the cache */ - - g_hash_table_insert (pbl->md->thumbnail_cache, pbl->cid, mini); - gtk_widget_set_usize (pbl->pixmap, 24, 24); + g_hash_table_insert (thumbnail_cache, pbl->cid, mini); + g_timeout_add (5 * 60 * 1000, pixbuf_uncache, pbl->cid); gtk_signal_disconnect (GTK_OBJECT (pbl->eb), pbl->destroy_id); if (pbl->loader) { @@ -532,6 +553,7 @@ embeddable_destroy_cb (GtkObject *embeddable, } g_free (pbl->type); + g_free (pbl->cid); g_free (pbl); }; @@ -693,7 +715,6 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) pbl->cid = g_strdup (cid); pbl->pixmap = bonobo_ui_toolbar_icon_new (); pbl->eb = eb; - pbl->md = md; pbl->destroy_id = gtk_signal_connect (GTK_OBJECT (eb), "destroy", embeddable_destroy_cb, @@ -1004,16 +1025,6 @@ mail_display_init (GtkObject *object) /* various other initializations */ mail_display->current_message = NULL; - mail_display->thumbnail_cache = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -thumbnail_cache_free (gpointer key, - gpointer value, - gpointer user_data) -{ - g_free (key); - gdk_pixbuf_unref (value); } static void @@ -1021,9 +1032,6 @@ mail_display_destroy (GtkObject *object) { MailDisplay *mail_display = MAIL_DISPLAY (object); - g_hash_table_foreach (mail_display->thumbnail_cache, - thumbnail_cache_free, NULL); - g_hash_table_destroy (mail_display->thumbnail_cache); g_datalist_clear (mail_display->data); g_free (mail_display->data); @@ -1035,6 +1043,8 @@ mail_display_class_init (GtkObjectClass *object_class) { object_class->destroy = mail_display_destroy; mail_display_parent_class = gtk_type_class (PARENT_TYPE); + + thumbnail_cache = g_hash_table_new (g_str_hash, g_str_equal); } static void diff --git a/mail/mail-format.c b/mail/mail-format.c index 4957d01c27..f6a145294e 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -179,17 +179,18 @@ get_cid (CamelMimePart *part, MailDisplay *md) GHashTable *urls; char *cid; gpointer orig_name, value; + static int fake_cid_counter = 0; urls = g_datalist_get_data (md->data, "urls"); /* If we have a real Content-ID, use it. If we don't, - * make a (syntactically invalid) fake one. + * make a (syntactically invalid, unique) fake one. */ if (camel_mime_part_get_content_id (part)) { cid = g_strdup_printf ("cid:%s", camel_mime_part_get_content_id (part)); } else - cid = g_strdup_printf ("cid:@@@%p", part); + cid = g_strdup_printf ("cid:@@@%d", fake_cid_counter++); if (g_hash_table_lookup_extended (urls, cid, &orig_name, &value)) { g_free (cid); -- cgit v1.2.3