From dab1c82a2155a56ae2444108b4182bb7c19d4889 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 30 Jan 2004 03:10:14 +0000 Subject: ** See bug #53558 (plus other fixes/cleanups) 2004-01-30 Not Zed ** See bug #53558 (plus other fixes/cleanups) * em-format.c (emf_format_secure): default implementation, handle output of inner part, but dont output any sign/encrypt info. (emf_multipart_signed, emf_multipart_encrypted): replaced with implementations from em-format-html.c, which now call em_format_format_secure to output guts. (emf_class_init): hook-up virtual method format_secure. * em-format.[ch]: add a virtual method for outputing secured parts. Moved all validity stuff from em-format-html.[ch] to here. * mail-component.c (impl_createControls): set the session interactive too. * em-format-html-display.c: make smime stuff dependent on HAVE_NSS. (efhd_multipart_signed, efhd_application_xpkcs7mime): removed, now handled by root class. (efhd_output_secure): renamed to efhd_format_secure, and use EMFormat::format_secure to kick off. (efhd_class_init): setup format_secure virtual method. * em-format-html.c (efh_multipart_encrypted): We need to handle this here so we can properly keep track of the ciphervalidity stuff. Also do it directly using the context, not multipartencrypted part. (efh_multipart_signed): with unsupported signature format, format as multipart/mixed, not as an attachment. (efh_multipart_signed): make the smime stuff optional. (efh_multipart_signed, efh_multipart_encrypted): Moved to em-format.c. (efh_application_xpkcs7mime): moved to em-format.c (efh_output_secure): renamed to efh_format_secure, linked into virtual method. call parent class to do the validation foo then output the info if needed. (efh_format_message): fixed access to validity stuff to parent object. (efh_class_init): hook up format_secure virtual method. (*): removed some now-unused headers. svn path=/trunk/; revision=24531 --- mail/ChangeLog | 43 ++++++++++ mail/em-format-html-display.c | 112 +++----------------------- mail/em-format-html.c | 131 +++++------------------------- mail/em-format-html.h | 3 - mail/em-format.c | 183 ++++++++++++++++++++++++++---------------- mail/em-format.h | 8 ++ mail/mail-component.c | 3 +- 7 files changed, 198 insertions(+), 285 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index b47b2fa701..96c8725ab4 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,46 @@ +2004-01-30 Not Zed + + ** See bug #53558 (plus other fixes/cleanups) + + * em-format.c (emf_format_secure): default implementation, handle + output of inner part, but dont output any sign/encrypt info. + (emf_multipart_signed, emf_multipart_encrypted): replaced with + implementations from em-format-html.c, which now call + em_format_format_secure to output guts. + (emf_class_init): hook-up virtual method format_secure. + + * em-format.[ch]: add a virtual method for outputing secured + parts. Moved all validity stuff from em-format-html.[ch] to here. + + * mail-component.c (impl_createControls): set the session + interactive too. + + * em-format-html-display.c: make smime stuff dependent on + HAVE_NSS. + (efhd_multipart_signed, efhd_application_xpkcs7mime): removed, now + handled by root class. + (efhd_output_secure): renamed to efhd_format_secure, and use + EMFormat::format_secure to kick off. + (efhd_class_init): setup format_secure virtual method. + + * em-format-html.c (efh_multipart_encrypted): We need to handle + this here so we can properly keep track of the ciphervalidity + stuff. Also do it directly using the context, not + multipartencrypted part. + (efh_multipart_signed): with unsupported signature format, format + as multipart/mixed, not as an attachment. + (efh_multipart_signed): make the smime stuff optional. + (efh_multipart_signed, efh_multipart_encrypted): Moved to + em-format.c. + (efh_application_xpkcs7mime): moved to em-format.c + (efh_output_secure): renamed to efh_format_secure, linked into + virtual method. call parent class to do the validation foo then + output the info if needed. + (efh_format_message): fixed access to validity stuff to parent + object. + (efh_class_init): hook up format_secure virtual method. + (*): removed some now-unused headers. + 2004-01-29 Nicel KM * mail-component.c: removed CAMEL_PROVIDER_IS_EXTERNAL check diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index 64fefde3fe..04a741fc79 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -64,10 +64,9 @@ #include #include #include -#include #include #include -#include +#include /* should this be in e-util rather than gal? */ #include @@ -76,8 +75,7 @@ #include #include -#if defined(HAVE_NSS) -#include +#ifdef HAVE_NSS #include "certificate-viewer.h" #include "e-cert-db.h" #endif @@ -137,6 +135,7 @@ static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *tx static void efhd_format_message(EMFormat *, CamelStream *, CamelMedium *); static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *); static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); +static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); static void efhd_complete(EMFormat *); static gboolean efhd_bonobo_object(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject); @@ -156,6 +155,7 @@ static guint efhd_signals[EFHD_LAST_SIGNAL] = { 0 }; /* EMFormatHandler's for bonobo objects */ static GHashTable *efhd_bonobo_handlers; static EMFormatHTMLClass *efhd_parent; +static EMFormatClass *efhd_format_class; static void efhd_gtkhtml_realise(GtkHTML *html, EMFormatHTMLDisplay *efhd) @@ -275,6 +275,7 @@ efhd_class_init(GObjectClass *klass) ((EMFormatClass *)klass)->format_message = efhd_format_message; ((EMFormatClass *)klass)->format_source = efhd_format_source; ((EMFormatClass *)klass)->format_attachment = efhd_format_attachment; + ((EMFormatClass *)klass)->format_secure = efhd_format_secure; ((EMFormatClass *)klass)->complete = efhd_complete; klass->finalize = efhd_finalise; @@ -327,6 +328,7 @@ em_format_html_display_get_type(void) (GInstanceInitFunc)efhd_init }; efhd_parent = g_type_class_ref(em_format_html_get_type()); + efhd_format_class = g_type_class_ref(em_format_get_type()); type = g_type_register_static(em_format_html_get_type(), "EMFormatHTMLDisplay", &info, 0); efhd_bonobo_handlers = g_hash_table_new(g_str_hash, g_str_equal); @@ -675,7 +677,7 @@ efhd_xpkcs7mime_info_response(GtkWidget *w, guint button, struct _smime_pobject po->widget = NULL; } -#if defined(HAVE_NSS) +#ifdef HAVE_NSS static void efhd_xpkcs7mime_viewcert_clicked(GtkWidget *button, struct _smime_pobject *po) { @@ -839,29 +841,12 @@ efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje } static void -efhd_output_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) +efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) { - CamelCipherValidity *save = ((EMFormatHTML *)emf)->valid_parent; - int len; - - /* Note: this same logic is in efh_output_secure */ - if (((EMFormatHTML *)emf)->valid == NULL) { - ((EMFormatHTML *)emf)->valid = valid; - } else { - e_dlist_addtail(&((EMFormatHTML *)emf)->valid_parent->children, (EDListNode *)valid); - camel_cipher_validity_envelope(((EMFormatHTML *)emf)->valid_parent, valid); - } + /* Note: We call EMFormatClass directly, not EMFormatHTML, our parent */ + efhd_format_class->format_secure(emf, stream, part, valid); - ((EMFormatHTML *)emf)->valid_parent = valid; - - len = emf->part_id->len; - g_string_append_printf(emf->part_id, ".signed"); - em_format_part(emf, stream, part); - g_string_truncate(emf->part_id, len); - - ((EMFormatHTML *)emf)->valid_parent = save; - - if (((EMFormatHTML *)emf)->valid == valid + if (emf->valid == valid && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE || valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) { char *classid; @@ -888,84 +873,9 @@ efhd_output_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Came } } -static void -efhd_application_xpkcs7mime(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) -{ - CamelCipherContext *context; - CamelException *ex; - extern CamelSession *session; - CamelMimePart *opart; - CamelCipherValidity *valid; - - ex = camel_exception_new(); - - context = camel_smime_context_new(session); - - opart = camel_mime_part_new(); - valid = camel_cipher_decrypt(context, part, opart, ex); - if (valid == NULL) { - 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 { - efhd_output_secure(emf, stream, opart, valid); - } - - camel_object_unref(opart); - camel_object_unref(context); - camel_exception_free(ex); -} - -/* ********************************************************************** */ - -static void -efhd_multipart_signed (EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) -{ - CamelMultipartSigned *mps; - CamelMimePart *cpart; - CamelCipherContext *cipher = NULL; - - mps = (CamelMultipartSigned *)camel_medium_get_content_object((CamelMedium *)part); - if (!CAMEL_IS_MULTIPART_SIGNED(mps) - || (cpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) { - em_format_format_source(emf, stream, part); - return; - } - - /* FIXME: Should be done via a plugin interface */ - /* FIXME: duplicated in em-format-html.c */ - if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0 - || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) - cipher = camel_smime_context_new(emf->session); - else if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) - cipher = camel_gpg_context_new(emf->session); - - if (cipher == NULL) { - em_format_format_error(emf, stream, _("Unsupported signature format")); - em_format_part_as(emf, stream, part, NULL); - } else { - CamelException *ex = camel_exception_new(); - CamelCipherValidity *valid; - - valid = camel_cipher_verify(cipher, part, ex); - if (valid == NULL) { - em_format_format_error(emf, stream, ex->desc?ex->desc:_("Unknown error verifying signature")); - em_format_part_as(emf, stream, part, NULL); - } else { - efhd_output_secure(emf, stream, cpart, valid); - } - - camel_exception_free(ex); - camel_object_unref(cipher); - } -} - /* ********************************************************************** */ static EMFormatHandler type_builtin_table[] = { - { "application/x-pkcs7-mime", (EMFormatFunc)efhd_application_xpkcs7mime }, - { "application/pkcs7-mime", (EMFormatFunc)efhd_application_xpkcs7mime }, - - { "multipart/signed", (EMFormatFunc)efhd_multipart_signed }, }; static void diff --git a/mail/em-format-html.c b/mail/em-format-html.c index a619040ef0..2a99a7085b 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -50,10 +50,8 @@ #include #include #include +#include #include -#include -#include -#include #include #include #include @@ -98,6 +96,7 @@ static void efh_format_error(EMFormat *emf, CamelStream *stream, const char *txt static void efh_format_message(EMFormat *, CamelStream *, CamelMedium *); static void efh_format_source(EMFormat *, CamelStream *, CamelMimePart *); static void efh_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); +static void efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); static gboolean efh_busy(EMFormat *); static void efh_builtin_init(EMFormatHTMLClass *efhc); @@ -176,7 +175,6 @@ efh_finalise(GObject *o) /* FIXME: check for leaked stuff */ em_format_html_clear_pobject(efh); - camel_cipher_validity_free(efh->valid); efh_gtkhtml_destroy(efh->html, efh); @@ -202,6 +200,7 @@ efh_class_init(GObjectClass *klass) ((EMFormatClass *)klass)->format_message = efh_format_message; ((EMFormatClass *)klass)->format_source = efh_format_source; ((EMFormatClass *)klass)->format_attachment = efh_format_attachment; + ((EMFormatClass *)klass)->format_secure = efh_format_secure; ((EMFormatClass *)klass)->busy = efh_busy; klass->finalize = efh_finalise; @@ -578,29 +577,15 @@ static const struct { /* TODO: this could probably be virtual on em-format-html then we only need one version of each type handler */ static void -efh_output_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) +efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) { - CamelCipherValidity *save = ((EMFormatHTML *)emf)->valid_parent; - int len; + efh_parent->format_secure(emf, stream, part, valid); - /* Note: this same logic is in efhd_output_secure */ - if (((EMFormatHTML *)emf)->valid == NULL) { - ((EMFormatHTML *)emf)->valid = valid; - } else { - e_dlist_addtail(&((EMFormatHTML *)emf)->valid_parent->children, (EDListNode *)valid); - camel_cipher_validity_envelope(((EMFormatHTML *)emf)->valid_parent, valid); - } - - ((EMFormatHTML *)emf)->valid_parent = valid; - - len = emf->part_id->len; - g_string_append_printf(emf->part_id, ".signed"); - em_format_part(emf, stream, part); - g_string_truncate(emf->part_id, len); - - ((EMFormatHTML *)emf)->valid_parent = save; - - if (((EMFormatHTML *)emf)->valid == valid + /* To explain, if the validity is the same, then we are the + base validity and now have a combined sign/encrypt validity + we can display. Primarily a new verification context is + created when we have an embeded message. */ + if (emf->valid == valid && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE || valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) { char *classid; @@ -631,33 +616,6 @@ efh_output_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Camel } } -static void -efh_application_xpkcs7mime(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) -{ - CamelCipherContext *context; - CamelException *ex; - extern CamelSession *session; - CamelMimePart *opart; - CamelCipherValidity *valid; - - ex = camel_exception_new(); - - context = camel_smime_context_new(session); - - opart = camel_mime_part_new(); - valid = camel_cipher_decrypt(context, part, opart, ex); - if (valid == NULL) { - 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 { - efh_output_secure(emf, stream, opart, valid); - } - - camel_object_unref(opart); - camel_object_unref(context); - camel_exception_free(ex); -} - static void efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) { @@ -1058,49 +1016,6 @@ efh_multipart_related(EMFormat *emf, CamelStream *stream, CamelMimePart *part, c } } -static void -efh_multipart_signed(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) -{ - CamelMimePart *cpart; - CamelMultipartSigned *mps; - CamelCipherContext *cipher = NULL; - - mps = (CamelMultipartSigned *)camel_medium_get_content_object((CamelMedium *)part); - if (!CAMEL_IS_MULTIPART_SIGNED(mps) - || (cpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) { - em_format_format_error(emf, stream, _("Could not parse MIME message. Displaying as source.")); - em_format_format_source(emf, stream, part); - return; - } - - /* FIXME: Should be done via a plugin interface */ - /* FIXME: duplicated in em-format-html-display.c */ - if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0 - || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) - cipher = camel_smime_context_new(emf->session); - else if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) - cipher = camel_gpg_context_new(emf->session); - - if (cipher == NULL) { - em_format_format_error(emf, stream, _("Unsupported signature format")); - em_format_part_as(emf, stream, part, NULL); - } else { - CamelException *ex = camel_exception_new(); - CamelCipherValidity *valid; - - valid = camel_cipher_verify(cipher, part, ex); - if (valid == NULL) { - em_format_format_error(emf, stream, ex->desc?ex->desc:_("Unknown error verifying signature")); - em_format_part_as(emf, stream, part, NULL); - } else { - efh_output_secure(emf, stream, cpart, valid); - } - - camel_exception_free(ex); - camel_object_unref(cipher); - } -} - static void efh_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri) { @@ -1124,9 +1039,6 @@ efh_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatH } static EMFormatHandler type_builtin_table[] = { - { "application/x-pkcs7-mime", (EMFormatFunc)efh_application_xpkcs7mime }, - { "application/pkcs7-mime", (EMFormatFunc)efh_application_xpkcs7mime }, - { "image/gif", (EMFormatFunc)efh_image }, { "image/jpeg", (EMFormatFunc)efh_image }, { "image/png", (EMFormatFunc)efh_image }, @@ -1148,7 +1060,6 @@ static EMFormatHandler type_builtin_table[] = { { "text/richtext", (EMFormatFunc)efh_text_enriched }, { "text/*", (EMFormatFunc)efh_text_plain }, { "message/external-body", (EMFormatFunc)efh_message_external }, - { "multipart/signed", (EMFormatFunc)efh_multipart_signed }, { "multipart/related", (EMFormatFunc)efh_multipart_related }, /* This is where one adds those busted, non-registered types, @@ -1318,10 +1229,11 @@ efh_format_timeout(struct _format_msg *m) efh_parent->format_clone((EMFormat *)efh, m->folder, m->uid, m->message, m->format_source); em_format_html_clear_pobject(m->format); - if (efh->valid) { - camel_cipher_validity_free(efh->valid); - efh->valid = NULL; - efh->valid_parent = NULL; + /* FIXME: method off EMFormat? */ + if (((EMFormat *)efh)->valid) { + camel_cipher_validity_free(((EMFormat *)efh)->valid); + ((EMFormat *)efh)->valid = NULL; + ((EMFormat *)efh)->valid_parent = NULL; } if (m->message == NULL) { @@ -1677,10 +1589,11 @@ em_format_html_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMediu static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMedium *part) { #define efh ((EMFormatHTML *)emf) - CamelCipherValidity *save = efh->valid, *save_parent = efh->valid_parent; + /* TODO: make this validity stuff a method */ + CamelCipherValidity *save = emf->valid, *save_parent = emf->valid_parent; - efh->valid = NULL; - efh->valid_parent = NULL; + emf->valid = NULL; + emf->valid_parent = NULL; if (emf->message != (CamelMimeMessage *)part) camel_stream_printf(stream, "
\n"); @@ -1694,10 +1607,10 @@ static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMedium * if (emf->message != (CamelMimeMessage *)part) camel_stream_printf(stream, "
\n"); - camel_cipher_validity_free(efh->valid); + camel_cipher_validity_free(emf->valid); - efh->valid = save; - efh->valid_parent = save_parent; + emf->valid = save; + emf->valid_parent = save_parent; #undef efh } diff --git a/mail/em-format-html.h b/mail/em-format-html.h index 4a981cd792..cd1365e620 100644 --- a/mail/em-format-html.h +++ b/mail/em-format-html.h @@ -106,9 +106,6 @@ struct _EMFormatHTML { EDList pending_object_list; - struct _CamelCipherValidity *valid; - struct _CamelCipherValidity *valid_parent; - GSList *headers; guint32 text_html_flags; /* default flags for text to html conversion */ diff --git a/mail/em-format.c b/mail/em-format.c index 7eb8794827..d0b5786492 100644 --- a/mail/em-format.c +++ b/mail/em-format.c @@ -60,6 +60,7 @@ static const char *emf_snoop_part(CamelMimePart *part); static const EMFormatHandler *emf_find_handler(EMFormat *emf, const char *mime_type); static void emf_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource); static void emf_format_prefix(EMFormat *emf, CamelStream *stream); +static void emf_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); static gboolean emf_busy(EMFormat *emf); enum { @@ -93,6 +94,7 @@ emf_finalise(GObject *o) g_hash_table_destroy(emf->inline_table); em_format_clear_headers(emf); + camel_cipher_validity_free(emf->valid); g_free(emf->charset); g_string_free(emf->part_id, TRUE); @@ -118,6 +120,7 @@ emf_class_init(GObjectClass *klass) ((EMFormatClass *)klass)->find_handler = emf_find_handler; ((EMFormatClass *)klass)->format_clone = emf_format_clone; ((EMFormatClass *)klass)->format_prefix = emf_format_prefix; + ((EMFormatClass *)klass)->format_secure = emf_format_secure; ((EMFormatClass *)klass)->busy = emf_busy; emf_signals[EMF_COMPLETE] = @@ -578,6 +581,33 @@ emf_format_prefix(EMFormat *emf, CamelStream *stream) /* NOOP */ } +static void +emf_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) +{ + CamelCipherValidity *save = emf->valid_parent; + int len; + + /* Note that this also requires support from higher up in the class chain + - validity needs to be cleared when you start output + - also needs to be cleared (but saved) whenever you start a new message. */ + + if (emf->valid == NULL) { + emf->valid = valid; + } else { + e_dlist_addtail(&emf->valid_parent->children, (EDListNode *)valid); + camel_cipher_validity_envelope(emf->valid_parent, valid); + } + + emf->valid_parent = valid; + + len = emf->part_id->len; + g_string_append_printf(emf->part_id, ".secured"); + em_format_part(emf, stream, part); + g_string_truncate(emf->part_id, len); + + emf->valid_parent = save; +} + static gboolean emf_busy(EMFormat *emf) { @@ -993,6 +1023,35 @@ emf_snoop_part(CamelMimePart *part) see bug #11778 for some discussion */ } +#ifdef HAVE_NSS +static void +emf_application_xpkcs7mime(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +{ + CamelCipherContext *context; + CamelException *ex; + extern CamelSession *session; + CamelMimePart *opart; + CamelCipherValidity *valid; + + ex = camel_exception_new(); + + context = camel_smime_context_new(session); + + opart = camel_mime_part_new(); + valid = camel_cipher_decrypt(context, part, opart, ex); + if (valid == NULL) { + 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 { + em_format_format_secure(emf, stream, opart, valid); + } + + camel_object_unref(opart); + camel_object_unref(context); + camel_exception_free(ex); +} +#endif + /* RFC 1740 */ static void emf_multipart_appledouble(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) @@ -1081,42 +1140,34 @@ emf_multipart_alternative(EMFormat *emf, CamelStream *stream, CamelMimePart *par static void emf_multipart_encrypted(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) { - CamelMultipartEncrypted *mpe; - CamelMimePart *mime_part; - CamelCipherContext *cipher; - CamelException ex; + CamelCipherContext *context; + CamelException *ex; const char *protocol; - int len; + CamelMimePart *opart; + CamelCipherValidity *valid; /* Currently we only handle RFC2015-style PGP encryption. */ protocol = camel_content_type_param (((CamelDataWrapper *) part)->mime_type, "protocol"); - if (!protocol || strcmp (protocol, "application/pgp-encrypted") != 0) - return emf_multipart_mixed(emf, stream, part, info); - - mpe = (CamelMultipartEncrypted *)camel_medium_get_content_object((CamelMedium *)part); - - if (!CAMEL_IS_MULTIPART_ENCRYPTED(mpe)) { - em_format_format_source(emf, stream, part); + if (!protocol || g_ascii_strcasecmp (protocol, "application/pgp-encrypted") != 0) { + em_format_format_error(emf, stream, _("Unsupported encryption type for multipart/encrypted")); + em_format_part_as(emf, stream, part, "multipart/mixed"); return; } - camel_exception_init (&ex); - cipher = camel_gpg_context_new(emf->session); - mime_part = camel_multipart_encrypted_decrypt(mpe, cipher, &ex); - camel_object_unref(cipher); - - if (camel_exception_is_set(&ex)) { - /* FIXME: error handler */ - em_format_format_error(emf, stream, camel_exception_get_description(&ex)); - camel_exception_clear(&ex); - return; + ex = camel_exception_new(); + context = camel_gpg_context_new(emf->session); + opart = camel_mime_part_new(); + valid = camel_cipher_decrypt(context, part, opart, ex); + if (valid == NULL) { + 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 { + em_format_format_secure(emf, stream, opart, valid); } - len = emf->part_id->len; - g_string_append_printf(emf->part_id, ".encrypted"); - em_format_part(emf, stream, mime_part); - g_string_truncate(emf->part_id, len); - camel_object_unref(mime_part); + camel_object_unref(opart); + camel_object_unref(context); + camel_exception_free(ex); } static void @@ -1232,69 +1283,50 @@ emf_multipart_related(EMFormat *emf, CamelStream *stream, CamelMimePart *part, c } } -/* this is only a fallback implementation, implementations should override */ static void emf_multipart_signed(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) { CamelMimePart *cpart; CamelMultipartSigned *mps; - CamelCipherValidity *valid = NULL; - CamelException ex; - const char *message = NULL; - gboolean good = FALSE; - int len; + CamelCipherContext *cipher = NULL; mps = (CamelMultipartSigned *)camel_medium_get_content_object((CamelMedium *)part); if (!CAMEL_IS_MULTIPART_SIGNED(mps) || (cpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) { + em_format_format_error(emf, stream, _("Could not parse MIME message. Displaying as source.")); em_format_format_source(emf, stream, part); return; } - len = emf->part_id->len; - g_string_append_printf(emf->part_id, ".signed"); - em_format_part(emf, stream, cpart); - g_string_truncate(emf->part_id, len); - - /* FIXME: This sequence is also copied in em-format-html.c */ + /* FIXME: Should be done via a plugin interface */ + /* FIXME: duplicated in em-format-html-display.c */ +#ifdef HAVE_NSS + if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0 + || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) + cipher = camel_smime_context_new(emf->session); + else +#endif + if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) + cipher = camel_gpg_context_new(emf->session); - camel_exception_init(&ex); - if (emf->session == NULL) { - message = _("Session not initialised"); + if (cipher == NULL) { + em_format_format_error(emf, stream, _("Unsupported signature format")); + em_format_part_as(emf, stream, part, "multipart/mixed"); } else { - CamelCipherContext *cipher = NULL; + CamelException *ex = camel_exception_new(); + CamelCipherValidity *valid; - /* FIXME: Should be done via a plugin interface */ - if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0 - || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) - cipher = camel_smime_context_new(emf->session); - else if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) - cipher = camel_gpg_context_new(emf->session); - - if (cipher == NULL) { - message = _("Unsupported signature format"); + valid = camel_cipher_verify(cipher, part, ex); + if (valid == NULL) { + em_format_format_error(emf, stream, ex->desc?ex->desc:_("Unknown error verifying signature")); + em_format_part_as(emf, stream, part, NULL); } else { - valid = camel_cipher_verify(cipher, part, &ex); - camel_object_unref(cipher); - if (valid) { - good = camel_cipher_validity_get_valid(valid); - message = camel_cipher_validity_get_description(valid); - } else { - message = camel_exception_get_description(&ex); - } + em_format_format_secure(emf, stream, cpart, valid); } + + camel_exception_free(ex); + camel_object_unref(cipher); } - - if (good) - em_format_format_error(emf, stream, _("This message is digitally signed and has been found to be authentic.")); - else - em_format_format_error(emf, stream, _("This message is digitally signed but can not be proven to be authentic.")); - - if (message) - em_format_format_error(emf, stream, message); - - camel_exception_clear(&ex); - camel_cipher_validity_free(valid); } static void @@ -1315,6 +1347,9 @@ emf_message_rfc822(EMFormat *emf, CamelStream *stream, CamelMimePart *part, cons } static EMFormatHandler type_builtin_table[] = { +#ifdef HAVE_NSS + { "application/x-pkcs7-mime", (EMFormatFunc)emf_application_xpkcs7mime }, +#endif { "multipart/alternative", emf_multipart_alternative }, { "multipart/appledouble", emf_multipart_appledouble }, { "multipart/encrypted", emf_multipart_encrypted }, @@ -1325,6 +1360,12 @@ static EMFormatHandler type_builtin_table[] = { { "message/rfc822", emf_message_rfc822 }, { "message/news", emf_message_rfc822 }, { "message/*", emf_message_rfc822 }, + + /* Insert brokenly-named parts here */ +#ifdef HAVE_NSS + { "application/pkcs7-mime", (EMFormatFunc)emf_application_xpkcs7mime }, +#endif + }; static void diff --git a/mail/em-format.h b/mail/em-format.h index a5fd08f55c..323c28865a 100644 --- a/mail/em-format.h +++ b/mail/em-format.h @@ -37,6 +37,7 @@ struct _CamelSession; struct _CamelURL; struct _CamelDataWrapper; struct _CamelMimeMessage; +struct _CamelCipherValidity; typedef struct _EMFormat EMFormat; typedef struct _EMFormatClass EMFormatClass; @@ -114,6 +115,10 @@ struct _EMFormat { const char *snoop_mime_type; /* if we snooped an application/octet-stream type, what we snooped */ + /* for validity enveloping */ + struct _CamelCipherValidity *valid; + struct _CamelCipherValidity *valid_parent; + /* for forcing inlining */ GHashTable *inline_table; @@ -153,6 +158,8 @@ struct _EMFormatClass { void (*format_message)(EMFormat *, struct _CamelStream *, struct _CamelMedium *); /* use for unparsable content */ void (*format_source)(EMFormat *, struct _CamelStream *, struct _CamelMimePart *); + /* for outputing secure(d) content */ + void (*format_secure)(EMFormat *, struct _CamelStream *, struct _CamelMimePart *, struct _CamelCipherValidity *); /* returns true if the formatter is still busy with pending stuff */ gboolean (*busy)(EMFormat *); @@ -212,6 +219,7 @@ void em_format_pull_level(EMFormat *emf); #define em_format_format_attachment(emf, stream, msg, type, info) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_attachment((emf), (stream), (msg), (type), (info)) #define em_format_format_message(emf, stream, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_message((emf), (stream), (msg)) #define em_format_format_source(emf, stream, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_source((emf), (stream), (msg)) +#define em_format_format_secure(emf, stream, msg, valid) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_secure((emf), (stream), (msg), (valid)) #define em_format_busy(emf) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->busy((emf)) diff --git a/mail/mail-component.c b/mail/mail-component.c index bda9d9801d..400a493008 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -403,8 +403,9 @@ impl_createControls (PortableServer_Servant servant, GtkWidget *view_widget; GtkWidget *statusbar_widget; + mail_session_set_interactive(TRUE); mc_startup(mail_component); - + view_widget = em_folder_browser_new (); tree_widget = (GtkWidget *) em_folder_tree_new_with_model (priv->model); em_folder_tree_enable_drag_and_drop ((EMFolderTree *) tree_widget); -- cgit v1.2.3