[evolution-patches] fix for 60900
- From: Not Zed <notzed ximian com>
- To: evolution-patches lists ximian com
- Subject: [evolution-patches] fix for 60900
- Date: Fri, 09 Jul 2004 13:12:58 +0800
Ok this contains the previous patch plus something which should actually fix the bug.
Its a pretty big patch unfortunately, but also adds caching of decrypted parts and verification status, which speeds up when we need to redraw.
Index: mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.3411
diff -u -3 -r1.3411 ChangeLog
--- mail/ChangeLog 5 Jul 2004 15:08:21 -0000 1.3411
+++ mail/ChangeLog 9 Jul 2004 05:10:31 -0000
@@ -1,3 +1,48 @@
+2004-07-09 Not Zed <NotZed Ximian com>
+
+ ** See bug #60900.
+
+ * em-format-html.c: convert the text_inline_parts hash to be keyed
+ off the partid.
+ (efh_free_inline_parts): -> efh_free_cache and fix to do it.
+
+ * em-format.c (emf_free_cache): make the inline table cache other
+ info too based on partid, this frees the structure.
+ (emf_clone_inlines): copy all of the cache data.
+ (em_format_is_inline): use the new data structure to determine
+ state.
+ (em_format_set_inline): same for setting.
+ (emf_multipart_signed): cache/lookup the cached part.
+ (emf_insert_cache): helper to add a cache entry.
+ (emf_multipart_encrypted): cache decrypted part.
+ (emf_application_xpkcs7mime): same.
+
+2004-07-08 Not Zed <NotZed Ximian com>
+
+ ** See bug #60900 (related only).
+
+ * em-format-html-display.c (efhd_attachment_show): let set_inline
+ do the redraw itself if required. kill some dead code.
+
+ * em-format.c (em_format_set_inline): trigger a redraw here like
+ the other em_format_set methods, if the state changed.
+
+ * em-format.c (emf_format_clone): free inline table keys & setup
+ string hash table.
+
+ * em-format-quote.c (emfq_format_attachment):
+ * em-format-html-display.c (efhd_format_attachment):
+ * em-format-html.c (efh_format_attachment): is_inline api changes.
+
+ * em-format-html-display.c (efhd_attachment_show): set_inline api
+ changes.
+
+ * em-format.c (em_format_is_inline): make this use the partid
+ rather than the part address as a key, which may change.
+ (emf_init): make the inline talbe a string hashtable.
+ (emf_finalise): free inline keys.
+ (emf_clone_inlines): copy the key string.
+
2004-07-02 JP Rosevaer <jpr novell com>
* Makefile.am (SUBDIRS): Revert previous error change
Index: mail/em-format-html-display.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html-display.c,v
retrieving revision 1.47
diff -u -3 -r1.47 em-format-html-display.c
--- mail/em-format-html-display.c 23 Jun 2004 08:08:40 -0000 1.47
+++ mail/em-format-html-display.c 9 Jul 2004 05:10:32 -0000
@@ -1046,38 +1046,7 @@
d(printf("show attachment button called\n"));
info->shown = ~info->shown;
- em_format_set_inline(info->puri.format, info->puri.part, info->shown);
- /* FIXME: do this in an idle handler */
- em_format_redraw(info->puri.format);
-#if 0
- /* FIXME: track shown state in parent */
-
- if (info->shown) {
- d(printf("hiding\n"));
- info->shown = FALSE;
- if (info->frame)
- gtk_widget_hide((GtkWidget *)info->frame);
- gtk_widget_show(info->forward);
- gtk_widget_hide(info->down);
- } else {
- d(printf("showing\n"));
- info->shown = TRUE;
- if (info->frame)
- gtk_widget_show((GtkWidget *)info->frame);
- gtk_widget_hide(info->forward);
- gtk_widget_show(info->down);
-
- /* have we decoded it yet? */
- if (info->output) {
- info->handle->handler(info->puri.format, info->output, info->puri.part, info->handle);
- camel_stream_close(info->output);
- camel_object_unref(info->output);
- info->output = NULL;
- }
- }
-
- em_format_set_inline(info->puri.format, info->puri.part, info->shown);
-#endif
+ em_format_set_inline(info->puri.format, info->puri.part_id, info->shown);
}
static EMPopupItem efhd_menu_items[] = {
@@ -1498,7 +1467,7 @@
info = (struct _attach_puri *)em_format_add_puri(emf, sizeof(*info), classid, part, efhd_attachment_frame);
em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_button);
info->handle = handle;
- info->shown = em_format_is_inline(emf, info->puri.part, handle);
+ info->shown = em_format_is_inline(emf, info->puri.part_id, info->puri.part, handle);
info->snoop_mime_type = emf->snoop_mime_type;
camel_stream_write_string(stream,
Index: mail/em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.60
diff -u -3 -r1.60 em-format-html.c
--- mail/em-format-html.c 24 May 2004 08:02:25 -0000 1.60
+++ mail/em-format-html.c 9 Jul 2004 05:10:32 -0000
@@ -75,13 +75,19 @@
#define EFH_TABLE_OPEN "<table>"
+struct _EMFormatHTMLCache {
+ CamelMultipart *textmp;
+
+ char partid[1];
+};
+
struct _EMFormatHTMLPrivate {
struct _CamelMimeMessage *last_part; /* not reffed, DO NOT dereference */
volatile int format_id; /* format thread id */
guint format_timeout_id;
struct _format_msg *format_timeout_msg;
- /* Table that re-maps text parts into a mutlipart/mixed */
+ /* Table that re-maps text parts into a mutlipart/mixed, EMFormatHTMLCache * */
GHashTable *text_inline_parts;
EDList pending_jobs;
@@ -120,7 +126,7 @@
e_dlist_init(&efh->priv->pending_jobs);
efh->priv->lock = g_mutex_new();
efh->priv->format_id = -1;
- efh->priv->text_inline_parts = g_hash_table_new(NULL, NULL);
+ efh->priv->text_inline_parts = g_hash_table_new(g_str_hash, g_str_equal);
efh->html = (GtkHTML *)gtk_html_new();
gtk_html_set_blocking(efh->html, FALSE);
@@ -163,10 +169,27 @@
}
}
+static struct _EMFormatHTMLCache *
+efh_insert_cache(EMFormatHTML *efh, const char *partid)
+{
+ struct _EMFormatHTMLCache *efhc;
+
+ efhc = g_malloc0(sizeof(*efh) + strlen(partid));
+ strcpy(efhc->partid, partid);
+ g_hash_table_insert(efh->priv->text_inline_parts, efhc->partid, efhc);
+
+ return efhc;
+}
+
+
static void
-efh_free_inline_parts(void *key, void *data, void *user)
+efh_free_cache(void *key, void *val, void *dat)
{
- camel_object_unref(data);
+ struct _EMFormatHTMLCache *efhc = val;
+
+ if (efhc->textmp)
+ camel_object_unref(efhc->textmp);
+ g_free(efhc);
}
static void
@@ -180,7 +203,7 @@
efh_gtkhtml_destroy(efh->html, efh);
- g_hash_table_foreach(efh->priv->text_inline_parts, efh_free_inline_parts, NULL);
+ g_hash_table_foreach(efh->priv->text_inline_parts, efh_free_cache, NULL);
g_hash_table_destroy(efh->priv->text_inline_parts);
g_free(efh->priv);
@@ -635,7 +658,8 @@
const char *format;
guint32 flags;
int i, count, len;
-
+ struct _EMFormatHTMLCache *efhc;
+
camel_stream_printf (stream,
"<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n"
"<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n"
@@ -663,8 +687,8 @@
filters a bit. Perhaps the superclass should just deal with
html anyway and be done with it ... */
- mp = g_hash_table_lookup(efh->priv->text_inline_parts, part);
- if (mp == NULL) {
+ efhc = g_hash_table_lookup(efh->priv->text_inline_parts, ((EMFormat *)efh)->part_id->str);
+ if (efhc == NULL || (mp = efhc->textmp) == NULL) {
EMInlineFilter *inline_filter;
CamelStream *null;
CamelContentType *ct;
@@ -685,8 +709,12 @@
camel_data_wrapper_write_to_stream(dw, (CamelStream *)filtered_stream);
camel_stream_close((CamelStream *)filtered_stream);
camel_object_unref(filtered_stream);
+
mp = em_inline_filter_get_multipart(inline_filter);
- g_hash_table_insert(efh->priv->text_inline_parts, part, mp);
+ if (efhc == NULL)
+ efhc = efh_insert_cache(efh, ((EMFormat *)efh)->part_id->str);
+ efhc->textmp = mp;
+
camel_object_unref(inline_filter);
camel_content_type_unref(ct);
}
@@ -1292,9 +1320,9 @@
| GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES);
} else {
/* clear cache of inline-scanned text parts */
- g_hash_table_foreach(p->text_inline_parts, efh_free_inline_parts, NULL);
+ g_hash_table_foreach(p->text_inline_parts, efh_free_cache, NULL);
g_hash_table_destroy(p->text_inline_parts);
- p->text_inline_parts = g_hash_table_new(NULL, NULL);
+ p->text_inline_parts = g_hash_table_new(g_str_hash, g_str_equal);
p->last_part = m->message;
}
@@ -1744,7 +1772,7 @@
camel_stream_write_string(stream, "</font></td></tr><tr></table>");
- if (handle && em_format_is_inline(emf, part, handle))
+ if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle))
handle->handler(emf, stream, part, handle);
}
Index: mail/em-format-quote.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-quote.c,v
retrieving revision 1.10
diff -u -3 -r1.10 em-format-quote.c
--- mail/em-format-quote.c 25 May 2004 16:16:25 -0000 1.10
+++ mail/em-format-quote.c 9 Jul 2004 05:10:32 -0000
@@ -394,7 +394,7 @@
static void
emfq_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle)
{
- if (handle && em_format_is_inline(emf, part, handle)) {
+ if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle)) {
char *text, *html;
camel_stream_write_string(stream,
Index: mail/em-format.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.c,v
retrieving revision 1.37
diff -u -3 -r1.37 em-format.c
--- mail/em-format.c 19 May 2004 07:02:12 -0000 1.37
+++ mail/em-format.c 9 Jul 2004 05:10:33 -0000
@@ -54,6 +54,24 @@
#define d(x)
+/* Used to cache various data/info for redraws
+ The validity stuff could be cached at a higher level but this is easier
+ This absolutely relies on the partid being _globally unique_
+ This is still kind of yucky, we should maintian a full tree of all this data,
+ along with/as part of the puri tree */
+struct _EMFormatCache {
+ struct _CamelCipherValidity *valid; /* validity copy */
+ struct _CamelMimePart *secured; /* encrypted subpart */
+
+ unsigned int state:2; /* inline state */
+
+ char partid[1];
+};
+
+#define INLINE_UNSET (0)
+#define INLINE_ON (1)
+#define INLINE_OFF (2)
+
static void emf_builtin_init(EMFormatClass *);
static const EMFormatHandler *emf_find_handler(EMFormat *emf, const char *mime_type);
@@ -71,11 +89,35 @@
static GObjectClass *emf_parent;
static void
+emf_free_cache(void *key, void *val, void *dat)
+{
+ struct _EMFormatCache *efc = val;
+
+ if (efc->valid)
+ camel_cipher_validity_free(efc->valid);
+ if (efc->secured)
+ camel_object_unref(efc->secured);
+ g_free(efc);
+}
+
+static struct _EMFormatCache *
+emf_insert_cache(EMFormat *emf, const char *partid)
+{
+ struct _EMFormatCache *new;
+
+ new = g_malloc0(sizeof(*new)+strlen(partid));
+ strcpy(new->partid, partid);
+ g_hash_table_insert(emf->inline_table, new->partid, new);
+
+ return new;
+}
+
+static void
emf_init(GObject *o)
{
EMFormat *emf = (EMFormat *)o;
- emf->inline_table = g_hash_table_new(NULL, NULL);
+ emf->inline_table = g_hash_table_new(g_str_hash, g_str_equal);
e_dlist_init(&emf->header_list);
em_format_default_headers(emf);
emf->part_id = g_string_new("");
@@ -89,8 +131,8 @@
if (emf->session)
camel_object_unref(emf->session);
- if (emf->inline_table)
- g_hash_table_destroy(emf->inline_table);
+ g_hash_table_foreach(emf->inline_table, emf_free_cache, NULL);
+ g_hash_table_destroy(emf->inline_table);
em_format_clear_headers(emf);
camel_cipher_validity_free(emf->valid);
@@ -526,7 +568,14 @@
static void
emf_clone_inlines(void *key, void *val, void *data)
{
- g_hash_table_insert(((EMFormat *)data)->inline_table, key, val);
+ struct _EMFormatCache *emfc = val, *new;
+
+ new = emf_insert_cache((EMFormat *)data, emfc->partid);
+ new->state = emfc->state;
+ if (emfc->valid)
+ new->valid = camel_cipher_validity_clone(emfc->valid);
+ if (emfc->secured)
+ camel_object_ref((new->secured = emfc->secured));
}
static void
@@ -535,8 +584,9 @@
em_format_clear_puri_tree(emf);
if (emf != emfsource) {
+ g_hash_table_foreach(emf->inline_table, emf_free_cache, NULL);
g_hash_table_destroy(emf->inline_table);
- emf->inline_table = g_hash_table_new(NULL, NULL);
+ emf->inline_table = g_hash_table_new(g_str_hash, g_str_equal);
if (emfsource) {
struct _EMFormatHeader *h;
@@ -829,6 +879,7 @@
* em_format_is_inline:
* @emf:
* @part:
+ * @partid: format->part_id part id of this part.
* @handle: handler for this part
*
* Returns true if the part should be displayed inline. Any part with
@@ -840,16 +891,17 @@
*
* Return value:
**/
-int em_format_is_inline(EMFormat *emf, CamelMimePart *part, const EMFormatHandler *handle)
+int em_format_is_inline(EMFormat *emf, const char *partid, CamelMimePart *part, const EMFormatHandler *handle)
{
- void *dummy, *override;
+ struct _EMFormatCache *emfc;
const char *tmp;
if (handle == NULL)
return FALSE;
- if (g_hash_table_lookup_extended(emf->inline_table, part, &dummy, &override))
- return GPOINTER_TO_INT(override);
+ emfc = g_hash_table_lookup(emf->inline_table, partid);
+ if (emfc && emfc->state != INLINE_UNSET)
+ return emfc->state & 1;
/* some types need to override the disposition, e.g. application/x-pkcs7-mime */
if (handle->flags & EM_FORMAT_HANDLER_INLINE_DISPOSITION)
@@ -866,16 +918,27 @@
/**
* em_format_set_inline:
* @emf:
- * @part:
+ * @partid: id of part
* @state:
*
* Force the attachment @part to be expanded or hidden explictly to match
* @state. This is used only to record the change for a redraw or
* cloned layout render and does not force a redraw.
**/
-void em_format_set_inline(EMFormat *emf, CamelMimePart *part, int state)
+void em_format_set_inline(EMFormat *emf, const char *partid, int state)
{
- g_hash_table_insert(emf->inline_table, part, GINT_TO_POINTER(state));
+ struct _EMFormatCache *emfc;
+
+ emfc = g_hash_table_lookup(emf->inline_table, partid);
+ if (emfc == NULL) {
+ emfc = emf_insert_cache(emf, partid);
+ } else if (emfc->state != INLINE_UNSET && (emfc->state & 1) == state)
+ return;
+
+ emfc->state = state?INLINE_ON:INLINE_OFF;
+
+ if (emf->message)
+ em_format_redraw(emf);
}
void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...)
@@ -1013,6 +1076,14 @@
extern CamelSession *session;
CamelMimePart *opart;
CamelCipherValidity *valid;
+ struct _EMFormatCache *emfc;
+
+ /* should this perhaps run off a key of ".secured" ? */
+ emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+ if (emfc && emfc->valid) {
+ em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+ return;
+ }
ex = camel_exception_new();
@@ -1024,6 +1095,12 @@
em_format_format_error(emf, stream, ex->desc?ex->desc:_("Could not parse S/MIME message: Unknown error"));
em_format_part_as(emf, stream, part, NULL);
} else {
+ if (emfc == NULL)
+ emfc = emf_insert_cache(emf, emf->part_id->str);
+
+ emfc->valid = camel_cipher_validity_clone(valid);
+ camel_object_ref((emfc->secured = opart));
+
em_format_format_secure(emf, stream, opart, valid);
}
@@ -1126,6 +1203,14 @@
const char *protocol;
CamelMimePart *opart;
CamelCipherValidity *valid;
+ struct _EMFormatCache *emfc;
+
+ /* should this perhaps run off a key of ".secured" ? */
+ emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+ if (emfc && emfc->valid) {
+ em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+ return;
+ }
/* Currently we only handle RFC2015-style PGP encryption. */
protocol = camel_content_type_param (((CamelDataWrapper *) part)->mime_type, "protocol");
@@ -1145,9 +1230,16 @@
em_format_format_error(emf, stream, ex->desc);
em_format_part_as(emf, stream, part, "multipart/mixed");
} else {
+ if (emfc == NULL)
+ emfc = emf_insert_cache(emf, emf->part_id->str);
+
+ emfc->valid = camel_cipher_validity_clone(valid);
+ camel_object_ref((emfc->secured = opart));
+
em_format_format_secure(emf, stream, opart, valid);
}
+ /* TODO: Make sure when we finalise this part, it is zero'd out */
camel_object_unref(opart);
camel_object_unref(context);
camel_exception_free(ex);
@@ -1272,6 +1364,14 @@
CamelMimePart *cpart;
CamelMultipartSigned *mps;
CamelCipherContext *cipher = NULL;
+ struct _EMFormatCache *emfc;
+
+ /* should this perhaps run off a key of ".secured" ? */
+ emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+ if (emfc && emfc->valid) {
+ em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+ return;
+ }
mps = (CamelMultipartSigned *)camel_medium_get_content_object((CamelMedium *)part);
if (!CAMEL_IS_MULTIPART_SIGNED(mps)
@@ -1308,6 +1408,12 @@
em_format_format_error(emf, stream, ex->desc);
em_format_part_as(emf, stream, part, "multipart/mixed");
} else {
+ if (emfc == NULL)
+ emfc = emf_insert_cache(emf, emf->part_id->str);
+
+ emfc->valid = camel_cipher_validity_clone(valid);
+ camel_object_ref((emfc->secured = cpart));
+
em_format_format_secure(emf, stream, cpart, valid);
}
Index: mail/em-format.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.h,v
retrieving revision 1.11
diff -u -3 -r1.11 em-format.h
--- mail/em-format.h 15 Mar 2004 15:19:00 -0000 1.11
+++ mail/em-format.h 9 Jul 2004 05:10:33 -0000
@@ -190,9 +190,10 @@
Or maybe it should live with sub-classes? */
int em_format_is_attachment(EMFormat *emf, struct _CamelMimePart *part);
-int em_format_is_inline(EMFormat *emf, struct _CamelMimePart *part, const EMFormatHandler *handle);
-/* FIXME: not sure about this api */
-void em_format_set_inline(EMFormat *emf, struct _CamelMimePart *part, int state);
+
+int em_format_is_inline(EMFormat *emf, const char *partid, struct _CamelMimePart *part, const EMFormatHandler *handle);
+void em_format_set_inline(EMFormat *emf, const char *partid, int state);
+
char *em_format_describe_part(struct _CamelMimePart *part, const char *mimetype);
/* for implementers */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]