diff options
-rw-r--r-- | camel/ChangeLog | 13 | ||||
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-mime-filter-chomp.c | 154 | ||||
-rw-r--r-- | camel/camel-mime-filter-chomp.h | 47 | ||||
-rw-r--r-- | camel/camel-pgp-mime.c | 51 | ||||
-rw-r--r-- | camel/camel-types.h | 1 |
6 files changed, 256 insertions, 12 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 02a22a3cc2..99235d0922 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,16 @@ +2002-02-27 Jeffrey Stedfast <fejj@ximian.com> + + * camel-mime-filter-chomp.c (camel_mime_filter_chomp_new): New + stream filter that chomps excess trailing whitespace from the end + of the stream. This is needed to update the PGP/MIME code to + comply with rfc3156. + + * camel-pgp-mime.c (camel_pgp_mime_part_verify): Don't attach a + from filter, if it ain't from-filtered already, then we'll just be + breaking stuff. To become rfc3156 compliant, add a chomp filter + here. + (camel_pgp_mime_part_sign): Add a chomp filter here too. + 2002-02-27 Not Zed <NotZed@Ximian.com> * camel-mime-part.c (init_header_name_table): Changed header diff --git a/camel/Makefile.am b/camel/Makefile.am index 4e626c45ea..a59d75f496 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -45,6 +45,7 @@ libcamel_la_SOURCES = \ camel-mime-filter-bestenc.c \ camel-mime-filter-basic.c \ camel-mime-filter-charset.c \ + camel-mime-filter-chomp.c \ camel-mime-filter-crlf.c \ camel-mime-filter-from.c \ camel-mime-filter-html.c \ @@ -135,6 +136,7 @@ libcamelinclude_HEADERS = \ camel-mime-filter-bestenc.h \ camel-mime-filter-basic.h \ camel-mime-filter-charset.h \ + camel-mime-filter-chomp.h \ camel-mime-filter-crlf.h \ camel-mime-filter-from.h \ camel-mime-filter-html.h \ diff --git a/camel/camel-mime-filter-chomp.c b/camel/camel-mime-filter-chomp.c new file mode 100644 index 0000000000..67a6e71ed7 --- /dev/null +++ b/camel/camel-mime-filter-chomp.c @@ -0,0 +1,154 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2002 Ximian, Inc. + * + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> + +#include "camel-mime-filter-chomp.h" + +static void filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace); +static void complete (CamelMimeFilter *f, char *in, size_t len, + size_t prespace, char **out, size_t *outlen, + size_t *outprespace); +static void reset (CamelMimeFilter *f); + + +static void +camel_mime_filter_chomp_class_init (CamelMimeFilterChompClass *klass) +{ + CamelMimeFilterClass *mime_filter_class = + (CamelMimeFilterClass *) klass; + + mime_filter_class->filter = filter; + mime_filter_class->complete = complete; + mime_filter_class->reset = reset; +} + +CamelType +camel_mime_filter_chomp_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterChomp", + sizeof (CamelMimeFilterChomp), + sizeof (CamelMimeFilterChompClass), + (CamelObjectClassInitFunc) camel_mime_filter_chomp_class_init, + NULL, + NULL, + NULL); + } + + return type; +} + +static void +filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace) +{ + register unsigned char *inptr, *s; + const unsigned char *inend; + register char *outptr; + + camel_mime_filter_set_size (f, len + prespace, FALSE); + + inend = in + len; + inptr = in; + + outptr = f->outbuf; + + while (inptr < inend) { + s = inptr; + while (inptr < inend && isspace ((int) *inptr)) + inptr++; + + if (inptr < inend) { + while (s < inptr) + *outptr++ = (char) *s++; + + while (inptr < inend && !isspace ((int) *inptr)) + *outptr++ = (char) *inptr++; + } else { +#if 0 + if ((inend - s) >= 2 && *s == '\r' && *(s + 1) == '\n') + *outptr++ = *s++; + if (*s == '\n') + *outptr++ = *s++; +#endif + if (s < inend) + camel_mime_filter_backup (f, s, inend - s); + break; + } + } + + *out = f->outbuf; + *outlen = outptr - f->outbuf; + *outprespace = f->outpre; +} + +static void +complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace, + char **out, size_t *outlen, size_t *outprespace) +{ + unsigned char *inptr; + char *outptr; + + if (len) + filter (f, in, len, prespace, out, outlen, outprespace); + + if (f->backlen) { + inptr = (unsigned char *) f->backbuf; + outptr = f->outbuf + *outlen; + + /* in the case of a canonical eoln */ + if (*inptr == '\r' && *(inptr + 1) == '\n') { + *outptr++ = *inptr++; + (*outlen)++; + } + + if (*inptr == '\n') { + *outptr++ = *inptr++; + (*outlen)++; + } + + /* to protect against further complete calls */ + camel_mime_filter_backup (f, "", 0); + } +} + +static void +reset (CamelMimeFilter *f) +{ + /* no-op */ +} + +CamelMimeFilter * +camel_mime_filter_chomp_new (void) +{ + CamelMimeFilterChomp *chomp = CAMEL_MIME_FILTER_CHOMP (camel_object_new (CAMEL_MIME_FILTER_CHOMP_TYPE)); + + return (CamelMimeFilter *) chomp; +} diff --git a/camel/camel-mime-filter-chomp.h b/camel/camel-mime-filter-chomp.h new file mode 100644 index 0000000000..781f2a6368 --- /dev/null +++ b/camel/camel-mime-filter-chomp.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2002 Ximian Inc. + * + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CAMEL_MIME_FILTER_CHOMP_H +#define _CAMEL_MIME_FILTER_CHOMP_H + +#include <camel/camel-mime-filter.h> + +#define CAMEL_MIME_FILTER_CHOMP_TYPE (camel_mime_filter_chomp_get_type ()) +#define CAMEL_MIME_FILTER_CHOMP(obj) CAMEL_CHECK_CAST (obj, CAMEL_MIME_FILTER_CHOMP_TYPE, CamelMimeFilterChomp) +#define CAMEL_MIME_FILTER_CHOMP_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, CAMEL_MIME_FILTER_CHOMP_TYPE, CamelMimeFilterChompClass) +#define CAMEL_IS_MIME_FILTER_CHOMP(obj) CAMEL_CHECK_TYPE (obj, CAMEL_MIME_FILTER_CHOMP_TYPE) + +typedef struct _CamelMimeFilterChompClass CamelMimeFilterChompClass; + +struct _CamelMimeFilterChomp { + CamelMimeFilter parent; + +}; + +struct _CamelMimeFilterChompClass { + CamelMimeFilterClass parent_class; +}; + +CamelType camel_mime_filter_chomp_get_type (void); + +CamelMimeFilter *camel_mime_filter_chomp_new (void); + +#endif /* ! _CAMEL_MIME_FILTER_CHOMP_H */ diff --git a/camel/camel-pgp-mime.c b/camel/camel-pgp-mime.c index f65f0f78a1..4e3eee7cba 100644 --- a/camel/camel-pgp-mime.c +++ b/camel/camel-pgp-mime.c @@ -30,6 +30,7 @@ #include "camel-mime-filter-from.h" #include "camel-mime-filter-crlf.h" #include "camel-mime-filter-charset.h" +#include "camel-mime-filter-chomp.h" #include "camel-stream-filter.h" #include "camel-stream-mem.h" #include "camel-stream-fs.h" @@ -42,7 +43,7 @@ #define d(x) x -/** rfc2015 stuff (aka PGP/MIME) *******************************/ +/** rfc2015/rfc3156 stuff (aka PGP/MIME) *******************************/ gboolean camel_pgp_mime_is_rfc2015_signed (CamelMimePart *mime_part) @@ -235,10 +236,10 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c CamelMultipart *multipart; CamelContentType *mime_type; CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter, *from_filter; + CamelMimeFilter *crlf_filter, *from_filter, *chomp_filter; CamelStream *stream, *sigstream; - gchar *hash_type = NULL; GSList *encodings = NULL; + char *hash_type = NULL; g_return_if_fail (*mime_part != NULL); g_return_if_fail (CAMEL_IS_MIME_PART (*mime_part)); @@ -251,24 +252,42 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c /* get the cleartext */ stream = camel_stream_mem_new (); + filtered_stream = camel_stream_filter_new_with_stream (stream); + + /* Note: see rfc3156, section 3 - second note */ + from_filter = CAMEL_MIME_FILTER (camel_mime_filter_from_new ()); + camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (from_filter)); + camel_object_unref (CAMEL_OBJECT (from_filter)); + + /* Note: see rfc3156, section 5.4 (this is the big thing that changed between rfc2015 and rfc3156) */ + chomp_filter = camel_mime_filter_chomp_new (); + camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (chomp_filter)); + camel_object_unref (CAMEL_OBJECT (chomp_filter)); + + /* Note: see rfc2015 or rfc3156, section 5.1 */ crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - from_filter = CAMEL_MIME_FILTER (camel_mime_filter_from_new ()); - filtered_stream = camel_stream_filter_new_with_stream (stream); camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); camel_object_unref (CAMEL_OBJECT (crlf_filter)); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (from_filter)); - camel_object_unref (CAMEL_OBJECT (from_filter)); + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (part), CAMEL_STREAM (filtered_stream)); + camel_stream_flush (CAMEL_STREAM (filtered_stream)); camel_object_unref (CAMEL_OBJECT (filtered_stream)); /* reset the stream */ camel_stream_reset (stream); + printf ("attempting to sign data:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n", + CAMEL_STREAM_MEM (stream)->buffer->len, CAMEL_STREAM_MEM (stream)->buffer->data); + /* construct the signature stream */ sigstream = camel_stream_mem_new (); switch (hash) { + case CAMEL_CIPHER_HASH_MD2: + /* this is a new addition with rfc3156 */ + hash_type = "pgp-md2"; + break; case CAMEL_CIPHER_HASH_MD5: hash_type = "pgp-md5"; break; @@ -350,7 +369,7 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, CamelMultipart *multipart; CamelMimePart *part, *sigpart; CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter, *from_filter; + CamelMimeFilter *crlf_filter, *chomp_filter; CamelStream *stream, *sigstream; CamelCipherValidity *valid; @@ -366,17 +385,22 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, /* get the plain part */ part = camel_multipart_get_part (multipart, 0); stream = camel_stream_mem_new (); + filtered_stream = camel_stream_filter_new_with_stream (stream); + + /* Note: see rfc3156, section 5.4 (this is the big thing that changed between rfc2015 and rfc3156) */ + chomp_filter = camel_mime_filter_chomp_new (); + camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (chomp_filter)); + camel_object_unref (CAMEL_OBJECT (chomp_filter)); + + /* Note: see rfc2015 or rfc3156, section 5.1 */ crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - from_filter = CAMEL_MIME_FILTER (camel_mime_filter_from_new ()); - filtered_stream = camel_stream_filter_new_with_stream (stream); camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); camel_object_unref (CAMEL_OBJECT (crlf_filter)); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (from_filter)); - camel_object_unref (CAMEL_OBJECT (from_filter)); wrapper = CAMEL_DATA_WRAPPER (part); camel_data_wrapper_write_to_stream (wrapper, CAMEL_STREAM (filtered_stream)); + camel_stream_flush (CAMEL_STREAM (filtered_stream)); camel_object_unref (CAMEL_OBJECT (filtered_stream)); camel_stream_reset (stream); @@ -390,6 +414,9 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, /* verify */ valid = camel_pgp_verify (context, stream, sigstream, ex); + printf ("attempted to verify data:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n", + CAMEL_STREAM_MEM (stream)->buffer->len, CAMEL_STREAM_MEM (stream)->buffer->data); + camel_object_unref (CAMEL_OBJECT (sigstream)); camel_object_unref (CAMEL_OBJECT (stream)); diff --git a/camel/camel-types.h b/camel/camel-types.h index 86da09cae4..292358a1d9 100644 --- a/camel/camel-types.h +++ b/camel/camel-types.h @@ -45,6 +45,7 @@ typedef struct _CamelMimeFilter CamelMimeFilter; typedef struct _CamelMimeFilterBasic CamelMimeFilterBasic; typedef struct _CamelMimeFilterBestenc CamelMimeFilterBestenc; typedef struct _CamelMimeFilterCharset CamelMimeFilterCharset; +typedef struct _CamelMimeFilterChomp CamelMimeFilterChomp; typedef struct _CamelMimeFilterIndex CamelMimeFilterIndex; typedef struct _CamelMimeFilterLinewrap CamelMimeFilterLinewrap; typedef struct _CamelMimeFilterSave CamelMimeFilterSave; |