aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog55
-rw-r--r--camel/Makefile.am4
-rw-r--r--camel/camel-cipher-context.c33
-rw-r--r--camel/camel-cipher-context.h9
-rw-r--r--camel/camel-folder-summary.h2
-rw-r--r--camel/camel-mime-filter-canon.c226
-rw-r--r--camel/camel-mime-filter-canon.h65
-rw-r--r--camel/camel-mime-parser.c10
-rw-r--r--camel/camel-mime-part-utils.c42
-rw-r--r--camel/camel-mime-part.h1
-rw-r--r--camel/camel-multipart-signed.c720
-rw-r--r--camel/camel-multipart-signed.h103
-rw-r--r--camel/camel-multipart.c57
-rw-r--r--camel/camel-multipart.h12
-rw-r--r--camel/camel-pgp-context.c55
-rw-r--r--camel/camel-seekable-substream.c5
-rw-r--r--camel/camel-seekable-substream.h3
-rw-r--r--camel/camel-smime-context.c48
-rw-r--r--camel/camel-stream-filter.c20
-rw-r--r--camel/providers/nntp/camel-nntp-stream.c2
-rw-r--r--camel/tests/stream/test3.c8
21 files changed, 1422 insertions, 58 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 5c024f3900..c25feb4098 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,58 @@
+2002-05-30 Not Zed <NotZed@Ximian.com>
+
+ * camel-cipher-context.h: Added a protocol field for users to use.
+
+ * camel-stream-filter.c (do_read): Sigh, the pre-size is READ_PAD
+ not READ_SIZE. Big difference.
+ (READ_PAD): Bumped upto 128 from 64, so we can fit a typical line
+ in full.
+
+ * providers/imap/camel-imap-folder.c (get_content): Changed to
+ load multipart/signed as an opaque block into the right kind of
+ object.
+
+ * camel-multipart.h (struct _CamelMultipart): Removed the boundary
+ field. It wans't actually used anywhere.
+
+ * camel-seekable-substream.c
+ (camel_seekable_substream_new_with_seekable_stream_and_bounds):
+ Shortened this stupidly long name to just :new(), its the only way
+ its ever used. Fixed all callers.
+
+ * camel-multipart-signed.[ch]: new wrapper for multipart/signed
+ types. We need to treat the entire content as a blob of data for
+ transport purposes. This also cleans up a lot of the sign/verify
+ handling.
+
+ * camel-mime-part-utils.c
+ (camel_mime_part_construct_content_from_parser): Just call
+ camel_multipart_construct_from_parser for multipart parts, also
+ use a multipart_signed for multipart/signed types.
+
+ * camel-multipart.c (camel_multipart_construct_from_parser): New
+ virtual function for multiparts to buld themselves.
+ (construct_from_parser): Implement for normal multiparts.
+ (toplevel): Got rid of a warning, it'll never be an abstract
+ class.
+
+ * camel-pgp-context.c (pgp_hash_to_id):
+ (pgp_id_to_hash): Implement.
+ (camel_pgp_context_init): Init the pgp protocol specifier.
+
+ * camel-cipher-context.c (camel_cipher_id_to_hash):
+ (camel_cipher_hash_to_id): Util virtual methods to handle the
+ cipher id string.
+
+ * camel-mime-filter-canon.[ch]: A new filter, end/start of line
+ canonicalisation filter. Can escape "From " and strip trailing
+ whitespace, and canonicalise the end of line to crlf or to lf.
+
+2002-05-29 Not Zed <NotZed@Ximian.com>
+
+ * camel-multipart.h (struct _CamelMultipart): Removed the
+ 'parent', nothing used it, anywhere. Cleaned up some formatting
+ slightly.
+
2002-05-30 Jeffrey Stedfast <fejj@ximian.com>
* providers/imap/camel-imap-store.c (camel_imap_store_readline):
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 36be0ea18d..a58f0e35db 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -50,6 +50,7 @@ libcamel_la_SOURCES = \
camel-mime-filter-basic.c \
camel-mime-filter-charset.c \
camel-mime-filter-chomp.c \
+ camel-mime-filter-canon.c \
camel-mime-filter-crlf.c \
camel-mime-filter-from.c \
camel-mime-filter-html.c \
@@ -65,6 +66,7 @@ libcamel_la_SOURCES = \
camel-mime-utils.c \
camel-movemail.c \
camel-multipart.c \
+ camel-multipart-signed.c \
camel-object.c \
camel-operation.c \
camel-partition-table.c \
@@ -146,6 +148,7 @@ libcamelinclude_HEADERS = \
camel-mime-filter-basic.h \
camel-mime-filter-charset.h \
camel-mime-filter-chomp.h \
+ camel-mime-filter-canon.h \
camel-mime-filter-crlf.h \
camel-mime-filter-from.h \
camel-mime-filter-html.h \
@@ -161,6 +164,7 @@ libcamelinclude_HEADERS = \
camel-mime-utils.h \
camel-movemail.h \
camel-multipart.h \
+ camel-multipart-signed.h \
camel-object.h \
camel-operation.h \
camel-partition-table.h \
diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c
index feefff5565..7771a3a64a 100644
--- a/camel/camel-cipher-context.c
+++ b/camel/camel-cipher-context.c
@@ -61,6 +61,9 @@ static int cipher_encrypt (CamelCipherContext *context, gboolea
static int cipher_decrypt (CamelCipherContext *context, CamelStream *istream,
CamelStream *ostream, CamelException *ex);
+static const char *cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash);
+static CamelCipherHash cipher_id_to_hash(CamelCipherContext *context, const char *id);
+
static CamelObjectClass *parent_class;
static void
@@ -96,6 +99,8 @@ camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_c
camel_cipher_context_class->verify = cipher_verify;
camel_cipher_context_class->encrypt = cipher_encrypt;
camel_cipher_context_class->decrypt = cipher_decrypt;
+ camel_cipher_context_class->hash_to_id = cipher_hash_to_id;
+ camel_cipher_context_class->id_to_hash = cipher_id_to_hash;
}
CamelType
@@ -364,6 +369,34 @@ camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream,
return retval;
}
+static CamelCipherHash
+cipher_id_to_hash(CamelCipherContext *context, const char *id)
+{
+ return CAMEL_CIPHER_HASH_DEFAULT;
+}
+
+/* a couple of util functions */
+CamelCipherHash
+camel_cipher_id_to_hash(CamelCipherContext *context, const char *id)
+{
+ g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), CAMEL_CIPHER_HASH_DEFAULT);
+
+ return ((CamelCipherContextClass *)((CamelObject *)context)->klass)->id_to_hash(context, id);
+}
+
+static const char *
+cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
+{
+ return NULL;
+}
+
+const char *
+camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
+{
+ g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
+
+ return ((CamelCipherContextClass *)((CamelObject *)context)->klass)->hash_to_id(context, hash);
+}
/* Cipher Validity stuff */
struct _CamelCipherValidity {
diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h
index 5147cc5ebc..c3a6641967 100644
--- a/camel/camel-cipher-context.h
+++ b/camel/camel-cipher-context.h
@@ -51,6 +51,8 @@ typedef struct _CamelCipherContext {
CamelObject parent_object;
struct _CamelCipherContextPrivate *priv;
+
+ const char *protocol; /* this MUST be set by implementors */
CamelSession *session;
@@ -76,6 +78,9 @@ typedef struct _CamelCipherContextClass {
int (*decrypt) (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream,
CamelException *ex);
+ CamelCipherHash (*id_to_hash)(CamelCipherContext *context, const char *id);
+ const char * (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash);
+
} CamelCipherContextClass;
CamelType camel_cipher_context_get_type (void);
@@ -102,6 +107,10 @@ int camel_cipher_encrypt (CamelCipherContext *context, gboolean
int camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream,
CamelException *ex);
+/* cipher context util routines */
+CamelCipherHash camel_cipher_id_to_hash(CamelCipherContext *context, const char *id);
+const char * camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash);
+
/* CamelCipherValidity utility functions */
CamelCipherValidity *camel_cipher_validity_new (void);
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
index 7545f2af22..62ea39a1df 100644
--- a/camel/camel-folder-summary.h
+++ b/camel/camel-folder-summary.h
@@ -51,7 +51,7 @@ struct _CamelMessageContentInfo {
struct _header_content_type *type;
char *id;
char *description;
- char *encoding;
+ char *encoding; /* this should be an enum?? */
guint32 size;
};
diff --git a/camel/camel-mime-filter-canon.c b/camel/camel-mime-filter-canon.c
new file mode 100644
index 0000000000..0fd48fb7b3
--- /dev/null
+++ b/camel/camel-mime-filter-canon.c
@@ -0,0 +1,226 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 Ximian, Inc.
+ *
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ * Michael Zucchi <notzed@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.
+ */
+
+/* canonicalisation filter, used for secure mime incoming and outgoing */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include "camel-mime-filter-canon.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_canon_class_init (CamelMimeFilterCanonClass *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_canon_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterCanon",
+ sizeof (CamelMimeFilterCanon),
+ sizeof (CamelMimeFilterCanonClass),
+ (CamelObjectClassInitFunc) camel_mime_filter_canon_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, c;
+ const unsigned char *inend, *start;
+ char *starto;
+ register char *o;
+ int lf = 0;
+ guint32 flags;
+
+ flags = ((CamelMimeFilterCanon *)f)->flags;
+
+ /* first, work out how much space we need */
+ inptr = in;
+ inend = in+len;
+ while (inptr < inend)
+ if (*inptr++ == '\n')
+ lf++;
+
+ /* worst case, extra 3 chars per line
+ "From \n" -> "=46rom \r\n"
+ We add 1 extra incase we're called from complete, when we didn't end in \n */
+
+ camel_mime_filter_set_size(f, len+lf*3+4, FALSE);
+
+ o = f->outbuf;
+ inptr = in;
+ start = inptr;
+ starto = o;
+ while (inptr < inend) {
+ /* first, check start of line, we always start at the start of the line */
+ c = *inptr;
+ if (flags & CAMEL_MIME_FILTER_CANON_FROM && c == 'F') {
+ inptr++;
+ if (inptr < inend-4) {
+ if (strncmp(inptr, "rom ", 4) == 0) {
+ *o++ = '=';
+ *o++ = '4';
+ *o++ = '6';
+ } else
+ *o++ = 'F';
+ *o++ = *inptr++;
+ *o++ = *inptr++;
+ *o++ = *inptr++;
+ *o++ = *inptr++;
+ } else {
+ break;
+ }
+ }
+
+ /* now scan for end of line */
+ while (inptr < inend) {
+ c = *inptr++;
+ if (c == '\n') {
+ /* check to strip trailing space */
+ if (flags & CAMEL_MIME_FILTER_CANON_STRIP) {
+ while (o>starto && (o[-1] == ' ' || o[-1] == '\t' || o[-1]=='\r'))
+ o--;
+ }
+ /* check end of line canonicalisation */
+ if (o>starto) {
+ if (flags & CAMEL_MIME_FILTER_CANON_CRLF) {
+ if (o[-1] != '\r')
+ *o++ = '\r';
+ } else {
+ if (o[-1] == '\r')
+ o--;
+ }
+ }
+ *o++ = c;
+ start = inptr;
+ starto = o;
+ break;
+ } else
+ *o++ = c;
+ }
+ }
+
+ /* TODO: We should probably track if we end somewhere in the middle of a line,
+ otherwise we potentially backup a full line, which could be large */
+
+ /* we got to the end of the data without finding anything, backup to start and re-process next time around */
+ camel_mime_filter_backup(f, start, inend - start);
+
+ *out = f->outbuf;
+ *outlen = starto - 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, *inend;
+ char *o, *starto;
+ guint32 flags;
+
+ if (len)
+ filter(f, in, len, prespace, out, outlen, outprespace);
+
+ /* the data didn't contain an eol or was too short for "From ", we only need to check for "From" and add an eol */
+ if (f->backlen) {
+ inptr = (unsigned char *)f->backbuf;
+ inend = (unsigned char *)f->backbuf + f->backlen;
+ starto = o = *out + *outlen;
+ flags = ((CamelMimeFilterCanon *)f)->flags;
+
+ /* Check any embedded "From " */
+ if (f->backlen >= 5
+ && (flags & CAMEL_MIME_FILTER_CANON_FROM)
+ && strcmp(inptr, "From ") == 0) {
+ strcpy(o, "=46rom ");
+ o += 7;
+ inptr += 5;
+ }
+
+ /* copy the rest of it */
+ while (inptr < inend)
+ *o++ = *inptr++;
+
+ /* check to strip trailing space */
+ if (flags & CAMEL_MIME_FILTER_CANON_STRIP) {
+ while (o>starto && (o[-1] == ' ' || o[-1] == '\t' || o[-1]=='\r'))
+ o--;
+ }
+ /* check end of line canonicalisation */
+ if (o>starto) {
+ if (flags & CAMEL_MIME_FILTER_CANON_CRLF) {
+ if (o[-1] != '\r')
+ *o++ = '\r';
+ } else {
+ if (o[-1] == '\r')
+ o--;
+ }
+ }
+
+ /* and always finish with an eol */
+ *o++ = '\n';
+
+ *outlen = o - *out;
+ }
+}
+
+static void
+reset (CamelMimeFilter *f)
+{
+ /* no-op */
+}
+
+CamelMimeFilter *
+camel_mime_filter_canon_new(guint32 flags)
+{
+ CamelMimeFilterCanon *chomp = CAMEL_MIME_FILTER_CANON (camel_object_new (CAMEL_MIME_FILTER_CANON_TYPE));
+
+ chomp->flags = flags;
+
+ return (CamelMimeFilter *) chomp;
+}
diff --git a/camel/camel-mime-filter-canon.h b/camel/camel-mime-filter-canon.h
new file mode 100644
index 0000000000..d3cffb240e
--- /dev/null
+++ b/camel/camel-mime-filter-canon.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 Ximian Inc.
+ *
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ * Michael Zucchi <notzed@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_CANON_H
+#define _CAMEL_MIME_FILTER_CANON_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <camel/camel-mime-filter.h>
+
+#define CAMEL_MIME_FILTER_CANON_TYPE (camel_mime_filter_canon_get_type ())
+#define CAMEL_MIME_FILTER_CANON(obj) CAMEL_CHECK_CAST (obj, CAMEL_MIME_FILTER_CANON_TYPE, CamelMimeFilterCanon)
+#define CAMEL_MIME_FILTER_CANON_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, CAMEL_MIME_FILTER_CANON_TYPE, CamelMimeFilterCanonClass)
+#define CAMEL_IS_MIME_FILTER_CANON(obj) CAMEL_CHECK_TYPE (obj, CAMEL_MIME_FILTER_CANON_TYPE)
+
+typedef struct _CamelMimeFilterCanon CamelMimeFilterCanon;
+typedef struct _CamelMimeFilterCanonClass CamelMimeFilterCanonClass;
+
+enum {
+ CAMEL_MIME_FILTER_CANON_CRLF = (1<<0), /* canoncialise end of line to crlf, otherwise canonicalise to lf only */
+ CAMEL_MIME_FILTER_CANON_FROM = (1<<1), /* escape "^From " using quoted-printable semantics into "=46rom " */
+ CAMEL_MIME_FILTER_CANON_STRIP = (1<<2), /* strip trailing space */
+};
+
+struct _CamelMimeFilterCanon {
+ CamelMimeFilter parent;
+
+ guint32 flags;
+};
+
+struct _CamelMimeFilterCanonClass {
+ CamelMimeFilterClass parent_class;
+};
+
+CamelType camel_mime_filter_canon_get_type (void);
+
+CamelMimeFilter *camel_mime_filter_canon_new(guint32 flags);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* ! _CAMEL_MIME_FILTER_CANON_H */
diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c
index f57583135d..2bfe4e5322 100644
--- a/camel/camel-mime-parser.c
+++ b/camel/camel-mime-parser.c
@@ -1681,8 +1681,8 @@ tail_recurse:
if ( (content = header_raw_find(&h->headers, "Content-Type", NULL))
&& (ct = header_content_type_decode(content))) {
if (!strcasecmp(ct->type, "multipart")) {
- bound = header_content_type_param(ct, "boundary");
- if (bound) {
+ if (!header_content_type_is(ct, "multipart", "signed")
+ && (bound = header_content_type_param(ct, "boundary"))) {
d(printf("multipart, boundary = %s\n", bound));
h->boundarylen = strlen(bound)+2;
h->boundarylenfinal = h->boundarylen+2;
@@ -1690,11 +1690,11 @@ tail_recurse:
sprintf(h->boundary, "--%s--", bound);
type = HSCAN_MULTIPART;
} else {
- header_content_type_unref(ct);
- ct = header_content_type_decode("text/plain");
+ /*header_content_type_unref(ct);
+ ct = header_content_type_decode("text/plain");*/
/* We can't quite do this, as it will mess up all the offsets ... */
/* header_raw_replace(&h->headers, "Content-Type", "text/plain", offset);*/
- g_warning("Multipart with no boundary, treating as text/plain");
+ /*g_warning("Multipart with no boundary, treating as text/plain");*/
}
} else if (!strcasecmp(ct->type, "message")) {
if (!strcasecmp(ct->subtype, "rfc822")
diff --git a/camel/camel-mime-part-utils.c b/camel/camel-mime-part-utils.c
index 987e5e77d7..037493b501 100644
--- a/camel/camel-mime-part-utils.c
+++ b/camel/camel-mime-part-utils.c
@@ -38,6 +38,7 @@
#include "camel-mime-part-utils.h"
#include "camel-mime-message.h"
#include "camel-multipart.h"
+#include "camel-multipart-signed.h"
#include "camel-seekable-substream.h"
#include "camel-stream-fs.h"
#include "camel-stream-filter.h"
@@ -336,47 +337,30 @@ void
camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParser *mp)
{
CamelDataWrapper *content = NULL;
- char *buf;
- int len;
switch (camel_mime_parser_state (mp)) {
case HSCAN_HEADER:
d(printf("Creating body part\n"));
- content = camel_data_wrapper_new ();
- simple_data_wrapper_construct_from_parser (content, mp);
+ /* multipart/signed is some fucked up type that we must treat as binary data, fun huh, idiots. */
+ if (header_content_type_is(camel_mime_parser_content_type(mp), "multipart", "signed")) {
+ content = (CamelDataWrapper *)camel_multipart_signed_new();
+ camel_multipart_construct_from_parser((CamelMultipart *)content, mp);
+ } else {
+ content = camel_data_wrapper_new ();
+ simple_data_wrapper_construct_from_parser (content, mp);
+ }
break;
case HSCAN_MESSAGE:
d(printf("Creating message part\n"));
content = (CamelDataWrapper *) camel_mime_message_new ();
camel_mime_part_construct_from_parser ((CamelMimePart *)content, mp);
break;
- case HSCAN_MULTIPART: {
- struct _header_content_type *content_type;
- CamelDataWrapper *bodypart;
-
- /* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
+ case HSCAN_MULTIPART:
d(printf("Creating multi-part\n"));
-
- content = (CamelDataWrapper *)camel_multipart_new ();
-
- content_type = camel_mime_parser_content_type (mp);
- camel_multipart_set_boundary ((CamelMultipart *)content,
- header_content_type_param (content_type, "boundary"));
-
- while (camel_mime_parser_step (mp, &buf, &len) != HSCAN_MULTIPART_END) {
- camel_mime_parser_unstep (mp);
- bodypart = (CamelDataWrapper *)camel_mime_part_new ();
- camel_mime_part_construct_from_parser ((CamelMimePart *)bodypart, mp);
- camel_multipart_add_part ((CamelMultipart *)content, (CamelMimePart *)bodypart);
- camel_object_unref ((CamelObject *)bodypart);
- }
-
- /* these are only return valid data in the MULTIPART_END state */
- camel_multipart_set_preface ((CamelMultipart *)content, camel_mime_parser_preface (mp));
- camel_multipart_set_postface ((CamelMultipart *)content, camel_mime_parser_postface (mp));
-
+ content = (CamelDataWrapper *)camel_multipart_new();
+ camel_multipart_construct_from_parser((CamelMultipart *)content, mp);
d(printf("Created multi-part\n"));
- break; }
+ break;
default:
g_warning("Invalid state encountered???: %d", camel_mime_parser_state (mp));
}
diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h
index 4f05ecb71b..e745f57a6a 100644
--- a/camel/camel-mime-part.h
+++ b/camel/camel-mime-part.h
@@ -65,6 +65,7 @@ struct _CamelMimePart
struct _header_raw *headers; /* mime headers */
/* All fields here are -** PRIVATE **- */
+ /* TODO: these should be in a camelcontentinfo */
char *description;
CamelMimeDisposition *disposition;
char *content_id;
diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c
new file mode 100644
index 0000000000..95e0e848da
--- /dev/null
+++ b/camel/camel-multipart-signed.c
@@ -0,0 +1,720 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * camel-multipart.c : Abstract class for a multipart
+ *
+ * Authors: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2002 Ximian, Inc. (www.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 <stdio.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <errno.h>
+
+#include "camel-mime-part.h"
+#include "camel-mime-message.h"
+#include "camel-mime-parser.h"
+#include "camel-stream-mem.h"
+#include "camel-multipart-signed.h"
+#include "camel-mime-part.h"
+#include "camel-exception.h"
+#include "md5-utils.h"
+
+#include "camel-stream-filter.h"
+#include "camel-seekable-substream.h"
+#include "camel-mime-filter-chomp.h"
+#include "camel-mime-filter-crlf.h"
+#include "camel-mime-filter-canon.h"
+
+#define d(x)
+
+static void signed_add_part(CamelMultipart *multipart, CamelMimePart *part);
+static void signed_add_part_at(CamelMultipart *multipart, CamelMimePart *part, guint index);
+static void signed_remove_part(CamelMultipart *multipart, CamelMimePart *part);
+static CamelMimePart *signed_remove_part_at (CamelMultipart *multipart, guint index);
+static CamelMimePart *signed_get_part(CamelMultipart *multipart, guint index);
+static guint signed_get_number(CamelMultipart *multipart);
+
+static int write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream);
+static void set_mime_type_field(CamelDataWrapper *data_wrapper, CamelContentType *mime_type);
+static int construct_from_stream(CamelDataWrapper *data_wrapper, CamelStream *stream);
+static int signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp);
+
+static CamelMultipartClass *parent_class = NULL;
+
+/* Returns the class for a CamelMultipartSigned */
+#define CMP_CLASS(so) CAMEL_MULTIPART_SIGNED_CLASS (CAMEL_OBJECT_GET_CLASS(so))
+
+/* Returns the class for a CamelDataWrapper */
+#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
+
+static void
+camel_multipart_signed_class_init (CamelMultipartSignedClass *camel_multipart_signed_class)
+{
+ CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS(camel_multipart_signed_class);
+ CamelMultipartClass *mpclass = (CamelMultipartClass *)camel_multipart_signed_class;
+
+ parent_class = (CamelMultipartClass *)camel_multipart_get_type();
+
+ /* virtual method overload */
+ camel_data_wrapper_class->construct_from_stream = construct_from_stream;
+ camel_data_wrapper_class->write_to_stream = write_to_stream;
+ camel_data_wrapper_class->set_mime_type_field = set_mime_type_field;
+
+ mpclass->add_part = signed_add_part;
+ mpclass->add_part_at = signed_add_part_at;
+ mpclass->remove_part = signed_remove_part;
+ mpclass->remove_part_at = signed_remove_part_at;
+ mpclass->get_part = signed_get_part;
+ mpclass->get_number = signed_get_number;
+ mpclass->construct_from_parser = signed_construct_from_parser;
+
+/*
+ mpclass->get_boundary = signed_get_boundary;
+ mpclass->set_boundary = signed_set_boundary;
+*/
+}
+
+static void
+camel_multipart_signed_init (gpointer object, gpointer klass)
+{
+ CamelMultipartSigned *multipart = (CamelMultipartSigned *)object;
+
+ camel_data_wrapper_set_mime_type(CAMEL_DATA_WRAPPER(multipart), "multipart/signed");
+ multipart->start1 = -1;
+}
+
+static void
+camel_multipart_signed_finalize (CamelObject *object)
+{
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)object;
+
+ g_free(mps->protocol);
+ g_free(mps->micalg);
+ if (mps->signature)
+ camel_object_unref((CamelObject *)mps->signature);
+ if (mps->content)
+ camel_object_unref((CamelObject *)mps->content);
+ if (mps->contentraw)
+ camel_object_unref((CamelObject *)mps->contentraw);
+}
+
+CamelType
+camel_multipart_signed_get_type (void)
+{
+ static CamelType camel_multipart_signed_type = CAMEL_INVALID_TYPE;
+
+ if (camel_multipart_signed_type == CAMEL_INVALID_TYPE) {
+ camel_multipart_signed_type = camel_type_register (camel_multipart_get_type (), "CamelMultipartSigned",
+ sizeof (CamelMultipartSigned),
+ sizeof (CamelMultipartSignedClass),
+ (CamelObjectClassInitFunc) camel_multipart_signed_class_init,
+ NULL,
+ (CamelObjectInitFunc) camel_multipart_signed_init,
+ (CamelObjectFinalizeFunc) camel_multipart_signed_finalize);
+ }
+
+ return camel_multipart_signed_type;
+}
+
+/**
+ * camel_multipart_signed_new:
+ *
+ * Create a new CamelMultipartSigned object.
+ *
+ * A MultipartSigned should be used to store and create parts of
+ * type "multipart/signed". This is because multipart/signed is
+ * entirely broken-by-design (tm) and uses completely
+ * different semantics to other mutlipart types. It must be treated
+ * as opaque data by any transport. See rfc 3156 for details.
+ *
+ * There are 3 ways to create the part:
+ * Use construct_from_stream. If this is used, then you must
+ * set the mime_type appropriately to match the data uses, so
+ * that the multiple parts my be extracted.
+ *
+ * Use construct_from_parser. The parser MUST be in the HSCAN_HEADER
+ * state, and the current content_type MUST be "multipart/signed" with
+ * the appropriate boundary and it SHOULD include the appropriate protocol
+ * and hash specifiers.
+ *
+ * Use sign_part. A signature part will automatically be created
+ * and the whole part may be written using write_to_stream to
+ * create a 'transport-safe' version (as safe as can be expected with
+ * such a broken specification).
+ *
+ * Return value: a new CamelMultipartSigned
+ **/
+CamelMultipartSigned *
+camel_multipart_signed_new (void)
+{
+ CamelMultipartSigned *multipart;
+
+ multipart = (CamelMultipartSigned *)camel_object_new(CAMEL_MULTIPART_SIGNED_TYPE);
+
+ return multipart;
+}
+
+/* yeah yuck.
+ Well, we could probably use the normal mime parser, but then it would change our
+ headers.
+ This is good enough ... till its not! */
+static int
+parse_content(CamelMultipartSigned *mps)
+{
+ CamelMultipart *mp = (CamelMultipart *)mps;
+ char *start, *end, *start2, *end2, *last;
+ CamelStreamMem *mem;
+ char *bound;
+ const char *boundary;
+
+ boundary = camel_multipart_get_boundary(mp);
+ if (boundary == NULL) {
+ g_warning("Trying to get multipart/signed content without setting boundary first");
+ return -1;
+ }
+
+ /* turn it into a string, and 'fix' it up */
+ /* this is extremely dodgey but should work! */
+ mem = (CamelStreamMem *)((CamelDataWrapper *)mps)->stream;
+ if (mem == NULL) {
+ g_warning("Trying to parse multipart/signed without constructing first");
+ return -1;
+ }
+
+ camel_stream_write((CamelStream *)mem, "", 1);
+ g_byte_array_set_size(mem->buffer, mem->buffer->len-1);
+ last = mem->buffer->data + mem->buffer->len;
+
+ bound = alloca(strlen(boundary)+5);
+ sprintf(bound, "--%s", boundary);
+
+ start = strstr(mem->buffer->data, bound);
+ if (start == NULL) {
+ printf("construct from stream, cannot find first boundary\n");
+ return -1;
+ }
+
+ if (start > (char *)mem->buffer->data) {
+ char *tmp = g_strndup(mem->buffer->data, start-(char *)mem->buffer->data-1);
+ camel_multipart_set_preface(mp, tmp);
+ g_free(tmp);
+ }
+
+ start += strlen(bound)+1;
+ if (start >= last)
+ return -1;
+ end = strstr(start, bound);
+ if (end == NULL) {
+ printf("construct from stream, cannot find second boundary\n");
+ return -1;
+ }
+
+ start2 = end + strlen(bound)+1;
+ if (start2 >= last)
+ return -1;
+ sprintf(bound, "--%s--", boundary);
+ end2 = strstr(start2, bound);
+ if (end2 == NULL) {
+ printf("construct from stream, cannot find last boundary\n");
+ return -1;
+ }
+
+ if (end2+strlen(bound)+1 < last)
+ camel_multipart_set_postface(mp, end2+strlen(bound)+1);
+
+ mps->start1 = start-(char *)mem->buffer->data;
+ mps->end1 = end-(char *)mem->buffer->data-1;
+ mps->start2 = start2-(char *)mem->buffer->data;
+ mps->end2 = end2-(char *)mem->buffer->data-1;
+
+ return 0;
+}
+
+/* we snoop the mime type to get boundary and hash info */
+static void
+set_mime_type_field(CamelDataWrapper *data_wrapper, CamelContentType *mime_type)
+{
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
+
+ ((CamelDataWrapperClass *)parent_class)->set_mime_type_field(data_wrapper, mime_type);
+ if (mime_type) {
+ const char *micalg, *protocol;
+
+ protocol = header_content_type_param(mime_type, "protocol");
+ g_free(mps->protocol);
+ mps->protocol = g_strdup(protocol);
+
+ micalg = header_content_type_param(mime_type, "micalg");
+ g_free(mps->micalg);
+ mps->micalg = g_strdup(micalg);
+ }
+}
+
+static void
+signed_add_part(CamelMultipart *multipart, CamelMimePart *part)
+{
+ g_warning("Cannot add parts to a signed part using add_part");
+}
+
+static void
+signed_add_part_at(CamelMultipart *multipart, CamelMimePart *part, guint index)
+{
+ g_warning("Cannot add parts to a signed part using add_part_at");
+}
+
+static void
+signed_remove_part(CamelMultipart *multipart, CamelMimePart *part)
+{
+ g_warning("Cannot remove parts from a signed part using remove_part");
+}
+
+static CamelMimePart *
+signed_remove_part_at (CamelMultipart *multipart, guint index)
+{
+ g_warning("Cannot remove parts from a signed part using remove_part");
+ return NULL;
+}
+
+static CamelMimePart *
+signed_get_part(CamelMultipart *multipart, guint index)
+{
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart;
+ CamelDataWrapper *dw = (CamelDataWrapper *)multipart;
+ CamelStream *stream;
+
+ switch (index) {
+ case CAMEL_MULTIPART_SIGNED_CONTENT:
+ if (mps->content)
+ return mps->content;
+ if (mps->contentraw) {
+ stream = mps->contentraw;
+ camel_object_ref((CamelObject *)stream);
+ } else if (mps->start1 == -1
+ && parse_content(mps) == -1
+ && (stream = ((CamelDataWrapper *)mps)->stream) == NULL) {
+ g_warning("Trying to get content on an invalid multipart/signed");
+ return NULL;
+ } else if (dw->stream == NULL) {
+ return NULL;
+ } else {
+ stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start1, mps->end1);
+ }
+ camel_stream_reset(stream);
+ mps->content = camel_mime_part_new();
+ camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->content, stream);
+ camel_object_unref((CamelObject *)stream);
+ return mps->content;
+ case CAMEL_MULTIPART_SIGNED_SIGNATURE:
+ if (mps->signature)
+ return mps->signature;
+ if (mps->start1 == -1
+ && parse_content(mps) == -1) {
+ g_warning("Trying to get signature on invalid multipart/signed");
+ return NULL;
+ } else if (dw->stream == NULL) {
+ return NULL;
+ }
+ stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start2, mps->end2);
+ camel_stream_reset(stream);
+ mps->signature = camel_mime_part_new();
+ camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->signature, stream);
+ camel_object_unref((CamelObject *)stream);
+ return mps->signature;
+ default:
+ g_warning("trying to get object out of bounds for multipart");
+ }
+
+ return NULL;
+}
+
+static guint
+signed_get_number(CamelMultipart *multipart)
+{
+ CamelDataWrapper *dw = (CamelDataWrapper *)multipart;
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart;
+
+ /* check what we have, so we return something reasonable */
+
+ if ((mps->content || mps->contentraw) && mps->signature)
+ return 2;
+
+ if (mps->start1 == -1 && parse_content(mps) == -1) {
+ if (dw->stream == NULL)
+ return 0;
+ else
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
+static void
+set_stream(CamelMultipartSigned *mps, CamelStream *mem)
+{
+ CamelDataWrapper *dw = (CamelDataWrapper *)mps;
+
+ if (dw->stream)
+ camel_object_unref((CamelObject *)dw->stream);
+ dw->stream = (CamelStream *)mem;
+
+ mps->start1 = -1;
+ if (mps->content) {
+ camel_object_unref((CamelObject *)mps->content);
+ mps->content = NULL;
+ }
+ if (mps->contentraw) {
+ camel_object_unref((CamelObject *)mps->contentraw);
+ mps->contentraw = NULL;
+ }
+ if (mps->signature) {
+ camel_object_unref((CamelObject *)mps->signature);
+ mps->signature = NULL;
+ }
+}
+
+static int
+construct_from_stream(CamelDataWrapper *data_wrapper, CamelStream *stream)
+{
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
+ CamelStream *mem = camel_stream_mem_new();
+
+ if (camel_stream_write_to_stream(stream, mem) == -1)
+ return -1;
+
+ set_stream(mps, mem);
+
+ return 0;
+}
+
+static int
+signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp)
+{
+ int err;
+ struct _header_content_type *content_type;
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart;
+ char *buf;
+ unsigned int len;
+ CamelStream *mem;
+
+ /* we *must not* be in multipart state, otherwise the mime parser will
+ parse the headers which is a no no @#$@# stupid multipart/signed spec */
+ g_assert(camel_mime_parser_state(mp) == HSCAN_HEADER);
+
+ /* All we do is copy it to a memstream */
+ content_type = camel_mime_parser_content_type(mp);
+ camel_multipart_set_boundary(multipart, header_content_type_param(content_type, "boundary"));
+
+ mem = camel_stream_mem_new();
+ while (camel_mime_parser_step(mp, &buf, &len) != HSCAN_BODY_END)
+ camel_stream_write(mem, buf, len);
+
+ set_stream(mps, mem);
+
+ err = camel_mime_parser_errno(mp);
+ if (err != 0) {
+ errno = err;
+ return -1;
+ } else
+ return 0;
+}
+
+static int
+write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
+{
+ CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
+ CamelMultipart *mp = (CamelMultipart *)mps;
+ const char *boundary;
+ int count, total=0;
+
+ /* we have 3 basic cases:
+ 1. constructed, we write out the data wrapper stream we got
+ 2. signed content, we create and write out a new stream
+ 3. invalid
+ */
+
+ /* 1 */
+ /* FIXME: locking? */
+ if (data_wrapper->stream) {
+ camel_stream_reset(data_wrapper->stream);
+ return camel_stream_write_to_stream(data_wrapper->stream, stream);
+ }
+
+ /* 3 */
+ if (mps->signature == NULL || mps->contentraw == NULL)
+ return -1;
+
+ /* 2 */
+ boundary = camel_multipart_get_boundary(mp);
+ if (mp->preface) {
+ count = camel_stream_write_string(stream, mp->preface);
+ if (count == -1)
+ return -1;
+ total += count;
+ }
+
+ /* first boundary */
+ count = camel_stream_printf(stream, "\n--%s\n", boundary);
+ if (count == -1)
+ return -1;
+ total += count;
+
+ /* output content part */
+ camel_stream_reset(mps->contentraw);
+ count = camel_stream_write_to_stream(mps->contentraw, stream);
+ if (count == -1)
+ return -1;
+ total += count;
+
+ /* boundary */
+ count = camel_stream_printf(stream, "\n--%s\n", boundary);
+ if (count == -1)
+ return -1;
+ total += count;
+
+ /* signature */
+ count = camel_data_wrapper_write_to_stream((CamelDataWrapper *)mps->signature, stream);
+ if (count == -1)
+ return -1;
+ total += count;
+
+ /* write the terminating boudary delimiter */
+ count = camel_stream_printf(stream, "\n--%s--\n", boundary);
+ if (count == -1)
+ return -1;
+ total += count;
+
+ /* and finally the postface */
+ if (mp->postface) {
+ count = camel_stream_write_string(stream, mp->postface);
+ if (count == -1)
+ return -1;
+ total += count;
+ }
+
+ return total;
+}
+
+/* See rfc3156, section 2 and others */
+/* We do this simply: Anything not base64 must be qp
+ This is so that we can safely translate any occurance of "From "
+ into the quoted-printable escaped version safely. */
+static void
+prepare_sign(CamelMimePart *mime_part)
+{
+ CamelDataWrapper *wrapper;
+ CamelMimePartEncodingType encoding;
+ int parts, i;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ if (!wrapper)
+ return;
+
+ if (CAMEL_IS_MULTIPART (wrapper)) {
+ parts = camel_multipart_get_number((CamelMultipart *)wrapper);
+ for (i = 0; i < parts; i++)
+ prepare_sign(camel_multipart_get_part((CamelMultipart *)wrapper, i));
+ } else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
+ prepare_sign((CamelMimePart *)wrapper);
+ } else {
+ encoding = camel_mime_part_get_encoding(mime_part);
+
+ if (encoding != CAMEL_MIME_PART_ENCODING_BASE64
+ && encoding != CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE) {
+ camel_mime_part_set_encoding(mime_part, CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE);
+ }
+ }
+}
+
+/**
+ * camel_multipart_signed_sign:
+ * @mps:
+ * @context: The CipherContext to use for signing.
+ * @content: CamelMimePart content you wish to sign/transport.
+ * @userid: The id of the signing key to use.
+ * @hash: The algorithm to use.
+ * @ex:
+ *
+ * Sign the part @content, and attach it as the first part
+ * (CAMEL_MULTIPART_SIGNED_CONTENT) of the multipart @mps. A
+ * signature object will be created and setup as the second part
+ * (CAMEL_MULTIPART_SIGNED_SIGNATURE) of the object. Once a part has
+ * been successfully signed the mutlipart is ready for transmission.
+ *
+ * This method should be used to create multipart/signed objects
+ * which are properly canoncalised before signing, etc.
+ *
+ * Return value: -1 on error, setting @ex appropriately. On error
+ * neither the content or signature parts will be setup.
+ **/
+int
+camel_multipart_signed_sign(CamelMultipartSigned *mps, CamelCipherContext *context, CamelMimePart *content, const char *userid, CamelCipherHash hash, CamelException *ex)
+{
+ CamelMimeFilter *canon_filter;
+ CamelStream *sigstream, *mem;
+ CamelStreamFilter *filter;
+ CamelContentType *mime_type;
+ CamelMimePart *signature;
+ CamelDataWrapper *dw;
+ char *type;
+
+ /* this needs to be set */
+ g_return_val_if_fail(context->protocol != NULL, -1);
+
+ prepare_sign(content);
+
+ mem = camel_stream_mem_new();
+ filter = camel_stream_filter_new_with_stream(mem);
+
+ canon_filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM);
+ camel_stream_filter_add(filter, (CamelMimeFilter *)canon_filter);
+ camel_object_unref((CamelObject *)canon_filter);
+
+ camel_data_wrapper_write_to_stream((CamelDataWrapper *)content, (CamelStream *)filter);
+ camel_stream_flush((CamelStream *)filter);
+ camel_object_unref((CamelObject *)filter);
+ camel_stream_reset(mem);
+
+#if 0
+ printf("-- Signing:\n");
+ fwrite(((CamelStreamMem *)mem)->buffer->data, ((CamelStreamMem *)mem)->buffer->len, 1, stdout);
+ printf("-- end\n");
+#endif
+
+ sigstream = camel_stream_mem_new();
+
+ if (camel_cipher_sign(context, userid, hash, mem, sigstream, ex) == -1) {
+ camel_object_unref((CamelObject *)mem);
+ camel_object_unref((CamelObject *)sigstream);
+ return -1;
+ }
+
+ /* create the signature wrapper object */
+ signature = camel_mime_part_new();
+ dw = camel_data_wrapper_new();
+ type = alloca(strlen(context->protocol) + 32);
+ sprintf(type, "%s; name=signature.asc", context->protocol);
+ camel_data_wrapper_set_mime_type(dw, type);
+ camel_stream_reset(sigstream);
+ camel_data_wrapper_construct_from_stream(dw, sigstream);
+ camel_object_unref((CamelObject *)sigstream);
+ camel_medium_set_content_object((CamelMedium *)signature, dw);
+ camel_object_unref((CamelObject *)dw);
+ camel_mime_part_set_description(signature, _("This is a digitally signed message part"));
+
+ /* setup our mime type and boundary */
+ mime_type = header_content_type_new("multipart", "signed");
+ header_content_type_set_param(mime_type, "micalg", camel_cipher_hash_to_id(context, hash));
+ header_content_type_set_param(mime_type, "protocol", context->protocol);
+ camel_data_wrapper_set_mime_type_field(CAMEL_DATA_WRAPPER (mps), mime_type);
+ header_content_type_unref(mime_type);
+ camel_multipart_set_boundary((CamelMultipart *)mps, NULL);
+
+ /* just keep the whole raw content. We dont *really* need to do this because
+ we know how we just proccessed it, but, well, better to be safe than sorry */
+ mps->signature = signature;
+ mps->contentraw = mem;
+ camel_stream_reset(mem);
+
+ /* clear the data-wrapper stream - tells write_to_stream to use the right object */
+ if (((CamelDataWrapper *)mps)->stream) {
+ camel_object_unref((CamelObject *) ((CamelDataWrapper *)mps)->stream);
+ ((CamelDataWrapper *)mps)->stream = NULL;
+ }
+
+ return 0;
+}
+
+/**
+ * camel_multipart_signed_verify:
+ * @mps:
+ * @context:
+ * @ex:
+ *
+ * Verify a signed object. This may be used to verify newly signed
+ * objects as well as those created from external streams or parsers.
+ *
+ * Return value: A validity value, or NULL on error, setting @ex
+ * appropriately.
+ **/
+CamelCipherValidity *
+camel_multipart_signed_verify(CamelMultipartSigned *mps, CamelCipherContext *context, CamelException *ex)
+{
+ CamelCipherValidity *valid;
+ CamelMimePart *sigpart;
+ CamelStream *sigstream, *constream;
+
+ /* we need to be able to verify stuff we just signed as well as stuff we loaded from a stream/parser */
+
+ if (mps->contentraw) {
+ constream = mps->contentraw;
+ camel_object_ref((CamelObject *)constream);
+ } else {
+ CamelStream *sub;
+ CamelMimeFilter *canon_filter;
+
+ if (mps->start1 == -1 && parse_content(mps) == -1) {
+ camel_exception_setv(ex, 1, _("parse error"));
+ return NULL;
+ }
+
+ /* first, prepare our parts */
+ sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1);
+ constream = (CamelStream *)camel_stream_filter_new_with_stream(sub);
+ camel_object_unref((CamelObject *)sub);
+
+ /* Note: see rfc2015 or rfc3156, section 5 */
+ canon_filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF);
+ camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter);
+ camel_object_unref((CamelObject *)canon_filter);
+ }
+
+ /* we do this as a normal mime part so we can have it handle transfer encoding etc */
+ sigstream = camel_stream_mem_new();
+ sigpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_SIGNATURE);
+ camel_data_wrapper_write_to_stream((CamelDataWrapper *)sigpart, sigstream);
+ camel_stream_reset(sigstream);
+
+ /* do the magic, the caller must supply the right context for this kind of object */
+ valid = camel_cipher_verify(context, camel_cipher_id_to_hash(context, mps->micalg), constream, sigstream, ex);
+
+#if 0
+ {
+ CamelStream *sout = camel_stream_fs_new_with_fd(dup(0));
+
+ camel_stream_printf(sout, "-- Verifying:\n");
+ camel_stream_reset(constream);
+ camel_stream_write_to_stream(constream, sout);
+ camel_stream_printf(sout, "-- end\n");
+ camel_object_unref((CamelObject *)sout);
+ }
+#endif
+
+ camel_object_unref((CamelObject *)constream);
+ camel_object_unref((CamelObject *)sigstream);
+
+ return valid;
+}
+
+
diff --git a/camel/camel-multipart-signed.h b/camel/camel-multipart-signed.h
new file mode 100644
index 0000000000..7371e370ed
--- /dev/null
+++ b/camel/camel-multipart-signed.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * camel-signed--multipart.h : class for a signed-multipart
+ *
+ * Authors: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2002 Ximian, Inc. (www.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
+ */
+
+/* Should this be a subclass of multipart?
+ No, because we dont have different parts?
+ I'm not really sure yet ... ? */
+
+#ifndef CAMEL_MULTIPART_SIGNED_H
+#define CAMEL_MULTIPART_SIGNED_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <camel/camel-multipart.h>
+#include <camel/camel-cipher-context.h>
+
+#define CAMEL_MULTIPART_SIGNED_TYPE (camel_multipart_signed_get_type ())
+#define CAMEL_MULTIPART_SIGNED(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MULTIPART_SIGNED_TYPE, CamelMultipartSigned))
+#define CAMEL_MULTIPART_SIGNED_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_SIGNED_TYPE, CamelMultipartSignedClass))
+#define CAMEL_IS_MULTIPART_SIGNED(o) (CAMEL_CHECK_TYPE((o), CAMEL_MULTIPART_SIGNED_TYPE))
+
+/*
+enum {
+ CAMEL_MULTIPART_EMPTY,
+ CAMEL_MULTIPART_CONST,
+ CAMEL_MULTIPART_SIGN,
+ CAMEL_MULTIPART_ENCR,
+};
+*/
+
+/* 'handy' enums for getting the internal parts of the multipart */
+enum {
+ CAMEL_MULTIPART_SIGNED_CONTENT,
+ CAMEL_MULTIPART_SIGNED_SIGNATURE,
+};
+
+typedef struct _CamelMultipartSigned CamelMultipartSigned;
+
+struct _CamelMultipartSigned
+{
+ CamelMultipart parent_object;
+
+ /* these are the client visible parts, decoded forms of our data wrapper content */
+ CamelMimePart *content;
+ CamelMimePart *signature;
+
+ /* the raw content which must go over the wire, if we have generated it */
+ /* perhaps this should jsut set data_wrapper->stream and update start1/end1 accordingly, as it is done
+ for other parts, or visa versa? */
+ CamelStream *contentraw;
+
+ /*int state;*/
+
+ /* just cache some info we use */
+ char *protocol;
+ char *micalg;
+
+ /* offset pointers of start of boundary in content object */
+ off_t start1, end1;
+ off_t start2, end2;
+};
+
+typedef struct {
+ CamelMultipartClass parent_class;
+} CamelMultipartSignedClass;
+
+/* Standard Camel function */
+CamelType camel_multipart_signed_get_type (void);
+
+/* public methods */
+CamelMultipartSigned *camel_multipart_signed_new (void);
+
+int camel_multipart_signed_sign (CamelMultipartSigned *mps, CamelCipherContext *context, CamelMimePart *content, const char *uiserid, CamelCipherHash hash, CamelException *ex);
+CamelCipherValidity *camel_multipart_signed_verify (CamelMultipartSigned *mps, CamelCipherContext *context, CamelException *ex);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_MULTIPART_SIGNED_H */
+
+
diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c
index f82b66312a..f792dffaaa 100644
--- a/camel/camel-multipart.c
+++ b/camel/camel-multipart.c
@@ -1,9 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-multipart.c : Abstract class for a multipart */
-#ifndef NO_WARNINGS
-#warning This should be a mostly abstract class, but it is not!
-#endif
/*
*
@@ -34,6 +31,7 @@
#include <string.h> /* strlen() */
#include <unistd.h> /* for getpid */
#include <time.h> /* for time */
+#include <errno.h>
#include "camel-stream-mem.h"
#include "camel-multipart.h"
@@ -63,6 +61,8 @@ static int write_to_stream (CamelDataWrapper *data_wrapper,
CamelStream *stream);
static void unref_part (gpointer data, gpointer user_data);
+static int construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp);
+
static CamelDataWrapperClass *parent_class = NULL;
@@ -91,6 +91,7 @@ camel_multipart_class_init (CamelMultipartClass *camel_multipart_class)
camel_multipart_class->get_number = get_number;
camel_multipart_class->set_boundary = set_boundary;
camel_multipart_class->get_boundary = get_boundary;
+ camel_multipart_class->construct_from_parser = construct_from_parser;
/* virtual method overload */
camel_data_wrapper_class->write_to_stream = write_to_stream;
@@ -115,8 +116,8 @@ camel_multipart_finalize (CamelObject *object)
g_list_foreach (multipart->parts, unref_part, NULL);
- if (multipart->boundary)
- g_free (multipart->boundary);
+ /*if (multipart->boundary)
+ g_free (multipart->boundary);*/
if (multipart->preface)
g_free (multipart->preface);
if (multipart->postface)
@@ -539,3 +540,49 @@ camel_multipart_set_postface(CamelMultipart *multipart, const char *postface)
multipart->postface = NULL;
}
}
+
+static int
+construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp)
+{
+ int err;
+ struct _header_content_type *content_type;
+ CamelMimePart *bodypart;
+ char *buf;
+ unsigned int len;
+
+ g_assert(camel_mime_parser_state(mp) == HSCAN_MULTIPART);
+
+ /* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
+ d(printf("Creating multi-part\n"));
+
+ content_type = camel_mime_parser_content_type(mp);
+ camel_multipart_set_boundary(multipart,
+ header_content_type_param(content_type, "boundary"));
+
+ while (camel_mime_parser_step(mp, &buf, &len) != HSCAN_MULTIPART_END) {
+ camel_mime_parser_unstep(mp);
+ bodypart = camel_mime_part_new();
+ camel_mime_part_construct_from_parser(bodypart, mp);
+ camel_multipart_add_part(multipart, bodypart);
+ camel_object_unref((CamelObject *)bodypart);
+ }
+
+ /* these are only return valid data in the MULTIPART_END state */
+ camel_multipart_set_preface(multipart, camel_mime_parser_preface (mp));
+ camel_multipart_set_postface(multipart, camel_mime_parser_postface (mp));
+
+ err = camel_mime_parser_errno(mp);
+ if (err != 0) {
+ errno = err;
+ return -1;
+ } else
+ return 0;
+}
+
+int
+camel_multipart_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp)
+{
+ g_return_val_if_fail(CAMEL_IS_MULTIPART(multipart), -1);
+
+ return CMP_CLASS(multipart)->construct_from_parser(multipart, mp);
+}
diff --git a/camel/camel-multipart.h b/camel/camel-multipart.h
index dfa8908bb2..ac2e37f540 100644
--- a/camel/camel-multipart.h
+++ b/camel/camel-multipart.h
@@ -40,21 +40,17 @@ extern "C" {
#define CAMEL_MULTIPART_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_TYPE, CamelMultipartClass))
#define CAMEL_IS_MULTIPART(o) (CAMEL_CHECK_TYPE((o), CAMEL_MULTIPART_TYPE))
+struct _CamelMimeParser;
struct _CamelMultipart
{
CamelDataWrapper parent_object;
- CamelMimePart *parent;
GList *parts;
- gchar *boundary;
gchar *preface;
gchar *postface;
-
};
-
-
typedef struct {
CamelDataWrapperClass parent_class;
@@ -68,8 +64,10 @@ typedef struct {
void (*set_boundary) (CamelMultipart *multipart, const char *boundary);
const gchar * (*get_boundary) (CamelMultipart *multipart);
-} CamelMultipartClass;
+ int (*construct_from_parser)(CamelMultipart *, struct _CamelMimeParser *);
+ /*int (*construct_from_stream)(CamelMultipart *, CamelStream *);*/
+} CamelMultipartClass;
/* Standard Camel function */
CamelType camel_multipart_get_type (void);
@@ -96,6 +94,8 @@ const gchar * camel_multipart_get_boundary (CamelMultipart *multipart);
void camel_multipart_set_preface (CamelMultipart *multipart, const char *preface);
void camel_multipart_set_postface (CamelMultipart *multipart, const char *postface);
+int camel_multipart_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/camel/camel-pgp-context.c b/camel/camel-pgp-context.c
index e6ef1a7820..d1c04b831f 100644
--- a/camel/camel-pgp-context.c
+++ b/camel/camel-pgp-context.c
@@ -43,6 +43,8 @@
#include <sys/types.h>
#include <dirent.h>
+#include <ctype.h>
+
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/time.h>
@@ -51,6 +53,8 @@
#include <termios.h>
#include <unistd.h>
+#include <ctype.h>
+
#include <iconv.h>
#include <gal/unicode/gunicode.h>
#include <gal/util/e-iconv.h>
@@ -76,12 +80,19 @@ static int pgp_encrypt (CamelCipherContext *context, gboolean s
static int pgp_decrypt (CamelCipherContext *context, CamelStream *istream,
CamelStream *ostream, CamelException *ex);
+static const char *pgp_hash_to_id(CamelCipherContext *context, CamelCipherHash hash);
+static CamelCipherHash pgp_id_to_hash(CamelCipherContext *context, const char *id);
+
static CamelCipherContextClass *parent_class;
static void
camel_pgp_context_init (CamelPgpContext *context)
{
+ CamelCipherContext *ciph = (CamelCipherContext *)context;
+
context->priv = g_new0 (struct _CamelPgpContextPrivate, 1);
+
+ ciph->protocol = "application/pgp-encrypted";
}
static void
@@ -107,6 +118,8 @@ camel_pgp_context_class_init (CamelPgpContextClass *camel_pgp_context_class)
camel_cipher_context_class->verify = pgp_verify;
camel_cipher_context_class->encrypt = pgp_encrypt;
camel_cipher_context_class->decrypt = pgp_decrypt;
+ camel_cipher_context_class->hash_to_id = pgp_hash_to_id;
+ camel_cipher_context_class->id_to_hash = pgp_id_to_hash;
}
CamelType
@@ -1476,3 +1489,45 @@ pgp_decrypt (CamelCipherContext *ctx, CamelStream *istream,
return -1;
}
+
+/* this has a 1:1 relationship to CamelCipherHash */
+static char *name_table[] = {
+ "pgp-sha1", /* we use sha1 as the 'default' */
+ "pgp-md2",
+ "pgp-md5",
+ "pgp-sha1",
+ "pgp-ripemd160",
+};
+
+static const char *pgp_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
+{
+ /* if we dont know, just use default? */
+ if (hash > sizeof(name_table)/sizeof(name_table[0]))
+ hash = CAMEL_CIPHER_HASH_DEFAULT;
+
+ return name_table[hash];
+}
+
+static CamelCipherHash pgp_id_to_hash(CamelCipherContext *context, const char *id)
+{
+ int i;
+ unsigned char *tmpid, *o;
+ const char *in;
+ unsigned char c;
+
+ if (id == NULL)
+ return CAMEL_CIPHER_HASH_DEFAULT;
+
+ tmpid = alloca(strlen(id)+1);
+ in = id;
+ o = tmpid;
+ while ((c = (unsigned char)*in++))
+ *o++ = tolower(c);
+
+ for (i=1;i<sizeof(name_table)/sizeof(name_table[0]);i++) {
+ if (!strcmp(name_table[i], tmpid))
+ return i;
+ }
+
+ return CAMEL_CIPHER_HASH_DEFAULT;
+}
diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c
index c51b52b99f..42a51d3be1 100644
--- a/camel/camel-seekable-substream.c
+++ b/camel/camel-seekable-substream.c
@@ -93,7 +93,7 @@ camel_seekable_substream_get_type (void)
}
/**
- * camel_seekable_substream_new_with_seekable_stream_and_bounds:
+ * camel_seekable_substream_new:
* @parent_stream: a seekable parent stream
* @inf_bound: a lower bound
* @sup_bound: an upper bound
@@ -110,8 +110,7 @@ camel_seekable_substream_get_type (void)
* Return value: the substream
**/
CamelStream *
-camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStream *parent_stream,
- off_t start, off_t end)
+camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, off_t end)
{
CamelSeekableSubstream *seekable_substream;
diff --git a/camel/camel-seekable-substream.h b/camel/camel-seekable-substream.h
index 897342c737..b500944298 100644
--- a/camel/camel-seekable-substream.h
+++ b/camel/camel-seekable-substream.h
@@ -59,8 +59,7 @@ CamelType camel_seekable_substream_get_type (void);
/* obtain a new seekable substream */
CamelStream *
-camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStream *parent_stream,
- off_t start, off_t end);
+camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, off_t end);
#ifdef __cplusplus
}
diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c
index 9234b18988..227b2dfc2a 100644
--- a/camel/camel-smime-context.c
+++ b/camel/camel-smime-context.c
@@ -950,4 +950,52 @@ smime_decode (CamelCMSContext *ctx, CamelMimeMessage *message,
return mesg;
}
+#if 0
+
+/* Ugh, so smime context inherets from cms context, not cipher context
+ this needs to be fixed ... */
+
+/* this has a 1:1 relationship to CamelCipherHash */
+static char **name_table[] = {
+ "sha1", /* we use sha1 as the 'default' */
+ NULL,
+ "md5",
+ "sha1",
+ NULL,
+};
+
+static const char *smime_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
+{
+ /* if we dont know, just use default? */
+ if (hash > sizeof(name_table)/sizeof(name_table[0])
+ || name_table[hash] == NULL;
+ hash = CAMEL_CIPHER_HASH_DEFAULT;
+
+ return name_table[hash];
+}
+
+static CamelCipherHash smime_id_to_hash(CamelCipherContext *context, const char *id)
+{
+ int i;
+ unsigned char *tmpid, *o, *in;
+ unsigned char c;
+
+ if (id == NULL)
+ return CAMEL_CIPHER_HASH_DEFAULT;
+
+ tmpid = alloca(strlen(id)+1);
+ in = id;
+ o = tmpid;
+ while ((c = *in++))
+ *o++ = tolower(c);
+
+ for (i=1;i<sizeof(name_table)/sizeof(name_table[0]);i++) {
+ if (!strcmp(name_table[i], tmpid))
+ return i;
+ }
+
+ return CAMEL_CIPHER_HASH_DEFAULT;
+}
+#endif
+
#endif /* HAVE_NSS */
diff --git a/camel/camel-stream-filter.c b/camel/camel-stream-filter.c
index b325aea1f1..bcb572278d 100644
--- a/camel/camel-stream-filter.c
+++ b/camel/camel-stream-filter.c
@@ -25,6 +25,10 @@
#define d(x)
/*#include <stdio.h>*/
+/* use my malloc debugger? */
+/*extern void g_check(void *mp);*/
+#define g_check(x)
+
struct _filter {
struct _filter *next;
int id;
@@ -44,7 +48,7 @@ struct _CamelStreamFilterPrivate {
int last_was_read; /* was the last op read or write? */
};
-#define READ_PAD (64) /* bytes padded before buffer */
+#define READ_PAD (128) /* bytes padded before buffer */
#define READ_SIZE (4096)
#define _PRIVATE(o) (((CamelStreamFilter *)(o))->priv)
@@ -211,8 +215,10 @@ do_read (CamelStream *stream, char *buffer, size_t n)
p->last_was_read = TRUE;
+ g_check(p->realbuffer);
+
if (p->filteredlen<=0) {
- int presize = READ_SIZE;
+ int presize = READ_PAD;
size = camel_stream_read(filter->source, p->buffer, READ_SIZE);
if (size <= 0) {
@@ -224,6 +230,7 @@ do_read (CamelStream *stream, char *buffer, size_t n)
while (f) {
camel_mime_filter_complete(f->filter, p->filtered, p->filteredlen,
presize, &p->filtered, &p->filteredlen, &presize);
+ g_check(p->realbuffer);
f = f->next;
}
size = p->filteredlen;
@@ -242,6 +249,7 @@ do_read (CamelStream *stream, char *buffer, size_t n)
while (f) {
camel_mime_filter_filter(f->filter, p->filtered, p->filteredlen, presize,
&p->filtered, &p->filteredlen, &presize);
+ g_check(p->realbuffer);
d(printf ("Filtered content (%s): '",
camel_type_to_name(((CamelObject *)f->filter)->s.type)));
@@ -258,6 +266,8 @@ do_read (CamelStream *stream, char *buffer, size_t n)
p->filteredlen -= size;
p->filtered += size;
+ g_check(p->realbuffer);
+
return size;
}
@@ -280,11 +290,15 @@ do_write (CamelStream *stream, const char *buf, size_t n)
d(fwrite(buffer, sizeof(char), len, stdout));
d(printf("'\n"));
+ g_check(p->realbuffer);
+
f = p->filters;
presize = 0;
while (f) {
camel_mime_filter_filter(f->filter, buffer, len, presize, &buffer, &len, &presize);
+ g_check(p->realbuffer);
+
d(printf ("Filtered content (%s): '",
camel_type_to_name(((CamelObject *)f->filter)->s.type)));
d(fwrite(buffer, sizeof(char), len, stdout));
@@ -296,6 +310,8 @@ do_write (CamelStream *stream, const char *buf, size_t n)
if (camel_stream_write(filter->source, buffer, len) != len)
return -1;
+ g_check(p->realbuffer);
+
return n;
}
diff --git a/camel/providers/nntp/camel-nntp-stream.c b/camel/providers/nntp/camel-nntp-stream.c
index 9072a8b75a..1e2dcb23f9 100644
--- a/camel/providers/nntp/camel-nntp-stream.c
+++ b/camel/providers/nntp/camel-nntp-stream.c
@@ -457,6 +457,6 @@ int camel_nntp_stream_getd(CamelNNTPStream *is, unsigned char **start, unsigned
*start = s;
dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start));
-
return 1;
}
+
diff --git a/camel/tests/stream/test3.c b/camel/tests/stream/test3.c
index b870a7773e..f85a8ce105 100644
--- a/camel/tests/stream/test3.c
+++ b/camel/tests/stream/test3.c
@@ -50,13 +50,13 @@ int main(int argc, char **argv)
check(ss != NULL);
for (i=0;i<ARRAY_LEN(ranges);i++) {
push("stream subrange %d-%d", ranges[i].lower, ranges[i].upper);
- sus = (CamelSeekableSubstream *)camel_seekable_substream_new_with_seekable_stream_and_bounds(ss, ranges[i].lower, ranges[i].upper);
+ sus = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus != NULL);
test_seekable_substream_writepart((CamelStream *)sus, j);
test_seekable_substream_readpart((CamelStream *)sus);
- sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new_with_seekable_stream_and_bounds(ss, ranges[i].lower, ranges[i].upper);
+ sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus2 != NULL);
test_seekable_substream_readpart((CamelStream *)sus2);
@@ -79,13 +79,13 @@ int main(int argc, char **argv)
check(ss != NULL);
for (i=0;i<ARRAY_LEN(ranges);i++) {
push("stream subrange %d-%d", ranges[i].lower, ranges[i].upper);
- sus = (CamelSeekableSubstream *)camel_seekable_substream_new_with_seekable_stream_and_bounds(ss, ranges[i].lower, ranges[i].upper);
+ sus = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus != NULL);
test_seekable_substream_writepart((CamelStream *)sus, j);
test_seekable_substream_readpart((CamelStream *)sus);
- sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new_with_seekable_stream_and_bounds(ss, ranges[i].lower, ranges[i].upper);
+ sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus2 != NULL);
test_seekable_substream_readpart((CamelStream *)sus2);