From 4c20fe02c4bf78e56caf5393598fdb71b4ac772e Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 4 Jun 2002 23:58:22 +0000 Subject: The following changes take a great leap toward fixing bug #1042. 2002-06-04 Jeffrey Stedfast The following changes take a great leap toward fixing bug #1042. * mail-display.c (mail_display_push_content_location): New function to push a Content-Location value onto the MailDisplay. (mail_display_get_content_location): Gets the current Content-Location CamelURL value. (mail_display_pop_content_location): Pop the Content-Location off the stack. * mail-format.c (get_location): Do URL merging if the Content-Location isn't a full URL. If the Content-Location doesn't exist, pretend the URL is actually the Content-Location URL of our parent multipart (assuming it exists). If that doesn't exist, then yes - return NULL. (handle_multipart_related): Push the Content-Location header value of the multipart/related so that we can do URL merging in get_location() as we process each of the subparts. When we're done, pop it back off the stack. svn path=/trunk/; revision=17113 --- mail/ChangeLog | 21 ++++++++++++ mail/mail-display.c | 49 ++++++++++++++++++++++++++-- mail/mail-display.h | 13 ++++++-- mail/mail-format.c | 93 ++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 142 insertions(+), 34 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 380c4aebca..cd2e957b65 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,24 @@ +2002-06-04 Jeffrey Stedfast + + The following changes take a great leap toward fixing bug #1042. + + * mail-display.c (mail_display_push_content_location): New + function to push a Content-Location value onto the MailDisplay. + (mail_display_get_content_location): Gets the current + Content-Location CamelURL value. + (mail_display_pop_content_location): Pop the Content-Location off + the stack. + + * mail-format.c (get_location): Do URL merging if the + Content-Location isn't a full URL. If the Content-Location doesn't + exist, pretend the URL is actually the Content-Location URL of our + parent multipart (assuming it exists). If that doesn't exist, then + yes - return NULL. + (handle_multipart_related): Push the Content-Location header value + of the multipart/related so that we can do URL merging in + get_location() as we process each of the subparts. When we're + done, pop it back off the stack. + 2002-06-04 Christopher James Lahey * message-list.etspec: Added priorities. diff --git a/mail/mail-display.c b/mail/mail-display.c index 990905fc41..35521e9b13 100644 --- a/mail/mail-display.c +++ b/mail/mail-display.c @@ -754,14 +754,14 @@ save_url (MailDisplay *md, const char *url) urls = g_datalist_get_data (md->data, "part_urls"); g_return_val_if_fail (urls != NULL, NULL); - + part = g_hash_table_lookup (urls, url); if (part == NULL) { GByteArray *ba; - + urls = g_datalist_get_data (md->data, "data_urls"); g_return_val_if_fail (urls != NULL, NULL); - + /* See if it's some piece of cached data if it is then pretend it * is a mime part so that we can use the mime part saveing routines. * It is gross but it keeps duplicated code to a minimum and helps @@ -2420,4 +2420,47 @@ mail_display_get_url_for_icon (MailDisplay *md, const char *icon_name) } +struct _location_url_stack { + struct _location_url_stack *parent; + CamelURL *url; +}; + +void +mail_display_push_content_location (MailDisplay *md, const char *location) +{ + struct _location_url_stack *node; + CamelURL *url; + + url = camel_url_new (location, NULL); + node = g_new (struct _location_url_stack, 1); + node->parent = md->urls; + node->url = url; + md->urls = node; +} + +CamelURL * +mail_display_get_content_location (MailDisplay *md) +{ + return md->urls ? md->urls->url : NULL; +} + +void +mail_display_pop_content_location (MailDisplay *md) +{ + struct _location_url_stack *node; + + if (!md->urls) { + g_warning ("content-location stack underflow!"); + return; + } + + node = md->urls; + md->urls = node->parent; + + if (node->url) + camel_url_free (node->url); + + g_free (node); +} + E_MAKE_TYPE (mail_display, "MailDisplay", MailDisplay, mail_display_class_init, mail_display_init, PARENT_TYPE); diff --git a/mail/mail-display.h b/mail/mail-display.h index 0fcd98ab00..80d17d78c3 100644 --- a/mail/mail-display.h +++ b/mail/mail-display.h @@ -31,7 +31,7 @@ struct _MailDisplay { gint redisplay_counter; gpointer last_active; guint idle_id; - + char *charset; char *selection; @@ -40,6 +40,11 @@ struct _MailDisplay { CamelMimeMessage *current_message; GData **data; + /* stack of Content-Location URLs used for combining with a + relative URL Content-Location on a leaf part in order to + construct the full URL */ + struct _location_url_stack *urls; + GHashTable *related; /* related parts not displayed yet */ /* Sigh. This shouldn't be needed. I haven't figured out why it is @@ -47,7 +52,7 @@ struct _MailDisplay { GtkWidget *invisible; MailConfigDisplayStyle display_style; - + guint printing : 1; }; @@ -100,4 +105,8 @@ char *mail_display_add_url (MailDisplay *md, const char *kind, char *url, gpoint const char *mail_display_get_url_for_icon (MailDisplay *md, const char *icon_name); +void mail_display_push_content_location (MailDisplay *md, const char *location); +CamelURL *mail_display_get_content_location (MailDisplay *md); +void mail_display_pop_content_location (MailDisplay *md); + #endif /* _MAIL_DISPLAY_H_ */ diff --git a/mail/mail-format.c b/mail/mail-format.c index 03bd1991c5..54c2df859a 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -223,9 +223,9 @@ mail_format_raw_message (CamelMimeMessage *mime_message, MailDisplay *md, static const char * get_cid (CamelMimePart *part, MailDisplay *md) { - char *cid; static int fake_cid_counter = 0; - + char *cid; + /* If we have a real Content-ID, use it. If we don't, * make a (syntactically invalid, unique) fake one. */ @@ -241,14 +241,43 @@ get_cid (CamelMimePart *part, MailDisplay *md) static const char * get_location (CamelMimePart *part, MailDisplay *md) { + CamelURL *base; const char *loc; - - /* FIXME: relative URLs */ + char *location; + + base = mail_display_get_content_location (md); + loc = camel_mime_part_get_content_location (part); - if (!loc) - return NULL; - - return mail_display_add_url (md, "part_urls", g_strdup (loc), part); + if (!loc) { + if (!base) + return NULL; + + location = camel_url_to_string (base, 0); + return mail_display_add_url (md, "part_urls", location, part); + } + + /* kludge: If the multipart/related does not have a + Content-Location header and the HTML part doesn't contain a + Content-Location header either, then we will end up + generating a invalid unique identifier in the form of + "cid:@@@%d" for use in GtkHTML's iframe src url. This means + that when GtkHTML requests a relative URL, it will request + "cid:/%s" */ + mail_display_add_url (md, "part_urls", g_strdup_printf ("cid:/%s", loc), part); + + if (!strchr (loc, ':') && base) { + CamelURL *url; + + mail_display_add_url (md, "part_urls", g_strdup (loc), part); + + url = camel_url_new_with_base (base, loc); + location = camel_url_to_string (url, 0); + camel_url_free (url); + } else { + location = g_strdup (loc); + } + + return mail_display_add_url (md, "part_urls", location, part); } @@ -1652,7 +1681,6 @@ handle_text_html (CamelMimePart *part, const char *mime_type, gtk_html_set_base (html, base); } - /* FIXME: deal with relative URLs */ location = get_location (part, md); if (!location) location = get_cid (part, md); @@ -1870,32 +1898,32 @@ handle_multipart_related (CamelMimePart *part, const char *mime_type, CamelMultipart *mp; CamelMimePart *body_part, *display_part = NULL; CamelContentType *content_type; - const char *start; + const char *location, *start; int i, nparts; GHashTable *related_save; int ret; - + g_return_val_if_fail (CAMEL_IS_MULTIPART (wrapper), FALSE); mp = CAMEL_MULTIPART (wrapper); nparts = camel_multipart_get_number (mp); - + content_type = camel_mime_part_get_content_type (part); start = header_content_type_param (content_type, "start"); if (start) { int len; - + /* The "start" parameter includes <>s, which Content-Id * does not. */ len = strlen (start) - 2; - + for (i = 0; i < nparts; i++) { const char *cid; - + body_part = camel_multipart_get_part (mp, i); cid = camel_mime_part_get_content_id (body_part); - + if (!strncmp (cid, start + 1, len) && strlen (cid) == len) { display_part = body_part; @@ -1906,50 +1934,57 @@ handle_multipart_related (CamelMimePart *part, const char *mime_type, /* No start parameter, so it defaults to the first part. */ display_part = camel_multipart_get_part (mp, 0); } - + if (!display_part) { /* Oops. Hrmph. */ return handle_multipart_mixed (part, mime_type, md, html, stream); } - + /* setup a 'stack' of related parts */ related_save = md->related; md->related = g_hash_table_new(NULL, NULL); + location = camel_mime_part_get_content_location (part); + if (location) + mail_display_push_content_location (md, location); + /* Record the Content-ID/Content-Location of any non-displayed parts. */ for (i = 0; i < nparts; i++) { body_part = camel_multipart_get_part (mp, i); if (body_part == display_part) continue; - + get_cid (body_part, md); get_location (body_part, md); g_hash_table_insert(md->related, body_part, body_part); } - + /* Now, display the displayed part. */ ret = format_mime_part (display_part, md, html, stream); - + /* FIXME: flush html stream via gtkhtml_stream_flush which doens't exist yet ... */ - while (gtk_events_pending()) - gtk_main_iteration(); - + while (gtk_events_pending ()) + gtk_main_iteration (); + /* Now check for related parts which didn't display, display them as attachments */ for (i = 0; i < nparts; i++) { body_part = camel_multipart_get_part (mp, i); if (body_part == display_part) continue; - + if (g_hash_table_lookup(md->related, body_part)) { if (ret) write_hr (html, stream); - ret |= format_mime_part(body_part, md, html, stream); + ret |= format_mime_part (body_part, md, html, stream); } } - - g_hash_table_destroy(md->related); + + g_hash_table_destroy (md->related); md->related = related_save; - + + if (location) + mail_display_pop_content_location (md); + return ret; } -- cgit v1.2.3