From 9c9f8ebfdf5195ddd34fd4a726bf16941b063957 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 22 Oct 2001 18:47:59 +0000 Subject: PGP verification UI changes to make it not HTML spoofable. * mail-format.c (handle_application_pgp): Remove this unused hack. (mail_format_mime_message): Initialize a fourth hash table, used to keep track of fake MIME parts. (mail_part_set_default_displayed_inline): New routine to set the default disposition of a part (doesn't change it if the user has already overridden it). (format_mime_part): Wrap a blockquote around the error text (moved here from mail_error_write since it doesn't apply in other cases). (write_hr): Write a
with appropriate padding between MIME parts. (write_one_text_plain_chunk): Write some plain text with appropriate margins. (handle_text_plain): Use write_one_text_plain_chunk. Update for inline specials handler API change. (fake_mime_part_from_data): Use the "fake_parts" hash to avoid recreating the same fake parts again if the message is redisplayed. Lets you toggle the shown/hiddenness of uudecode parts, and do the new pgp verification thing for inline pgp signatures. (try_inline_pgp): Don't do any actual PGP handling here: Just rewrite as a multipart/encrypted. (try_inline_pgp_sig): Likewise, just do a multipart/signed (with the x-inline-pgp-hack parameter set). (try_uudecoding, try_inline_binhex): Update for API changes. (handle_multipart_signed): Exciting and new. Use to create a button which the user must click to do the verification. Change the formatting of the gpg output text a bit. * mail-display.c (on_link_clicked): Remove x-evolution-decode-pgp hack, which is no longer used. (pixbuf_gen_idle): Add a hack for the PGP verification button. (do_attachment_header, do_external_viewer): Split out of on_object_requeested for clarity. (do_signature): New routine to do the PGP verification button. (on_object_requested): Now just dispatches to do_attachment_header, do_external_viewer, or do_signature. (mail_error_write): Don't do
here. Fixed the problem that was trying to fix elsewhere. svn path=/trunk/; revision=13888 --- mail/ChangeLog | 128 +++++++---- mail/mail-display.c | 281 ++++++++++++----------- mail/mail-format.c | 626 ++++++++++++++++++++++------------------------------ 3 files changed, 495 insertions(+), 540 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 87ced53bdf..dcd356683e 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,47 @@ +2001-10-22 Dan Winship + + PGP verification UI changes to make it not HTML spoofable. + + * mail-format.c (handle_application_pgp): Remove this unused + hack. + (mail_format_mime_message): Initialize a fourth hash table, used + to keep track of fake MIME parts. + (mail_part_set_default_displayed_inline): New routine to set the + default disposition of a part (doesn't change it if the user has + already overridden it). + (format_mime_part): Wrap a blockquote around the error text (moved + here from mail_error_write since it doesn't apply in other cases). + (write_hr): Write a
with appropriate padding between MIME + parts. + (write_one_text_plain_chunk): Write some plain text with + appropriate margins. + (handle_text_plain): Use write_one_text_plain_chunk. Update for + inline specials handler API change. + (fake_mime_part_from_data): Use the "fake_parts" hash to avoid + recreating the same fake parts again if the message is + redisplayed. Lets you toggle the shown/hiddenness of uudecode + parts, and do the new pgp verification thing for inline pgp + signatures. + (try_inline_pgp): Don't do any actual PGP handling here: Just + rewrite as a multipart/encrypted. + (try_inline_pgp_sig): Likewise, just do a multipart/signed (with + the x-inline-pgp-hack parameter set). + (try_uudecoding, try_inline_binhex): Update for API changes. + (handle_multipart_signed): Exciting and new. Use to + create a button which the user must click to do the + verification. Change the formatting of the gpg output text a bit. + + * mail-display.c (on_link_clicked): Remove x-evolution-decode-pgp + hack, which is no longer used. + (pixbuf_gen_idle): Add a hack for the PGP verification button. + (do_attachment_header, do_external_viewer): Split out of + on_object_requeested for clarity. + (do_signature): New routine to do the PGP verification button. + (on_object_requested): Now just dispatches to + do_attachment_header, do_external_viewer, or do_signature. + (mail_error_write): Don't do
here. Fixed the problem + that was trying to fix elsewhere. + 2001-10-22 Dan Winship * mail-callbacks.c (transfer_msg): Fix these functions so they @@ -14220,48 +14264,48 @@ End of branch current_message = NULL, which shouldn't happen, but has happened to me. -2000-07-25 Dan Winship - - * message-thread.c (group_root_set): Don't group together messages - with the same non-Re: subject and no References/In-Reply-To. More - often than not, they're unrelated. (eg, "[No subject]".) - (thread_messages): Handle messages with no Message-Id. "This - shouldn't happen", but it does sometimes, and it's not much code - to make it just work. - -2000-07-25 Ettore Perazzoli - - * mail-config.c (create_service_page): Call - `gtk_option_menu_set_menu()' as the last thing, as `GtkOptionMenu' - is fscking broken. Also, `gtk_widget_show()' the individual menu - items. - -2000-07-24 Dan Winship - - * message-list.c (mark_msg_seen, ml_tree_set_value_at, - message_list_regenerate): Update for CamelFolder API changes. - (Certain functions no longer take a CamelException.) - - * mail-ops.c (real_fetch_mail, real_send_mail, real_delete_msg): - ditto - - * component-factory.c (real_create_imap_storage, - real_create_news_storage): ditto - -2000-07-24 Dan Winship - - * component-factory.c, folder-browser-factory.c, test-mail.c: - Remove GOAD support. - - * main.c: Remove GOAD support. - (main): More "guess the build mistake" fun, this time for the - failure to initialize Bonobo case. - -2000-07-24 Peter Williams - - * mail-tools.c (mail_tool_set_uid_flags): Change - function to faithfully pass parameters to - camel_folder_set_message_flags; this function is +2000-07-25 Dan Wnihspi dm + +* m seasegt-rhae.d cg(orpur_oo_tes)t :oD'n trguo poteghtrem seaseg +sw ti hht easemn noR-:es buejtca dnn oeRefercnseI/-neRlp-yoT .oMer +foet nhtnan to ,htyer' enueralet.d( ge ,["oNs buejtc"]). +t(rhae_demssgase:)H nald eemssgasew ti honM seasegI-.d" hTsi +hsuodl'n tahppne,"b tui todses motemise ,na dtis'n tom cu hoced +otm ka etij su towkr +.2 +00-0702- 5E ttro eeParzzlo i< teoterh@lexiocedc.mo +> + *amlic-noif.g cc(erta_eesvrci_eapeg:)C la +l` tg_kpoitnom_ne_ues_temun)( 'sat ehl sa thtni,ga sG`ktpOitnoeMun +'i ssfkcni grbkone .A sl,o` tg_kiwgdtes_oh(w')t ehi dnvidiau lemun +time.s + +02000--742 aD niWsnih p< adwnh@lexiocedc.mo +> + *emssga-eiltsc.( amkrm_gss_ee,nm _lrtees_tev_laeua_,t +emssga_eiltsr_genereta)e :pUadetf roC maleoFdlreA IPc ahgnse +.( eCtria nufcnitno sonl noeg rateka C malexEectpoi.n +) + *amlio-spc.( erlaf_tehcm_ia,lr ae_lesdnm_ia,lr ae_ledeletm_gs:) +idtt +o + *ocpmnone-taftcro.y cr(ae_lrcaeeti_am_ptsroga,e +erlac_erta_eensws_otareg:)d tiot + +02000--742 aD niWsnih p< adwnh@lexiocedc.mo +> + *ocpmnone-taftcro.y,cf loed-rrbwoes-raftcro.y,ct se-tamlic. +:R mevo eOGDAs puoptr +. + *amnic. :eRomevG AO Dusppro.t +m(ia)n :oMer" ugse sht eubli dimtska"ef nu ,htsit mi eof rht +ef iaulert onitiaiilezB nobo oaces +.2 +00-0702- 4P tereW liilma s< epetwrh@lexiocedc.mo +> + *amlit-ooslc.( amlit_oo_les_tiu_dlfga)s :hCnaeg +ufcnitnot oaftifhluylp sa saparemetsrt +oc malef_loed_res_temssga_elfga;st ih sufnction is somewhat useless now. Other files synced with API change. diff --git a/mail/mail-display.c b/mail/mail-display.c index 3dbd12523c..ebe1a5147c 100644 --- a/mail/mail-display.c +++ b/mail/mail-display.c @@ -218,11 +218,7 @@ on_link_clicked (GtkHTML *html, const char *url, MailDisplay *md) g_warning ("Can't handle news URLs yet."); else if (!g_strncasecmp (url, "mailto:", 7)) send_to_url (url); - else if (!strcmp (url, "x-evolution-decode-pgp:")) { - g_datalist_set_data (md->data, "show_pgp", - GINT_TO_POINTER (1)); - mail_display_queue_redisplay (md); - } else if (*url == '#') + else if (*url == '#') mail_display_jump_to_anchor (md, url); else gnome_url_show (url); @@ -580,9 +576,12 @@ pixbuf_gen_idle (struct _PixbufLoader *pbl) error = TRUE; } - if (error || !pbl->mstream) - pixbuf = pixbuf_for_mime_type (pbl->type); - else + if (error || !pbl->mstream) { + if (pbl->type) + pixbuf = pixbuf_for_mime_type (pbl->type); + else + pixbuf = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/pgp-signature-nokey.png"); + } else pixbuf = gdk_pixbuf_loader_get_pixbuf (pbl->loader); width = gdk_pixbuf_get_width (pixbuf); @@ -776,138 +775,94 @@ save_url (MailDisplay *md, const char *url) } static gboolean -on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) +do_attachment_header (GtkHTML *html, GtkHTMLEmbedded *eb, + CamelMimePart *part, MailDisplay *md) { - MailDisplay *md = data; - GHashTable *urls; - CamelMedium *medium; - CamelDataWrapper *wrapper; - OAF_ServerInfo *component; - GtkWidget *embedded; - BonoboObjectClient *server; - Bonobo_PersistStream persist; - CORBA_Environment ev; - GByteArray *ba; - CamelStream *cstream; - BonoboStream *bstream; - char *cid; + GtkWidget *button, *mainbox, *hbox, *arrow, *popup; + MailMimeHandler *handler; + struct _PixbufLoader *pbl; - cid = eb->classid; + pbl = g_new0 (struct _PixbufLoader, 1); + if (g_strncasecmp (eb->type, "image/", 6) == 0) { + CamelDataWrapper *content; - if (!strncmp (cid, "popup:", 6)) - cid += 6; - if (strncmp (cid, "cid:", 4) != 0) - return FALSE; + content = camel_medium_get_content_object (CAMEL_MEDIUM (part)); + if (!camel_data_wrapper_is_offline (content)) { + pbl->mstream = camel_stream_mem_new (); + camel_data_wrapper_write_to_stream (content, pbl->mstream); + camel_stream_reset (pbl->mstream); + } + } + pbl->type = g_strdup (eb->type); + pbl->cid = g_strdup (eb->classid + 6); + pbl->pixmap = bonobo_ui_toolbar_icon_new (); + pbl->eb = eb; + pbl->destroy_id = gtk_signal_connect (GTK_OBJECT (eb), "destroy", + embeddable_destroy_cb, pbl); - urls = g_datalist_get_data (md->data, "part_urls"); - g_return_val_if_fail (urls != NULL, FALSE); + g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc)pixbuf_gen_idle, + pbl, NULL); - medium = g_hash_table_lookup (urls, cid); - g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), FALSE); + mainbox = gtk_hbox_new (FALSE, 0); - if (cid != eb->classid) { - /* This is a part wrapper */ -#ifdef USE_OLD_DISPLAY_STYLE - GtkWidget *ebox; -#else - GtkWidget *button, *mainbox, *hbox, *arrow, *popup; - MailMimeHandler *handler; -#endif - struct _PixbufLoader *pbl; + button = gtk_button_new (); + gtk_object_set_data (GTK_OBJECT (button), "MailDisplay", md); - pbl = g_new0 (struct _PixbufLoader, 1); - if (g_strncasecmp (eb->type, "image/", 6) == 0) { - CamelDataWrapper *content; + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (button_press), part); - content = camel_medium_get_content_object (medium); - if (!camel_data_wrapper_is_offline (content)) { - pbl->mstream = camel_stream_mem_new (); - camel_data_wrapper_write_to_stream (content, pbl->mstream); - camel_stream_reset (pbl->mstream); - } - } - pbl->type = g_strdup (eb->type); - pbl->cid = g_strdup (cid); - pbl->pixmap = bonobo_ui_toolbar_icon_new (); - pbl->eb = eb; - pbl->destroy_id = gtk_signal_connect (GTK_OBJECT (eb), - "destroy", - embeddable_destroy_cb, - pbl); - - g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc)pixbuf_gen_idle, - pbl, NULL); + hbox = gtk_hbox_new (FALSE, 2); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); -#ifdef USE_OLD_DISPLAY_STYLE - ebox = gtk_event_box_new (); - gtk_widget_set_sensitive (GTK_WIDGET (ebox), TRUE); - gtk_widget_add_events (GTK_WIDGET (ebox), - GDK_BUTTON_PRESS_MASK); - gtk_object_set_data (GTK_OBJECT (ebox), "MailDisplay", md); - gtk_object_set_data (GTK_OBJECT (ebox), "CamelMimePart", - medium); - gtk_object_set_data_full (GTK_OBJECT (ebox), "mime_type", - g_strdup (eb->type), - (GDestroyNotify)g_free); - - gtk_signal_connect (GTK_OBJECT (ebox), "button_press_event", - GTK_SIGNAL_FUNC (pixmap_press), md->scroll); - - gtk_container_add (GTK_CONTAINER (ebox), pbl->pixmap); - gtk_widget_show_all (ebox); - gtk_container_add (GTK_CONTAINER (eb), ebox); -#else - mainbox = gtk_hbox_new (FALSE, 0); - - button = gtk_button_new (); - gtk_object_set_data (GTK_OBJECT (button), "MailDisplay", md); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (button_press), medium); - - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); - - if (mail_part_is_displayed_inline (CAMEL_MIME_PART (medium), md)) { - arrow = gnome_stock_new_with_icon (GNOME_STOCK_PIXMAP_DOWN); - } else { - arrow = gnome_stock_new_with_icon (GNOME_STOCK_PIXMAP_FORWARD); - } - gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), pbl->pixmap, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (button), hbox); - - popup = gtk_button_new (); - gtk_container_add (GTK_CONTAINER (popup), - gtk_arrow_new (GTK_ARROW_DOWN, - GTK_SHADOW_ETCHED_IN)); - - gtk_object_set_data (GTK_OBJECT (popup), "MailDisplay", md); - gtk_object_set_data (GTK_OBJECT (popup), "CamelMimePart", - medium); - gtk_object_set_data_full (GTK_OBJECT (popup), "mime_type", - g_strdup (eb->type), - (GDestroyNotify)g_free); - - gtk_signal_connect (GTK_OBJECT (popup), "button_press_event", - GTK_SIGNAL_FUNC (pixmap_press), md->scroll); - - gtk_box_pack_start (GTK_BOX (mainbox), button, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (mainbox), popup, TRUE, TRUE, 0); - gtk_widget_show_all (mainbox); - - handler = mail_lookup_handler (eb->type); - if (handler && handler->builtin) { - gtk_widget_set_sensitive (button, TRUE); - } else { - gtk_widget_set_sensitive (button, FALSE); - } + if (mail_part_is_displayed_inline (part, md)) + arrow = gnome_stock_new_with_icon (GNOME_STOCK_PIXMAP_DOWN); + else + arrow = gnome_stock_new_with_icon (GNOME_STOCK_PIXMAP_FORWARD); + gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), pbl->pixmap, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (button), hbox); + + popup = gtk_button_new (); + gtk_container_add (GTK_CONTAINER (popup), + gtk_arrow_new (GTK_ARROW_DOWN, + GTK_SHADOW_ETCHED_IN)); + + gtk_object_set_data (GTK_OBJECT (popup), "MailDisplay", md); + gtk_object_set_data (GTK_OBJECT (popup), "CamelMimePart", part); + gtk_object_set_data_full (GTK_OBJECT (popup), "mime_type", + g_strdup (eb->type), (GDestroyNotify)g_free); + + gtk_signal_connect (GTK_OBJECT (popup), "button_press_event", + GTK_SIGNAL_FUNC (pixmap_press), md->scroll); + + gtk_box_pack_start (GTK_BOX (mainbox), button, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (mainbox), popup, TRUE, TRUE, 0); + gtk_widget_show_all (mainbox); + + handler = mail_lookup_handler (eb->type); + if (handler && handler->builtin) + gtk_widget_set_sensitive (button, TRUE); + else + gtk_widget_set_sensitive (button, FALSE); - gtk_container_add (GTK_CONTAINER (eb), mainbox); -#endif + gtk_container_add (GTK_CONTAINER (eb), mainbox); - return TRUE; - } + return TRUE; +} + +static gboolean +do_external_viewer (GtkHTML *html, GtkHTMLEmbedded *eb, + CamelMimePart *part, MailDisplay *md) +{ + CamelDataWrapper *wrapper; + OAF_ServerInfo *component; + GtkWidget *embedded; + BonoboObjectClient *server; + Bonobo_PersistStream persist; + CORBA_Environment ev; + GByteArray *ba; + CamelStream *cstream; + BonoboStream *bstream; component = gnome_vfs_mime_get_default_component (eb->type); if (!component) @@ -929,7 +884,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) /* Write the data to a CamelStreamMem... */ ba = g_byte_array_new (); cstream = camel_stream_mem_new_with_byte_array (ba); - wrapper = camel_medium_get_content_object (medium); + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part)); camel_data_wrapper_write_to_stream (wrapper, cstream); /* ...convert the CamelStreamMem to a BonoboStreamMem... */ @@ -958,6 +913,66 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) return TRUE; } + +static gboolean +do_signature (GtkHTML *html, GtkHTMLEmbedded *eb, + CamelMimePart *part, MailDisplay *md) +{ + GtkWidget *button; + struct _PixbufLoader *pbl; + + pbl = g_new0 (struct _PixbufLoader, 1); + pbl->type = NULL; + pbl->cid = g_strdup (eb->classid); + pbl->pixmap = bonobo_ui_toolbar_icon_new (); + pbl->eb = eb; + pbl->destroy_id = gtk_signal_connect (GTK_OBJECT (eb), "destroy", + embeddable_destroy_cb, pbl); + + g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc)pixbuf_gen_idle, + pbl, NULL); + + button = gtk_button_new (); + gtk_object_set_data (GTK_OBJECT (button), "MailDisplay", md); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (button_press), part); + gtk_container_add (GTK_CONTAINER (button), pbl->pixmap); + gtk_widget_show_all (button); + gtk_container_add (GTK_CONTAINER (eb), button); + + return TRUE; +} + +static gboolean +on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) +{ + MailDisplay *md = data; + GHashTable *urls; + CamelMimePart *part; + + urls = g_datalist_get_data (md->data, "part_urls"); + if (!urls) + return FALSE; + + if (!strncmp (eb->classid, "popup:", 6)) { + part = g_hash_table_lookup (urls, eb->classid + 6); + if (!CAMEL_IS_MIME_PART (part)) + return FALSE; + return do_attachment_header (html, eb, part, md); + } else if (!strncmp (eb->classid, "signature:", 10)) { + part = g_hash_table_lookup (urls, eb->classid); + if (!CAMEL_IS_MIME_PART (part)) + return FALSE; + return do_signature (html, eb, part, md); + } else if (!strncmp (eb->classid, "cid:", 4)) { + part = g_hash_table_lookup (urls, eb->classid); + if (!CAMEL_IS_MIME_PART (part)) + return FALSE; + return do_external_viewer (html, eb, part, md); + } + + return FALSE; +} static void load_http (MailDisplay *md, gpointer data) @@ -1336,9 +1351,9 @@ mail_error_write (GtkHTML *html, GtkHTMLStream *stream, htmltext = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); g_free (buf); - gtk_html_stream_printf (stream, "
"); + gtk_html_stream_printf (stream, ""); gtk_html_stream_write (stream, htmltext, strlen (htmltext)); - gtk_html_stream_printf (stream, "
"); + gtk_html_stream_printf (stream, ""); g_free (htmltext); } @@ -1540,11 +1555,13 @@ link_open_in_browser (GtkWidget *w, MailDisplay *mail_display) mail_display); } +#if 0 static void link_save_as (GtkWidget *w, MailDisplay *mail_display) { g_print ("FIXME save %s\n", mail_display->html->pointer_url); } +#endif static void link_copy_location (GtkWidget *w, MailDisplay *mail_display) diff --git a/mail/mail-format.c b/mail/mail-format.c index 91545cd97a..00be9a5a14 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "mail.h" #include "mail-tools.h" @@ -49,12 +50,14 @@ #include "mail-mt.h" #include "mail-crypto.h" -static char *try_inline_pgp (char *start, CamelMimePart *part, MailDisplay *md); -static char *try_inline_pgp_sig (char *start, CamelMimePart *part, MailDisplay *md); -static char *try_uudecoding (char *start, CamelMimePart *part, MailDisplay *md); -static char *try_inline_binhex (char *start, CamelMimePart *part, MailDisplay *md); - -static void decode_pgp (CamelStream *ciphertext, CamelStream *plaintext, MailDisplay *md); +static char *try_inline_pgp (char *start, CamelMimePart *part, + guint offset, MailDisplay *md); +static char *try_inline_pgp_sig (char *start, CamelMimePart *part, + guint offset, MailDisplay *md); +static char *try_uudecoding (char *start, CamelMimePart *part, + guint offset, MailDisplay *md); +static char *try_inline_binhex (char *start, CamelMimePart *part, + guint offset, MailDisplay *md); static gboolean handle_text_plain (CamelMimePart *part, const char *mime_type, @@ -95,12 +98,6 @@ static gboolean handle_message_external_body (CamelMimePart *part, const char *mime_type, MailDisplay *md); -#ifdef APPLICATION_PGP_IS_NO_LONGER_SUPPORTED -static gboolean handle_application_pgp (CamelMimePart *part, - const char *mime_type, - MailDisplay *md); -#endif /* APPLICATION_PGP_IS_NO_LONGER_SUPPORTED */ - static gboolean handle_via_bonobo (CamelMimePart *part, const char *mime_type, MailDisplay *md); @@ -159,28 +156,33 @@ add_url (const char *kind, char *url, gpointer data, MailDisplay *md) void mail_format_mime_message (CamelMimeMessage *mime_message, MailDisplay *md) { - GHashTable *urls; + GHashTable *hash; g_return_if_fail (CAMEL_IS_MIME_MESSAGE (mime_message)); - urls = g_datalist_get_data (md->data, "part_urls"); - if (!urls) { - urls = g_hash_table_new (g_str_hash, g_str_equal); - g_datalist_set_data_full (md->data, "part_urls", urls, + hash = g_datalist_get_data (md->data, "part_urls"); + if (!hash) { + hash = g_hash_table_new (g_str_hash, g_str_equal); + g_datalist_set_data_full (md->data, "part_urls", hash, free_part_urls); } - urls = g_datalist_get_data (md->data, "data_urls"); - if (!urls) { - urls = g_hash_table_new (g_str_hash, g_str_equal); - g_datalist_set_data_full (md->data, "data_urls", urls, + hash = g_datalist_get_data (md->data, "data_urls"); + if (!hash) { + hash = g_hash_table_new (g_str_hash, g_str_equal); + g_datalist_set_data_full (md->data, "data_urls", hash, free_data_urls); } - /* ok, so they're not urls. so sue me. */ - urls = g_datalist_get_data (md->data, "attachment_states"); - if (!urls) { - urls = g_hash_table_new (g_direct_hash, g_direct_equal); - g_datalist_set_data_full (md->data, "attachment_states", urls, + hash = g_datalist_get_data (md->data, "attachment_states"); + if (!hash) { + hash = g_hash_table_new (NULL, NULL); + g_datalist_set_data_full (md->data, "attachment_states", hash, + (GDestroyNotify) g_hash_table_destroy); + } + hash = g_datalist_get_data (md->data, "fake_parts"); + if (!hash) { + hash = g_hash_table_new (NULL, NULL); + g_datalist_set_data_full (md->data, "fake_parts", hash, (GDestroyNotify) g_hash_table_destroy); } @@ -358,15 +360,6 @@ setup_mime_tables (void) g_hash_table_insert (mime_function_table, "multipart/signed", handle_multipart_signed); -#ifdef APPLICATION_PGP_IS_NO_LONGER_SUPPORTED - /* Some broken mailers, such as The Bat! send pgp - * signed/encrypted messages with a content-type of - * application/pgp which basically means it's a text/plain but - * either signed or encrypted. */ - g_hash_table_insert (mime_function_table, "application/pgp", - handle_application_pgp); -#endif /* APPLICATION_PGP_IS_NO_LONGER_SUPPORTED */ - /* RFC 2046 says unrecognized text subtypes can be treated * as text/plain (as long as you recognize the character set), * and unrecognized multipart subtypes as multipart/mixed. */ @@ -531,15 +524,6 @@ mail_part_is_inline (CamelMimePart *part) if (!header_content_type_is (content_type, "message", "*")) return TRUE; -#ifdef APPLICATION_PGP_IS_NO_LONGER_SUPPORTED - /* The Bat! and possibly a few other broken mailers send application/pgp - * parts instead of following rfc2015 because they SUCK!!! Since this part - * is really a text/plain part, we should show it inline. - */ - if (!header_content_type_is (content_type, "application", "pgp")) - return TRUE; -#endif /* APPLICATION_PGP_IS_NO_LONGER_SUPPORTED */ - /* Otherwise, display it inline if it's "anonymous", and * as an attachment otherwise. */ @@ -610,6 +594,19 @@ mail_part_toggle_displayed (CamelMimePart *part, MailDisplay *md) g_hash_table_insert (asht, part, GINT_TO_POINTER (state)); } +static void +mail_part_set_default_displayed_inline (CamelMimePart *part, MailDisplay *md, + gboolean displayed) +{ + GHashTable *asht = g_datalist_get_data (md->data, "attachment_states"); + gint state; + + if (g_hash_table_lookup (asht, part)) + return; + + state = I_VALID | (displayed ? I_DISPLAYED : 0); + g_hash_table_insert (asht, part, GINT_TO_POINTER (state)); +} static void attachment_header (CamelMimePart *part, const char *mime_type, MailDisplay *md) @@ -652,14 +649,6 @@ attachment_header (CamelMimePart *part, const char *mime_type, MailDisplay *md) g_free (htmlinfo); } -#if 0 - /* Describe the click action, if any. */ - if (action) { - mail_html_write (md->html, md->stream, - "
Click on the icon to %s.", action); - } -#endif - mail_html_write (md->html, md->stream, "" "
\n"); @@ -685,7 +674,8 @@ format_mime_part (CamelMimePart *part, MailDisplay *md) char *mesg; mesg = e_utf8_from_locale_string (_("Could not parse MIME message. Displaying as source.")); - mail_error_write (md->html, md->stream, "%s", mesg); + mail_error_write (md->html, md->stream, + "
%s
", mesg); g_free (mesg); if (mail_content_loaded (wrapper, md, TRUE, NULL, NULL)) handle_text_plain (part, "text/plain", md); @@ -1103,13 +1093,22 @@ mail_format_get_data_wrapper_text (CamelDataWrapper *wrapper, MailDisplay *mail_ return ba; } +static void +write_hr (MailDisplay *md) +{ + mail_html_write (md->html, md->stream, + "
" + "
\n"); +} + /*----------------------------------------------------------------------* * Mime handling functions *----------------------------------------------------------------------*/ struct { char *start; - char * (*handler) (char *start, CamelMimePart *part, MailDisplay *md); + char * (*handler) (char *start, CamelMimePart *part, + guint offset, MailDisplay *md); } text_specials[] = { { "-----BEGIN PGP MESSAGE-----\n", try_inline_pgp }, { "-----BEGIN PGP SIGNED MESSAGE-----\n", try_inline_pgp_sig }, @@ -1118,6 +1117,14 @@ struct { }; #define NSPECIALS (sizeof (text_specials) / sizeof (*text_specials)) +static void +write_one_text_plain_chunk (const char *text, int len, MailDisplay *md) +{ + mail_html_write (md->html, md->stream, "
\n"); + mail_text_write (md->html, md->stream, "%.*s", len, text); + mail_html_write (md->html, md->stream, "
\n"); +} + static gboolean handle_text_plain (CamelMimePart *part, const char *mime_type, MailDisplay *md) @@ -1145,10 +1152,6 @@ handle_text_plain (CamelMimePart *part, const char *mime_type, if (format && !g_strcasecmp (format, "flowed")) return handle_text_plain_flowed (text, md); - mail_html_write (md->html, md->stream, - "\n\n" - "
\n"); - /* Only look for binhex and stuff if this is real text/plain. * (and not, say, application/mac-binhex40 that mail-identify * has decided to call text/plain because it starts with English @@ -1168,12 +1171,10 @@ handle_text_plain (CamelMimePart *part, const char *mime_type, break; /* Deal with special case */ - if (start != p) { - /* the %.*s thing just grabs upto start-p chars; go read ANSI C */ - mail_text_write (md->html, md->stream, "%.*s", start-p, p); - } + if (start != p) + write_one_text_plain_chunk (p, start - p, md); - p = text_specials[i].handler (start, part, md); + p = text_specials[i].handler (start, part, start - text, md); if (p == start) { /* Oops. That failed. Output this line normally and * skip over it. @@ -1185,77 +1186,19 @@ handle_text_plain (CamelMimePart *part, const char *mime_type, break; } p++; - mail_text_write (md->html, md->stream, "%.*s", p-start, start); + write_one_text_plain_chunk (start, p - start, md); } else if (p) - mail_html_write (md->html, md->stream, "
"); + write_hr (md); } /* Finish up (or do the whole thing if there were no specials). */ if (p) - mail_text_write (md->html, md->stream, "%s", p); + write_one_text_plain_chunk (p, strlen (p), md); g_free (text); - mail_html_write (md->html, md->stream, "
\n"); return TRUE; } -#ifdef APPLICATION_PGP_IS_NO_LONGER_SUPPORTED -/* This is a special-case hack from broken mailers such as The Bat! */ -static gboolean -handle_application_pgp (CamelMimePart *part, const char *mime_type, - MailDisplay *md) -{ - CamelDataWrapper *wrapper = - camel_medium_get_content_object (CAMEL_MEDIUM (part)); - const char *format, *xaction; - CamelMimePart *mime_part; - CamelContentType *type; - GByteArray *bytes; - - /* Check the format and x-action parameters. */ - type = camel_mime_part_get_content_type (part); - format = header_content_type_param (type, "format"); - xaction = header_content_type_param (type, "x-action"); - - /* We don't know how to handle non-text broken-pgp'd mime parts */ - if (g_strcasecmp (format, "text") != 0) - return FALSE; - - bytes = mail_format_get_data_wrapper_text (wrapper, md); - if (!bytes) - return FALSE; - - mime_part = camel_mime_part_new (); - if (!g_strcasecmp (xaction, "sign")) { - camel_mime_part_set_content (mime_part, bytes->data, bytes->len, "text/plain"); - } else { - CamelStream *ciphertext, *plaintext; - GByteArray *buffer; - - ciphertext = camel_stream_mem_new (); - camel_stream_write (ciphertext, bytes->data, bytes->len); - camel_stream_reset (ciphertext); - - plaintext = camel_stream_mem_new (); - decode_pgp (ciphertext, plaintext, md); - camel_object_unref (CAMEL_OBJECT (ciphertext)); - - buffer = CAMEL_STREAM_MEM (plaintext)->buffer; - - camel_mime_part_set_content (mime_part, buffer->data, buffer->len, "text/plain"); - camel_object_unref (CAMEL_OBJECT (plaintext)); - } - - g_byte_array_free (bytes, TRUE); - - camel_medium_set_content_object (CAMEL_MEDIUM (part), - camel_medium_get_content_object (CAMEL_MEDIUM (mime_part))); - camel_object_unref (CAMEL_OBJECT (mime_part)); - - return handle_text_plain (part, "text/plain", md); -} -#endif /* APPLICATION_PGP_IS_NO_LONGER_SUPPORTED */ - static gboolean handle_text_plain_flowed (char *buf, MailDisplay *md) { @@ -1336,12 +1279,18 @@ handle_text_plain_flowed (char *buf, MailDisplay *md) } static CamelMimePart * -fake_mime_part_from_data (const char *data, int len, const char *type) +fake_mime_part_from_data (const char *data, int len, const char *type, + guint offset, MailDisplay *md) { + GHashTable *fake_parts = g_datalist_get_data (md->data, "fake_parts"); CamelStream *memstream; CamelDataWrapper *wrapper; CamelMimePart *part; + part = g_hash_table_lookup (fake_parts, GUINT_TO_POINTER (offset)); + if (part) + return part; + memstream = camel_stream_mem_new_with_buffer (data, len); wrapper = camel_data_wrapper_new (); camel_data_wrapper_construct_from_stream (wrapper, memstream); @@ -1351,6 +1300,8 @@ fake_mime_part_from_data (const char *data, int len, const char *type) camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper); camel_object_unref (CAMEL_OBJECT (wrapper)); camel_mime_part_set_disposition (part, "inline"); + + g_hash_table_insert (fake_parts, GUINT_TO_POINTER (offset), part); return part; } @@ -1360,229 +1311,118 @@ destroy_part (CamelObject *root, gpointer event_data, gpointer user_data) camel_object_unref (user_data); } -static void -decode_pgp (CamelStream *ciphertext, CamelStream *plaintext, MailDisplay *md) -{ - CamelException ex; - - camel_exception_init (&ex); - - /* FIXME: multipart parts */ - if (g_datalist_get_data (md->data, "show_pgp")) { - CamelPgpContext *ctx; - - ctx = camel_pgp_context_new (session, mail_config_get_pgp_type (), - mail_config_get_pgp_path ()); - - if (ctx) { - camel_pgp_decrypt (ctx, ciphertext, plaintext, &ex); - camel_object_unref (CAMEL_OBJECT (ctx)); - camel_stream_reset (plaintext); - } else { - camel_exception_setv (&ex, CAMEL_EXCEPTION_SYSTEM, - _("No GPG/PGP program configured.")); - } - - if (!camel_exception_is_set (&ex)) - return; - } - - mail_html_write (md->html, md->stream, - "
" - "" - "", - get_url_for_icon ("gnome-lockscreen.png", md)); - - if (camel_exception_is_set (&ex)) { - char *str; - - str = e_utf8_from_locale_string (_("Encrypted message not displayed")); - mail_html_write (md->html, md->stream, "%s

\n", str); - g_free (str); - - str = e_utf8_from_locale_string (camel_exception_get_description (&ex)); - mail_error_write (md->html, md->stream, "%s", str); - camel_exception_clear (&ex); - g_free (str); - } else { - char *str1, *str2; - - str1 = e_utf8_from_locale_string (_("Encrypted message")); - str2 = e_utf8_from_locale_string (_("Click icon to decrypt.")); - mail_html_write (md->html, md->stream, "%s

\n%s", - str1, str2); - g_free (str1); - g_free (str2); - } - - mail_html_write (md->html, md->stream, "
"); -} - static char * -try_inline_pgp (char *start, CamelMimePart *part, MailDisplay *md) +try_inline_pgp (char *start, CamelMimePart *mime_part, + guint offset, MailDisplay *md) { - CamelStream *ciphertext, *plaintext; - GByteArray *buffer; + CamelMimePart *part; + CamelMultipart *multipart; char *end; - + end = strstr (start, "-----END PGP MESSAGE-----"); if (!end) return start; - - end += strlen ("-----END PGP MESSAGE-----") - 1; - - mail_html_write (md->html, md->stream, "
"); - - ciphertext = camel_stream_mem_new (); - camel_stream_write (ciphertext, start, end - start); - camel_stream_reset (ciphertext); - - plaintext = camel_stream_mem_new (); - decode_pgp (ciphertext, plaintext, md); - camel_object_unref (CAMEL_OBJECT (ciphertext)); - - buffer = CAMEL_STREAM_MEM (plaintext)->buffer; - if (buffer && buffer->len) { - mail_html_write (md->html, md->stream, - "
"); - mail_text_write (md->html, md->stream, "%.*s", buffer->len, buffer->data); - mail_html_write (md->html, md->stream, "
"); - } - - camel_object_unref (CAMEL_OBJECT (plaintext)); - - return end; -} -static void -mail_write_authenticity (MailDisplay *md, CamelCipherValidity *valid) -{ - char *str; - - /* Now display the "seal-of-authenticity" or something... */ - if (valid && camel_cipher_validity_get_valid (valid)) { - str = e_utf8_from_locale_string ( - _("This message is digitally signed and " - "has been found to be authentic.")); - mail_html_write (md->html, md->stream, - "
\n" - "" - "
%s

", - get_url_for_icon (EVOLUTION_ICONSDIR "/pgp-signature-ok.png", md), - str); - g_free (str); - } else { - str = e_utf8_from_locale_string ( - _("This message is digitally signed but can " - "not be proven to be authentic.")); - mail_html_write (md->html, md->stream, - "
\n" - "" - "
%s

", - get_url_for_icon (EVOLUTION_ICONSDIR "/pgp-signature-bad.png", md), - str); - g_free (str); - } + end += sizeof ("-----END PGP MESSAGE-----") - 1; - if (valid && camel_cipher_validity_get_description (valid)) { - mail_error_write (md->html, md->stream, "%s", - camel_cipher_validity_get_description (valid)); - mail_html_write (md->html, md->stream, "

"); - } + multipart = camel_multipart_new (); + camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), + "multipart/encrypted; " + "protocol=\"application/pgp-encrypted\""); + + part = fake_mime_part_from_data ("Version: 1\n", + sizeof ("Version: 1\n") - 1, + "application/pgp-encrypted", + offset + 1, md); + camel_multipart_add_part (multipart, part); + camel_object_unref (CAMEL_OBJECT (part)); + + part = fake_mime_part_from_data (start, end - start + 1, + "application/octet-stream", + offset, md); + camel_multipart_add_part (multipart, part); + camel_object_unref (CAMEL_OBJECT (part)); + + part = camel_mime_part_new (); + camel_medium_set_content_object (CAMEL_MEDIUM (part), + CAMEL_DATA_WRAPPER (multipart)); + + camel_object_hook_event (CAMEL_OBJECT (md->current_message), + "finalize", destroy_part, part); + + write_hr (md); + format_mime_part (part, md); + + return end; } static char * -try_inline_pgp_sig (char *start, CamelMimePart *part, MailDisplay *md) +try_inline_pgp_sig (char *start, CamelMimePart *mime_part, + guint offset, MailDisplay *md) { - CamelCipherValidity *valid = NULL; - CamelPgpContext *context; - char *msg_start, *pgp_start, *sig_start, *sig_end; - - pgp_start = strstr (start, "-----BEGIN PGP SIGNED MESSAGE-----"); - if (pgp_start) { - /* skip over -----BEGIN PGP SIGNED MESSAGE----- */ - msg_start = strchr (pgp_start, '\n'); - if (!msg_start++) - return start; - - /* skip over Hash: header */ - msg_start = strchr (msg_start, '\n'); - if (!msg_start++) - return start; - } else { - /* Some MUAs don't enclose the signed text in - -----BEGIN PGP SIGNED MESSAGE----- */ - msg_start = start; - } - - /* find the beginning of the signature block */ - sig_start = strstr (msg_start, "-----BEGIN PGP SIGNATURE-----"); - if (!sig_start) + CamelMimePart *part; + CamelMultipart *multipart; + char *msg_start, *msg_end, *sig_start, *sig_end; + CamelContentType *type; + char *type_str; + + /* We know start points to "-----BEGIN PGP SIGNED MESSAGE-----" */ + msg_start = start + sizeof ("-----BEGIN PGP SIGNED MESSAGE-----") - 1; + if (*msg_start++ != '\n') return start; - - /* find the end of the pgp signature block */ + /* Skip 'One or more "Hash" Armor Headers' followed by + * 'Exactly one empty line'. + */ + msg_start = strstr (msg_start, "\n\n"); + if (!msg_start) + return start; + msg_start += 2; + msg_end = strstr (msg_start, "-----BEGIN PGP SIGNATURE-----"); + if (!msg_end) + return start; + msg_end--; + + sig_start = msg_end; sig_end = strstr (sig_start, "-----END PGP SIGNATURE-----"); if (!sig_end) return start; - - sig_end += strlen ("-----END PGP SIGNATURE-----") + 1; - - mail_html_write (md->html, md->stream, "
"); - - context = camel_pgp_context_new (session, mail_config_get_pgp_type (), - mail_config_get_pgp_path ()); - - if (context) { - CamelMimeFilterCharset *charset_filter; - CamelStreamFilter *filtered_stream; - CamelStream *ciphertext; - CamelContentType *type; - const char *charset; - CamelException *ex; - - ex = camel_exception_new (); - - ciphertext = camel_stream_mem_new (); - - type = camel_mime_part_get_content_type (part); - charset = header_content_type_param (type, "charset"); - if (!charset) - charset = mail_config_get_default_charset (); - - filtered_stream = camel_stream_filter_new_with_stream (ciphertext); - charset_filter = camel_mime_filter_charset_new_convert ("utf-8", charset); - if (charset_filter) { - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (charset_filter)); - camel_object_unref (CAMEL_OBJECT (charset_filter)); - } - - camel_stream_write (CAMEL_STREAM (filtered_stream), pgp_start, sig_end - pgp_start); - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - - camel_stream_reset (ciphertext); - - valid = camel_pgp_verify (context, ciphertext, NULL, ex); - camel_object_unref (CAMEL_OBJECT (ciphertext)); - camel_object_unref (CAMEL_OBJECT (context)); - - camel_exception_free (ex); - } - - mail_text_write (md->html, md->stream, "%.*s", sig_start - msg_start, msg_start); - - mail_write_authenticity (md, valid); - - mail_html_write (md->html, md->stream, "
"); - - camel_cipher_validity_free (valid); - + sig_end += sizeof ("-----END PGP SIGNATURE-----") - 1; + + multipart = camel_multipart_new (); + camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), + "multipart/signed; micalg=pgp-md5" + "; x-inline-pgp-hack=true"); + + type = camel_mime_part_get_content_type (mime_part); + type_str = header_content_type_format (type); + part = fake_mime_part_from_data (msg_start, msg_end - msg_start, + type_str, offset, md); + g_free (type_str); + camel_multipart_add_part (multipart, part); + camel_object_unref (CAMEL_OBJECT (part)); + + part = fake_mime_part_from_data (sig_start, sig_end - sig_start, + "application/pgp-signature", + offset + 1, md); + camel_multipart_add_part (multipart, part); + camel_object_unref (CAMEL_OBJECT (part)); + + part = camel_mime_part_new (); + camel_medium_set_content_object (CAMEL_MEDIUM (part), + CAMEL_DATA_WRAPPER (multipart)); + + camel_object_hook_event (CAMEL_OBJECT (md->current_message), + "finalize", destroy_part, part); + + write_hr (md); + format_mime_part (part, md); + return sig_end; } static char * -try_uudecoding (char *start, CamelMimePart *mime_part, MailDisplay *md) +try_uudecoding (char *start, CamelMimePart *mime_part, + guint offset, MailDisplay *md) { int mode, len, state = 0; char *filename, *estart, *p, *out, uulen = 0; @@ -1613,21 +1453,23 @@ try_uudecoding (char *start, CamelMimePart *mime_part, MailDisplay *md) out = g_malloc (p - estart); len = uudecode_step (estart, p - estart, out, &state, &save, &uulen); - part = fake_mime_part_from_data (out, len, "application/octet-stream"); + part = fake_mime_part_from_data (out, len, "application/octet-stream", + offset, md); g_free (out); camel_mime_part_set_filename (part, filename); g_free (filename); camel_object_hook_event (CAMEL_OBJECT (md->current_message), "finalize", destroy_part, part); - mail_html_write (md->html, md->stream, "
"); + write_hr (md); format_mime_part (part, md); return p + 4; } static char * -try_inline_binhex (char *start, CamelMimePart *mime_part, MailDisplay *md) +try_inline_binhex (char *start, CamelMimePart *mime_part, + guint offset, MailDisplay *md) { char *p; CamelMimePart *part; @@ -1644,11 +1486,12 @@ try_inline_binhex (char *start, CamelMimePart *mime_part, MailDisplay *md) p += 2; part = fake_mime_part_from_data (start, p - start, - "application/mac-binhex40"); + "application/mac-binhex40", + offset, md); camel_object_hook_event (CAMEL_OBJECT (md->current_message), "finalize", destroy_part, part); - mail_html_write (md->html, md->stream, "
"); + write_hr (md); format_mime_part (part, md); return p; @@ -1855,9 +1698,7 @@ handle_multipart_mixed (CamelMimePart *part, const char *mime_type, nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts; i++) { if (i != 0 && output) - mail_html_write (md->html, md->stream, - "
" - "
\n"); + write_hr (md); part = camel_multipart_get_part (mp, i); @@ -1906,52 +1747,105 @@ static gboolean handle_multipart_signed (CamelMimePart *part, const char *mime_type, MailDisplay *md) { + CamelMimePart *subpart; CamelDataWrapper *wrapper; CamelMultipart *mp; - CamelException *ex; gboolean output = FALSE; - CamelCipherValidity *valid; int nparts, i; - + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part)); g_return_val_if_fail (CAMEL_IS_MULTIPART (wrapper), FALSE); - ex = camel_exception_new (); - - if (camel_pgp_mime_is_rfc2015_signed (part)) { - valid = mail_crypto_pgp_mime_part_verify (part, ex); - } else { - camel_exception_free (ex); - return handle_multipart_mixed (part, mime_type, md); - } - - if (!valid) { - camel_exception_free (ex); - return handle_multipart_mixed (part, mime_type, md); - } - - camel_exception_free (ex); - - /* now display all the subparts (there should be only 1) *except* the signature (last part) */ + /* Display all the subparts (there should be only 1) + * except the signature (last part). + */ mp = CAMEL_MULTIPART (wrapper); nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts - 1; i++) { if (i != 0 && output) - mail_html_write (md->html, md->stream, - "
" - "
\n"); + write_hr (md); - part = camel_multipart_get_part (mp, i); + subpart = camel_multipart_get_part (mp, i); - output = format_mime_part (part, md); + output = format_mime_part (subpart, md); + } + + subpart = camel_multipart_get_part (mp, i); + mail_part_set_default_displayed_inline (subpart, md, FALSE); + + if (!mail_part_is_displayed_inline (subpart, md)) { + char *url; + + /* Write out the click-for-info object */ + url = g_strdup_printf ("signature:%p/%lu", subpart, + (unsigned long)time (NULL)); + add_url ("part_urls", url, subpart, md); + mail_html_write (md->html, md->stream, + "
" + "" + "" + "" + "
", url); + + mail_html_write (md->html, md->stream, "%s", + U_("This message is digitally signed. " + "Click the lock icon for more information.")); + + mail_html_write (md->html, md->stream, + "
" + "
\n"); + } else { + CamelCipherValidity *valid = NULL; + CamelException ex; + const char *message = NULL; + gboolean good = FALSE; + + /* Write out the verification results */ + + camel_exception_init (&ex); + if (camel_pgp_mime_is_rfc2015_signed (part)) { + valid = mail_crypto_pgp_mime_part_verify (part, &ex); + if (!valid) { + message = camel_exception_get_description (&ex); + } else { + good = camel_cipher_validity_get_valid (valid); + message = camel_cipher_validity_get_description (valid); + } + } else + message = U_("Evolution does not recognize this type of signed message."); + + if (good) { + mail_html_write (md->html, md->stream, + "" + "" + "
%s

", + get_url_for_icon (EVOLUTION_ICONSDIR "/pgp-signature-ok.png", md), + U_("This message is digitally signed and " + "has been found to be authentic.")); + } else { + mail_html_write (md->html, md->stream, + "" + "" + "
%s

", + get_url_for_icon (EVOLUTION_ICONSDIR "/pgp-signature-bad.png", md), + U_("This message is digitally signed but can " + "not be proven to be authentic.")); + } + + if (message) { + mail_html_write (md->html, md->stream, + "", + good ? "" : "color=red"); + mail_text_write (md->html, md->stream, "%s", message); + mail_html_write (md->html, md->stream, ""); + } + + mail_html_write (md->html, md->stream, "
"); + camel_exception_clear (&ex); + camel_cipher_validity_free (valid); } - - mail_write_authenticity (md, valid); - camel_cipher_validity_free (valid); - - mail_html_write (md->html, md->stream, "
"); return TRUE; } -- cgit v1.2.3