From a9edef00dd65010d4e08517d861ea55992bd863d Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Fri, 1 Jul 2005 03:29:23 +0000 Subject: implement extraction of inline signed/encrypted pgp parts and package them 2005-06-24 Matt Brown * em-inline-filter.c: implement extraction of inline signed/encrypted pgp parts and package them into x-inlinepgp-signed/x-inline-pgp-encrypted parts. * em-format-html.c: Formatters to verify/decrypt and then display the parts generated by the inline filter. svn path=/trunk/; revision=29603 --- mail/ChangeLog | 8 ++++ mail/em-format-html.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++-- mail/em-format.c | 2 + mail/em-inline-filter.c | 30 ++++++++---- 4 files changed, 152 insertions(+), 13 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index c5cbc39e5e..d38c8202c6 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,11 @@ +2005-06-24 Matt Brown + + * em-inline-filter.c: implement extraction of inline signed/encrypted pgp + parts and package them into x-inlinepgp-signed/x-inline-pgp-encrypted + parts. + * em-format-html.c: Formatters to verify/decrypt and then display the + parts generated by the inline filter. + 2005-06-25 Not Zed ** See bug #307398 diff --git a/mail/em-format-html.c b/mail/em-format-html.c index ad26fbacad..95190101ce 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -48,6 +48,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -658,6 +661,117 @@ efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Camel } } +static void +efh_inlinepgp_signed(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *ipart, EMFormatHandler *info) +{ + + CamelCipherContext *cipher; + CamelCipherValidity *valid; + CamelException *ex; + CamelMimePart *opart=NULL; + CamelContentType *type; + CamelStreamFilter *filtered_stream; + CamelStream *ostream; + CamelDataWrapper *dw; + CamelMimeFilterPgp *pgp_filter; + + /* Check we're passed valid input */ + type = camel_mime_part_get_content_type(ipart); + if (!camel_content_type_is(type, "application", "x-inlinepgp-signed")) { + em_format_format_error((EMFormat *)efh, stream, + "Invalid mime type passed to inline PGP format"); + return; + } + + ex = camel_exception_new(); + cipher = camel_gpg_context_new (((EMFormat *)efh)->session); + /* Verify the signature of the message */ + valid = camel_cipher_verify(cipher, ipart, ex); + if (!valid) { + /* Display an error */ + em_format_format_error((EMFormat *)efh, stream, ex->desc ? ex->desc : + _("Unknown error verifying signed messaage")); + camel_exception_free(ex); + camel_object_unref(cipher); + return; + } + + /* Setup output stream */ + ostream = camel_stream_mem_new(); + filtered_stream = camel_stream_filter_new_with_stream(ostream); + + /* Add PGP header / footer filter */ + pgp_filter = (CamelMimeFilterPgp *)camel_mime_filter_pgp_new(); + camel_stream_filter_add(filtered_stream, (CamelMimeFilter *)pgp_filter); + camel_object_unref(pgp_filter); + + /* Pass through the filters that have been setup */ + dw = camel_medium_get_content_object((CamelMedium *)ipart); + camel_data_wrapper_decode_to_stream(dw, (CamelStream *)filtered_stream); + camel_stream_flush((CamelStream *)filtered_stream); + camel_object_unref(filtered_stream); + + /* Extract new part and display it as text/plain */ + dw = camel_data_wrapper_new(); + camel_data_wrapper_construct_from_stream(dw, ostream); + camel_data_wrapper_set_mime_type(dw, "text/plain"); + opart = camel_mime_part_new(); + camel_medium_set_content_object((CamelMedium *)opart, dw); + camel_mime_part_set_content_type(opart, "text/plain"); + + /* Pass it off to the real formatter */ + em_format_format_secure((EMFormat *)efh, stream, opart, valid); + + /* Clean Up */ + camel_object_unref(dw); + camel_object_unref(opart); + camel_object_unref(ostream); + camel_object_unref(cipher); + camel_exception_free(ex); +} + +static void +efh_inlinepgp_encrypted(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *ipart, EMFormatHandler *info) +{ + CamelCipherContext *cipher; + CamelCipherValidity *valid; + CamelException *ex; + CamelMimePart *opart; + CamelContentType *type; + + /* Check we're passed valid input */ + type = camel_mime_part_get_content_type(ipart); + if (!camel_content_type_is(type, "application", "x-inlinepgp-encrypted")) { + em_format_format_error((EMFormat *)efh, stream, + "Invalid mime type passed to inline PGP format encrypted"); + return; + } + + cipher = camel_gpg_context_new (((EMFormat *)efh)->session); + ex = camel_exception_new(); + opart = camel_mime_part_new(); + /* Decrypt the message */ + valid = camel_cipher_decrypt (cipher, ipart, opart, ex); + if (!valid) { + /* Display an error */ + em_format_format_error((EMFormat *)efh, stream, ex->desc ? ex->desc : + _("Unknown error decrypting messaage")); + camel_exception_free(ex); + camel_object_unref(cipher); + camel_object_unref(opart); + return; + } + + /* Pass it off to the real formatter */ + em_format_format_secure((EMFormat *)efh, stream, opart, valid); + + /* Clean Up */ + camel_object_unref(opart); + camel_object_unref (cipher); + camel_exception_free (ex); +} + + static void efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) { @@ -671,10 +785,6 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo int i, count, len; struct _EMFormatHTMLCache *efhc; - camel_stream_printf (stream, - "
\n", - efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); - flags = efh->text_html_flags; dw = camel_medium_get_content_object((CamelMedium *)part); @@ -742,10 +852,14 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo type = camel_mime_part_get_content_type(newpart); if (camel_content_type_is (type, "text", "*")) { + camel_stream_printf (stream, + "
\n", + efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); camel_stream_write_string(stream, "\n"); em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, camel_medium_get_content_object((CamelMedium *)newpart)); camel_stream_flush((CamelStream *)filtered_stream); camel_stream_write_string(stream, "\n"); + camel_stream_write_string(stream, "
\n"); } else { g_string_append_printf(((EMFormat *)efh)->part_id, ".inline.%d", i); em_format_part((EMFormat *)efh, stream, newpart); @@ -754,7 +868,6 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo } camel_object_unref(filtered_stream); - camel_stream_write_string(stream, "
\n"); } static void @@ -1114,6 +1227,8 @@ static EMFormatHandler type_builtin_table[] = { { "message/external-body", (EMFormatFunc)efh_message_external }, { "message/delivery-status", (EMFormatFunc)efh_message_deliverystatus }, { "multipart/related", (EMFormatFunc)efh_multipart_related }, + { "application/x-inlinepgp-signed", (EMFormatFunc)efh_inlinepgp_signed }, + { "application/x-inlinepgp-encrypted", (EMFormatFunc)efh_inlinepgp_encrypted }, /* This is where one adds those busted, non-registered types, that some idiot mailer writers out there decide to pull out diff --git a/mail/em-format.c b/mail/em-format.c index dd7cf1e084..10965148c0 100644 --- a/mail/em-format.c +++ b/mail/em-format.c @@ -914,6 +914,8 @@ int em_format_is_attachment(EMFormat *emf, CamelMimePart *part) return !(camel_content_type_is (dw->mime_type, "multipart", "*") || camel_content_type_is(dw->mime_type, "application", "x-pkcs7-mime") || camel_content_type_is(dw->mime_type, "application", "pkcs7-mime") + || camel_content_type_is(dw->mime_type, "application", "x-inlinepgp-signed") + || camel_content_type_is(dw->mime_type, "application", "x-inlinepgp-encrypted") || (camel_content_type_is (dw->mime_type, "text", "*") && camel_mime_part_get_filename(part) == NULL)); } diff --git a/mail/em-inline-filter.c b/mail/em-inline-filter.c index 40da981d58..38cd013912 100644 --- a/mail/em-inline-filter.c +++ b/mail/em-inline-filter.c @@ -102,6 +102,7 @@ enum { EMIF_BINHEX, EMIF_POSTSCRIPT, EMIF_PGPSIGNED, + EMIF_PGPENCRYPTED, }; const struct { const char *name; @@ -112,7 +113,8 @@ const struct { { "application/octet-stream", CAMEL_TRANSFER_ENCODING_UUENCODE, }, { "application/mac-binhex40", CAMEL_TRANSFER_ENCODING_7BIT, }, { "application/postscript", CAMEL_TRANSFER_ENCODING_7BIT, }, - { "text/plain", CAMEL_TRANSFER_ENCODING_7BIT, 1, }, + { "application/x-inlinepgp-signed", CAMEL_TRANSFER_ENCODING_DEFAULT, }, + { "application/x-inlinepgp-encrypted", CAMEL_TRANSFER_ENCODING_DEFAULT, }, }; static void @@ -124,12 +126,16 @@ emif_add_part(EMInlineFilter *emif, const char *data, int len) CamelMimePart *part; const char *mimetype; - if (emif->state == EMIF_PLAIN) + if (emif->state == EMIF_PLAIN || emif->state == EMIF_PGPSIGNED || emif->state == EMIF_PGPENCRYPTED) type = emif->base_encoding; else type = emif_types[emif->state].type; g_byte_array_append(emif->data, data, len); + /* check the part will actually have content */ + if (emif->data->len <= 0) { + return; + } mem = camel_stream_mem_new_with_byte_array(emif->data); emif->data = g_byte_array_new(); @@ -223,17 +229,18 @@ emif_scan(CamelMimeFilter *f, char *in, size_t len, int final) emif_add_part(emif, data_start, start-data_start); data_start = start; emif->state = EMIF_POSTSCRIPT; -#if 0 -/* This should be hooked in once someone can work out how to handle it. - Maybe we need a multipart_gpg_inline_signed or some crap, if it - can't be converted to a real multipart/signed */ } else if (strncmp(start, "-----BEGIN PGP SIGNED MESSAGE-----", 34) == 0) { inptr[-1] = '\n'; emif_add_part(emif, data_start, start-data_start); data_start = start; emif->state = EMIF_PGPSIGNED; -#endif + } else if (strncmp(start, "-----BEGIN PGP MESSAGE-----", 27) == 0) { + inptr[-1] = '\n'; + emif_add_part(emif, data_start, start-data_start); + data_start = start; + emif->state = EMIF_PGPENCRYPTED; } + break; case EMIF_UUENC: if (strcmp(start, "end") == 0) { @@ -279,7 +286,6 @@ emif_scan(CamelMimeFilter *f, char *in, size_t len, int final) } break; case EMIF_PGPSIGNED: - /* This is currently a noop - it just turns it into a text part */ if (strcmp(start, "-----END PGP SIGNATURE-----") == 0) { inptr[-1] = '\n'; emif_add_part(emif, data_start, inptr-data_start); @@ -287,6 +293,14 @@ emif_scan(CamelMimeFilter *f, char *in, size_t len, int final) emif->state = EMIF_PLAIN; } break; + case EMIF_PGPENCRYPTED: + if (strcmp(start, "-----END PGP MESSAGE-----") == 0) { + inptr[-1] = '\n'; + emif_add_part(emif, data_start, inptr-data_start); + data_start = inptr; + emif->state = EMIF_PLAIN; + } + break; } inptr[-1] = '\n'; -- cgit v1.2.3