summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@ximian.com>2001-09-19 08:03:57 +0000
committerJeffrey Stedfast <fejj@src.gnome.org>2001-09-19 08:03:57 +0000
commit98e7fa7bd7d827e6d49439924e49e91bbfb87b5e (patch)
tree7653cf1d65cb0d57329a4e3866a073f4f39e636a
parenta6e2e02c93f92b202e7b9cd68c4815889bef39df (diff)
downloadgmime-98e7fa7bd7d827e6d49439924e49e91bbfb87b5e.tar.gz
Copy over the filters.
2001-09-19 Jeffrey Stedfast <fejj@ximian.com> * gmime-stream-filter.c (stream_substream): Copy over the filters. * gmime-part.c (g_mime_part_verify_content_md5): Updated. (g_mime_part_set_content_md5): Updated. (g_mime_part_get_content): Updated. (write_content): Updated. * gmime-data-wrapper.c (g_mime_data_wrapper_write_to_stream): Implemented. * gmime-filter-basic.[c,h]: A basic filter that does Base64 and QP encoding/decoding. * gmime-filter-crlf.[c,h]: A simple filter that does crlf(/dot) encoding/decoding.
-rw-r--r--ChangeLog18
-rw-r--r--Makefile.am8
-rw-r--r--gmime-data-wrapper.c31
-rw-r--r--gmime-filter-basic.c180
-rw-r--r--gmime-filter-basic.h56
-rw-r--r--gmime-filter-crlf.c175
-rw-r--r--gmime-filter-crlf.h60
-rw-r--r--gmime-filter.c6
-rw-r--r--gmime-filter.h2
-rw-r--r--gmime-part.c93
-rw-r--r--gmime-stream-filter.c88
-rw-r--r--gmime-stream-filter.h2
-rw-r--r--gmime/gmime-data-wrapper.c31
-rw-r--r--gmime/gmime-filter-basic.c180
-rw-r--r--gmime/gmime-filter-basic.h56
-rw-r--r--gmime/gmime-filter-crlf.c175
-rw-r--r--gmime/gmime-filter-crlf.h60
-rw-r--r--gmime/gmime-filter.c6
-rw-r--r--gmime/gmime-filter.h2
-rw-r--r--gmime/gmime-part.c93
-rw-r--r--gmime/gmime-stream-filter.c88
-rw-r--r--gmime/gmime-stream-filter.h2
22 files changed, 1224 insertions, 188 deletions
diff --git a/ChangeLog b/ChangeLog
index 532a3c23..f9ee039d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2001-09-19 Jeffrey Stedfast <fejj@ximian.com>
+ * gmime-stream-filter.c (stream_substream): Copy over the filters.
+
+ * gmime-part.c (g_mime_part_verify_content_md5): Updated.
+ (g_mime_part_set_content_md5): Updated.
+ (g_mime_part_get_content): Updated.
+ (write_content): Updated.
+
+ * gmime-data-wrapper.c (g_mime_data_wrapper_write_to_stream):
+ Implemented.
+
+ * gmime-filter-basic.[c,h]: A basic filter that does Base64 and QP
+ encoding/decoding.
+
+ * gmime-filter-crlf.[c,h]: A simple filter that does crlf(/dot)
+ encoding/decoding.
+
+2001-09-19 Jeffrey Stedfast <fejj@ximian.com>
+
* gmime-data-wrapper.c (g_mime_data_wrapper_new_with_stream): Ref
the stream.
(g_mime_data_wrapper_set_stream): Same.
diff --git a/Makefile.am b/Makefile.am
index aa7176fd..b42f4398 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,6 +19,9 @@ libgmime_la_SOURCES = \
gmime-charset.c \
gmime-content-type.c \
gmime-data-wrapper.c \
+ gmime-filter.c \
+ gmime-filter-basic.c \
+ gmime-filter-crlf.c \
gmime-header.c \
gmime-message.c \
gmime-param.c \
@@ -26,6 +29,7 @@ libgmime_la_SOURCES = \
gmime-part.c \
gmime-stream.c \
gmime-stream-file.c \
+ gmime-stream-filter.c \
gmime-stream-fs.c \
gmime-stream-mem.c \
gmime-utils.c \
@@ -39,6 +43,9 @@ gmimeinc_HEADERS = \
gmime-charset.h \
gmime-content-type.h \
gmime-data-wrapper.h \
+ gmime-filter.h \
+ gmime-filter-basic.h \
+ gmime-filter-crlf.h \
gmime-header.h \
gmime-message.h \
gmime-param.h \
@@ -46,6 +53,7 @@ gmimeinc_HEADERS = \
gmime-part.h \
gmime-stream.h \
gmime-stream-file.h \
+ gmime-stream-filter.c \
gmime-stream-fs.h \
gmime-stream-mem.h \
gmime-utils.h \
diff --git a/gmime-data-wrapper.c b/gmime-data-wrapper.c
index 50abe035..61cc0d76 100644
--- a/gmime-data-wrapper.c
+++ b/gmime-data-wrapper.c
@@ -22,7 +22,8 @@
#include "gmime-data-wrapper.h"
-
+#include "gmime-stream-filter.h"
+#include "gmime-filter-basic.h"
/**
* g_mime_data_wrapper_new:
@@ -163,5 +164,31 @@ g_mime_data_wrapper_get_encoding (GMimeDataWrapper *wrapper)
ssize_t
g_mime_data_wrapper_write_to_stream (GMimeDataWrapper *wrapper, GMimeStream *stream)
{
- return -1;
+ GMimeStream *filtered_stream;
+ GMimeFilter *filter;
+ ssize_t written;
+
+ g_return_val_if_fail (wrapper != NULL, -1);
+ g_return_val_if_fail (wrapper->stream != NULL, -1);
+
+ filtered_stream = g_mime_stream_filter_new_with_stream (wrapper->stream);
+ switch (wrapper->encoding) {
+ case GMIME_PART_ENCODING_BASE64:
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_BASE64_DEC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
+ break;
+ case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_QP_DEC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
+ break;
+ default:
+ break;
+ }
+
+ written = g_mime_stream_write_to_stream (filtered_stream, stream);
+ g_mime_stream_unref (filtered_stream);
+
+ g_mime_stream_reset (wrapper->stream);
+
+ return written;
}
diff --git a/gmime-filter-basic.c b/gmime-filter-basic.c
new file mode 100644
index 00000000..7bbde34c
--- /dev/null
+++ b/gmime-filter-basic.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "gmime-filter-basic.h"
+#include "gmime-utils.h"
+
+static void filter_destroy (GMimeFilter *filter);
+static GMimeFilter *filter_copy (GMimeFilter *filter);
+static void filter_filter (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_complete (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_reset (GMimeFilter *filter);
+
+static GMimeFilter template = {
+ NULL, NULL, NULL, NULL,
+ 0, 0, NULL, 0, 0,
+ filter_destroy,
+ filter_copy,
+ filter_filter,
+ filter_complete,
+ filter_reset,
+};
+
+
+/**
+ * g_mime_filter_basic_new_type:
+ * @type:
+ *
+ * Returns a new basic filter of type @type.
+ **/
+GMimeFilter *
+g_mime_filter_basic_new_type (GMimeFilterBasicType type)
+{
+ GMimeFilterBasic *new;
+
+ new = g_new (GMimeFilterBasic, 1);
+
+ new->type = type;
+ new->state = 0;
+ new->save = 0;
+
+ g_mime_filter_construct (GMIME_FILTER (new), &template);
+
+ filter_reset (GMIME_FILTER (new));
+
+ return GMIME_FILTER (new);
+}
+
+
+static void
+filter_destroy (GMimeFilter *filter)
+{
+ g_free (filter);
+}
+
+static GMimeFilter *
+filter_copy (GMimeFilter *filter)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+
+ return g_mime_filter_basic_new_type (basic->type);
+}
+
+/* here we do all of the basic mime filtering */
+static void
+filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+ int newlen;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_BASE64_ENC:
+ /* wont go to more than 2x size (overly conservative) */
+ g_mime_filter_set_size (filter, len * 2 + 6, FALSE);
+ newlen = g_mime_utils_base64_encode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 2 + 6);
+ break;
+ case GMIME_FILTER_BASIC_QP_ENC:
+ /* *4 is overly conservative, but will do */
+ g_mime_filter_set_size (filter, len * 4 + 4, FALSE);
+ newlen = g_mime_utils_quoted_encode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 4 + 4);
+ break;
+ case GMIME_FILTER_BASIC_BASE64_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len + 3, FALSE);
+ newlen = g_mime_utils_base64_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len + 3);
+ break;
+ case GMIME_FILTER_BASIC_QP_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_quoted_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ }
+
+ *out = filter->outbuf;
+ *outlen = newlen;
+ *outprespace = filter->outpre;
+}
+
+static void
+filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+ int newlen;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_BASE64_ENC:
+ /* wont go to more than 2x size (overly conservative) */
+ g_mime_filter_set_size (filter, len*2+6, FALSE);
+ newlen = g_mime_utils_base64_encode_close (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 2 + 6);
+ break;
+ case GMIME_FILTER_BASIC_QP_ENC:
+ /* *4 is definetly more than needed ... */
+ g_mime_filter_set_size (filter, len * 4 + 4, FALSE);
+ newlen = g_mime_utils_quoted_encode_close (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 4 + 4);
+ break;
+ case GMIME_FILTER_BASIC_BASE64_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_base64_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ case GMIME_FILTER_BASIC_QP_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_quoted_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ }
+
+ *out = filter->outbuf;
+ *outlen = newlen;
+ *outprespace = filter->outpre;
+}
+
+/* should this 'flush' outstanding state/data bytes? */
+static void
+filter_reset (GMimeFilter *filter)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_QP_ENC:
+ basic->state = -1;
+ break;
+ default:
+ basic->state = 0;
+ }
+ basic->save = 0;
+}
diff --git a/gmime-filter-basic.h b/gmime-filter-basic.h
new file mode 100644
index 00000000..f220fd18
--- /dev/null
+++ b/gmime-filter-basic.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __G_MIME_FILTER_BASIC_H__
+#define __G_MIME_FILTER_BASIC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include "gmime-filter.h"
+
+typedef enum {
+ GMIME_FILTER_BASIC_BASE64_ENC = 1,
+ GMIME_FILTER_BASIC_BASE64_DEC,
+ GMIME_FILTER_BASIC_QP_ENC,
+ GMIME_FILTER_BASIC_QP_DEC,
+} GMimeFilterBasicType;
+
+typedef struct _GMimeFilterBasic {
+ GMimeFilter parent;
+
+ GMimeFilterBasicType type;
+
+ int state;
+ int save;
+} GMimeFilterBasic;
+
+GMimeFilter *g_mime_filter_basic_new_type (GMimeFilterBasicType type);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_FILTER_BASIC_H__ */
diff --git a/gmime-filter-crlf.c b/gmime-filter-crlf.c
new file mode 100644
index 00000000..5954ad3d
--- /dev/null
+++ b/gmime-filter-crlf.c
@@ -0,0 +1,175 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "gmime-filter-crlf.h"
+
+static void filter_destroy (GMimeFilter *filter);
+static GMimeFilter *filter_copy (GMimeFilter *filter);
+static void filter_filter (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_complete (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_reset (GMimeFilter *filter);
+
+static GMimeFilter template = {
+ NULL, NULL, NULL, NULL,
+ 0, 0, NULL, 0, 0,
+ filter_destroy,
+ filter_copy,
+ filter_filter,
+ filter_complete,
+ filter_reset,
+};
+
+
+/**
+ * g_mime_filter_crlf_new_type:
+ * @direction:
+ * @mode:
+ *
+ * Returns a new crlf(/dot) filter.
+ **/
+GMimeFilter *
+g_mime_filter_crlf_new (GMimeFilterCRLFDirection direction, GMimeFilterCRLFMode mode)
+{
+ GMimeFilterCRLF *new;
+
+ new = g_new (GMimeFilterCRLF, 1);
+
+ new->direction = direction;
+ new->mode = mode;
+ new->saw_cr = FALSE;
+ new->saw_lf = FALSE;
+ new->saw_dot = FALSE;
+
+ g_mime_filter_construct (GMIME_FILTER (new), &template);
+
+ return GMIME_FILTER (new);
+}
+
+
+static void
+filter_destroy (GMimeFilter *filter)
+{
+ g_free (filter);
+}
+
+static GMimeFilter *
+filter_copy (GMimeFilter *filter)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+
+ return g_mime_filter_crlf_new (crlf->direction, crlf->mode);
+}
+
+static void
+filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+ gboolean do_dots;
+ char *p, *q;
+
+ do_dots = crlf->mode == GMIME_FILTER_CRLF_MODE_CRLF_DOTS;
+
+ if (crlf->direction == GMIME_FILTER_CRLF_ENCODE) {
+ g_mime_filter_set_size (filter, 3 * len, FALSE);
+
+ p = in;
+ q = filter->outbuf;
+ while (p < in + len) {
+ if (*p == '\n') {
+ crlf->saw_lf = TRUE;
+ *q++ = '\r';
+ } else {
+ if (do_dots && *p == '.' && crlf->saw_lf)
+ *q++ = '.';
+
+ crlf->saw_lf = FALSE;
+ }
+
+ *q++ = *p++;
+ }
+ } else {
+ g_mime_filter_set_size (filter, len, FALSE);
+
+ p = in;
+ q = filter->outbuf;
+ while (p < in + len) {
+ if (*p == '\r') {
+ crlf->saw_cr = TRUE;
+ } else {
+ if (crlf->saw_cr) {
+ crlf->saw_cr = FALSE;
+
+ if (*p == '\n') {
+ crlf->saw_lf = TRUE;
+ *q++ = *p++;
+ continue;
+ } else
+ *q++ = '\r';
+ }
+
+ *q++ = *p;
+ }
+
+ if (do_dots && *p == '.') {
+ if (crlf->saw_lf) {
+ crlf->saw_dot = TRUE;
+ crlf->saw_lf = FALSE;
+ p++;
+ } else if (crlf->saw_dot) {
+ crlf->saw_dot = FALSE;
+ }
+ }
+
+ crlf->saw_lf = FALSE;
+
+ p++;
+ }
+ }
+
+ *out = filter->outbuf;
+ *outlen = q - filter->outbuf;
+ *outprespace = filter->outpre;
+}
+
+static void
+filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ if (in && len)
+ filter_filter (filter, in, len, prespace, out, outlen, outprespace);
+}
+
+static void
+filter_reset (GMimeFilter *filter)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+
+ crlf->saw_cr = FALSE;
+ crlf->saw_lf = TRUE;
+ crlf->saw_dot = FALSE;
+}
diff --git a/gmime-filter-crlf.h b/gmime-filter-crlf.h
new file mode 100644
index 00000000..52bcb5cc
--- /dev/null
+++ b/gmime-filter-crlf.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __G_MIME_FILTER_CRLF_H__
+#define __G_MIME_FILTER_CRLF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include "gmime-filter.h"
+
+typedef enum {
+ GMIME_FILTER_CRLF_ENCODE,
+ GMIME_FILTER_CRLF_DECODE
+} GMimeFilterCRLFDirection;
+
+typedef enum {
+ GMIME_FILTER_CRLF_MODE_CRLF_DOTS,
+ GMIME_FILTER_CRLF_MODE_CRLF_ONLY,
+} GMimeFilterCRLFMode;
+
+typedef struct _GMimeFilterCRLF {
+ GMimeFilter parent;
+
+ GMimeFilterCRLFDirection direction;
+ GMimeFilterCRLFMode mode;
+ gboolean saw_cr;
+ gboolean saw_lf;
+ gboolean saw_dot;
+} GMimeFilterCRLF;
+
+GMimeFilter *g_mime_filter_crlf_new_type (GMimeFilterCRLFDirection direction, GMimeFilterCRLFMode mode);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_FILTER_CRLF_H__ */
diff --git a/gmime-filter.c b/gmime-filter.c
index 00709db3..aaf9fa2f 100644
--- a/gmime-filter.c
+++ b/gmime-filter.c
@@ -192,10 +192,10 @@ g_mime_filter_reset (GMimeFilter *filter)
{
g_return_if_fail (filter != NULL);
- filter->reset (f);
+ filter->reset (filter);
/* could free some buffers, if they are really big? */
- f->backlen = 0;
+ filter->backlen = 0;
}
@@ -255,6 +255,6 @@ g_mime_filter_set_size (GMimeFilter *filter, size_t size, gboolean keep)
/* this could be offset from the end of the structure, but
this should be good enough */
- f->outpre = PRE_HEAD * 4;
+ filter->outpre = PRE_HEAD * 4;
}
}
diff --git a/gmime-filter.h b/gmime-filter.h
index 09bd145b..2d55922f 100644
--- a/gmime-filter.h
+++ b/gmime-filter.h
@@ -30,6 +30,7 @@ extern "C" {
#endif /* __cplusplus */
#include <glib.h>
+#include <sys/types.h>
typedef struct _GMimeFilter GMimeFilter;
@@ -62,6 +63,7 @@ struct _GMimeFilter {
void (*reset) (GMimeFilter *filter);
};
+#define GMIME_FILTER(filter) ((GMimeFilter *) filter)
void g_mime_filter_construct (GMimeFilter *filter, GMimeFilter *template);
diff --git a/gmime-part.c b/gmime-part.c
index 6b1b3dd3..c1dd7f13 100644
--- a/gmime-part.c
+++ b/gmime-part.c
@@ -31,12 +31,18 @@
#include <unistd.h>
#include <string.h>
#include <ctype.h>
+
#include "gmime-part.h"
#include "gmime-utils.h"
#include "gmime-stream-mem.h"
+#include "gmime-stream-filter.h"
+#include "gmime-filter-basic.h"
#include "md5-utils.h"
+#define NEEDS_DECODING(encoding) (((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_BASE64 || \
+ ((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_QUOTEDPRINTABLE)
+
/**
* g_mime_part_new: Create a new MIME Part object
*
@@ -235,19 +241,19 @@ g_mime_part_set_content_md5 (GMimePart *mime_part, const char *content_md5)
if (content_md5) {
mime_part->content_md5 = g_strdup (content_md5);
- } else if (mime_part->content) {
+ } else if (mime_part->content->stream) {
char digest[16], b64digest[32];
int len, state, save;
GMimeStream *stream;
GByteArray *buf;
- if (GMIME_IS_STREAM_MEM (mime_part->content->stream)) {
- stream = mime_part->content->stream;
- g_mime_stream_ref (mime_part->content->stream);
- } else {
+ stream = mime_part->content->stream;
+ if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
stream = g_mime_stream_mem_new ();
- g_mime_stream_write_to_stream (mime_part->content->stream, stream);
- g_mime_stream_reset (mime_part->content->stream);
+ g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
+ } else {
+ stream = mime_part->content->stream;
+ g_mime_stream_ref (stream);
}
buf = GMIME_STREAM_MEM (stream)->buffer;
@@ -285,15 +291,16 @@ g_mime_part_verify_content_md5 (GMimePart *mime_part)
GByteArray *buf;
g_return_val_if_fail (mime_part != NULL, FALSE);
+ g_return_val_if_fail (mime_part->content != NULL, FALSE);
g_return_val_if_fail (mime_part->content_md5 != NULL, FALSE);
- if (GMIME_IS_STREAM_MEM (mime_part->content)) {
+ stream = mime_part->content->stream;
+ if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
+ stream = g_mime_stream_mem_new ();
+ g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
+ } else {
stream = mime_part->content->stream;
g_mime_stream_ref (stream);
- } else {
- stream = g_mime_stream_mem_new ();
- g_mime_stream_write_to_stream (mime_part->content->stream, GMIME_STREAM (stream));
- g_mime_stream_reset (mime_part->content->stream);
}
buf = GMIME_STREAM_MEM (stream)->buffer;
@@ -844,9 +851,6 @@ g_mime_part_set_content_object (GMimePart *mime_part, GMimeDataWrapper *content)
}
-#define NEEDS_DECODING(encoding) (((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_BASE64 || \
- ((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_QUOTEDPRINTABLE)
-
/**
* g_mime_part_get_content:
* @mime_part: the GMimePart to be decoded.
@@ -858,6 +862,7 @@ g_mime_part_set_content_object (GMimePart *mime_part, GMimeDataWrapper *content)
const char *
g_mime_part_get_content (const GMimePart *mime_part, guint *len)
{
+ GMimeStream *stream;
GByteArray *buf;
g_return_val_if_fail (mime_part != NULL, NULL);
@@ -869,34 +874,12 @@ g_mime_part_get_content (const GMimePart *mime_part, guint *len)
if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
/* Decode and cache this mime part's contents... */
GMimeStream *cache;
- int len, save = 0, state = 0;
- char inbuf[4096], outbuf[4096];
- ssize_t nread;
buf = g_byte_array_new ();
-
- while (!g_mime_stream_eos (stream)) {
- nread = g_mime_stream_read (stream, inbuf, sizeof (inbuf));
- if (nread > 0) {
- switch (mime_part->content->encoding) {
- case GMIME_PART_ENCODING_BASE64:
- len = g_mime_utils_base64_decode_step (inbuf, nread, outbuf,
- &state, &save);
- g_byte_array_append (buf, outbuf, len);
- break;
- case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
- len = g_mime_utils_quoted_decode_step (inbuf, nread, outbuf,
- &state, &save);
- g_byte_array_append (buf, outbuf, len);
- break;
- default:
- g_byte_array_append (buf, inbuf, nread);
- }
- }
- }
-
cache = g_mime_stream_mem_new_with_byte_array (buf);
+ g_mime_data_wrapper_write_to_stream (mime_part->content, cache);
+
g_mime_data_wrapper_set_stream (mime_part->content, cache);
g_mime_data_wrapper_set_encoding (mime_part->content, GMIME_PART_ENCODING_DEFAULT);
g_mime_stream_unref (cache);
@@ -1022,38 +1005,32 @@ get_content_type (GMimeContentType *mime_type)
static void
write_content (GMimePart *part, GMimeStream *stream)
{
- const char *content;
- int save = 0, state = 0;
- char *outbuf;
- int len;
+ GMimeStream *filtered_stream;
+ GMimeFilter *filter;
+ ssize_t written;
if (!part->content || !part->content->stream)
return;
- content = g_mime_part_get_content (part, &len);
- if (!content)
- return;
-
+ filtered_stream = g_mime_stream_filter_new_with_stream (stream);
switch (part->encoding) {
case GMIME_PART_ENCODING_BASE64:
- outbuf = g_malloc (BASE64_ENCODE_LEN (len));
- len = g_mime_utils_base64_encode_close (content, len, outbuf, &state, &save);
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_BASE64_ENC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
break;
case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
- state = -1;
- outbuf = g_malloc (QP_ENCODE_LEN (len));
- len = g_mime_utils_quoted_encode_close (content, len, outbuf, &state, &save);
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_QP_ENC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
break;
default:
- outbuf = g_malloc (len);
- memcpy (outbuf, content, len);
+ break;
}
- g_warning ("write_content(): writing outbuf...%.*s", 20, outbuf);
- g_mime_stream_write (stream, outbuf, len);
- g_warning ("write_content(): done.");
+ written = g_mime_data_wrapper_write_to_stream (part->content, filtered_stream);
+ g_mime_stream_unref (filtered_stream);
- g_free (outbuf);
+ /* this is just so that I get a warning on fail... */
+ g_return_if_fail (written != -1);
}
diff --git a/gmime-stream-filter.c b/gmime-stream-filter.c
index 62bdf03e..9d4bf5f8 100644
--- a/gmime-stream-filter.c
+++ b/gmime-stream-filter.c
@@ -73,7 +73,7 @@ static void
stream_destroy (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *fn, *f;
f = p->filters;
@@ -96,7 +96,7 @@ static ssize_t
stream_read (GMimeStream *stream, char *buf, size_t len)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _CamelStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
ssize_t size;
@@ -137,7 +137,7 @@ stream_read (GMimeStream *stream, char *buf, size_t len)
}
size = MIN (len, p->filteredlen);
- memcpy (buffer, p->filtered, size);
+ memcpy (buf, p->filtered, size);
p->filteredlen -= size;
p->filtered += size;
@@ -148,7 +148,7 @@ static ssize_t
stream_write (GMimeStream *stream, char *buf, size_t len)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
char *buffer;
int presize;
@@ -162,12 +162,12 @@ stream_write (GMimeStream *stream, char *buf, size_t len)
f = p->filters;
presize = 0;
while (f) {
- g_mime_mime_filter_filter (f->filter, buffer, n, presize, &buffer, &n, &presize);
+ g_mime_filter_filter (f->filter, buffer, n, presize, &buffer, &n, &presize);
f = f->next;
}
- if (gmime_stream_write (filter->source, buffer, n) != n)
+ if (g_mime_stream_write (filter->source, buffer, n) != n)
return -1;
/* return 'len' because that's what our caller expects */
@@ -178,7 +178,7 @@ static int
stream_flush (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
int len, presize;
char *buffer;
@@ -209,7 +209,7 @@ static int
stream_close (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
if (!p->last_was_read) {
stream_flush (stream);
@@ -222,7 +222,7 @@ static gboolean
stream_eos (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
if (p->filteredlen > 0)
return FALSE;
@@ -234,7 +234,7 @@ static int
stream_reset (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
p->filteredlen = 0;
@@ -272,33 +272,56 @@ stream_length (GMimeStream *stream)
static GMimeStream *
stream_substream (GMimeStream *stream, off_t start, off_t end)
{
- GMimeStreamFilter *filter;
- struct _filters *f, *fn;
+ GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
+ GMimeStreamFilter *sub;
+ struct _filter *f, *fn;
- filter = g_new (GMimeStreamFilter, 1);
- filter->source = GMIME_STREAM_FILTER (stream)->source;
- g_mime_stream_ref (filter->source);
+ sub = g_new (GMimeStreamFilter, 1);
+ sub->source = filter->source;
+ g_mime_stream_ref (sub->source);
- filter->priv = g_new (struct _GMimeStreamFilterPrivate, 1);
- filter->priv->filters = NULL;
- filter->priv->filterid = 0;
- filter->priv->realbuffer = g_malloc (READ_SIZE + READ_PAD);
- filter->priv->buffer = filter->priv->realbuffer + READ_PAD;
- filter->priv->last_was_read = TRUE;
- filter->priv->filteredlen = 0;
+ sub->priv = g_new (struct _GMimeStreamFilterPrivate, 1);
+ sub->priv->filters = NULL;
+ sub->priv->filterid = 0;
+ sub->priv->realbuffer = g_malloc (READ_SIZE + READ_PAD);
+ sub->priv->buffer = sub->priv->realbuffer + READ_PAD;
+ sub->priv->last_was_read = TRUE;
+ sub->priv->filteredlen = 0;
- /* FIXME: copy the filters... */
+ if (filter->priv->filters) {
+ struct _filter *f, *sn, *s = NULL;
+
+ f = filter->priv->filters;
+ while (f) {
+ sn = g_new (struct _filter, 1);
+ sn->filter = g_mime_filter_copy (f->filter);
+ sn->id = f->id;
+
+ if (s) {
+ s->next = sn;
+ s = sn;
+ } else {
+ s = sub->priv->filters = sn;
+ }
+
+ f = f->next;
+ }
+
+ s->next = NULL;
+
+ sub->priv->filterid = filter->priv->filterid;
+ }
g_mime_stream_construct (GMIME_STREAM (filter), &template,
GMIME_STREAM_FILTER_TYPE,
- filter->source->bound_start,
- filter->source->bound_end);
+ sub->source->bound_start,
+ sub->source->bound_end);
- return GMIME_STREAM (filter);
+ return GMIME_STREAM (sub);
}
-GMimeStreamFilter *
+GMimeStream *
g_mime_stream_filter_new_with_stream (GMimeStream *stream)
{
GMimeStreamFilter *filter;
@@ -329,11 +352,14 @@ g_mime_stream_filter_new_with_stream (GMimeStream *stream)
int
g_mime_stream_filter_add (GMimeStreamFilter *fstream, GMimeFilter *filter)
{
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (fstream);
+ struct _GMimeStreamFilterPrivate *p;
struct _filter *f, *fn;
+ g_return_val_if_fail (fstream != NULL, -1);
g_return_val_if_fail (filter != NULL, -1);
+ p = fstream->priv;
+
fn = g_new (struct _filter, 1);
fn->next = NULL;
fn->filter = filter;
@@ -353,10 +379,12 @@ g_mime_stream_filter_add (GMimeStreamFilter *fstream, GMimeFilter *filter)
void
g_mime_stream_filter_remove (GMimeStreamFilter *fstream, int id)
{
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (fstream);
+ struct _GMimeStreamFilterPrivate *p;
struct _filter *f, *fn;
- g_return_val_if_fail (filter != NULL, -1);
+ g_return_if_fail (fstream != NULL);
+
+ p = fstream->priv;
if (id == -1)
return;
diff --git a/gmime-stream-filter.h b/gmime-stream-filter.h
index c30f07f4..93da9931 100644
--- a/gmime-stream-filter.h
+++ b/gmime-stream-filter.h
@@ -42,7 +42,7 @@ typedef struct _GMimeStreamFilter {
#define GMIME_STREAM_FILTER_TYPE g_str_hash ("GMimeStreamFilter")
#define GMIME_IS_STREAM_FILTER(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILTER_TYPE)
-#define GMIME_STREAM_FILTER(stream) ((GMimeStreamMem *) stream)
+#define GMIME_STREAM_FILTER(stream) ((GMimeStreamFilter *) stream)
GMimeStream *g_mime_stream_filter_new_with_stream (GMimeStream *stream);
diff --git a/gmime/gmime-data-wrapper.c b/gmime/gmime-data-wrapper.c
index 50abe035..61cc0d76 100644
--- a/gmime/gmime-data-wrapper.c
+++ b/gmime/gmime-data-wrapper.c
@@ -22,7 +22,8 @@
#include "gmime-data-wrapper.h"
-
+#include "gmime-stream-filter.h"
+#include "gmime-filter-basic.h"
/**
* g_mime_data_wrapper_new:
@@ -163,5 +164,31 @@ g_mime_data_wrapper_get_encoding (GMimeDataWrapper *wrapper)
ssize_t
g_mime_data_wrapper_write_to_stream (GMimeDataWrapper *wrapper, GMimeStream *stream)
{
- return -1;
+ GMimeStream *filtered_stream;
+ GMimeFilter *filter;
+ ssize_t written;
+
+ g_return_val_if_fail (wrapper != NULL, -1);
+ g_return_val_if_fail (wrapper->stream != NULL, -1);
+
+ filtered_stream = g_mime_stream_filter_new_with_stream (wrapper->stream);
+ switch (wrapper->encoding) {
+ case GMIME_PART_ENCODING_BASE64:
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_BASE64_DEC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
+ break;
+ case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_QP_DEC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
+ break;
+ default:
+ break;
+ }
+
+ written = g_mime_stream_write_to_stream (filtered_stream, stream);
+ g_mime_stream_unref (filtered_stream);
+
+ g_mime_stream_reset (wrapper->stream);
+
+ return written;
}
diff --git a/gmime/gmime-filter-basic.c b/gmime/gmime-filter-basic.c
new file mode 100644
index 00000000..7bbde34c
--- /dev/null
+++ b/gmime/gmime-filter-basic.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "gmime-filter-basic.h"
+#include "gmime-utils.h"
+
+static void filter_destroy (GMimeFilter *filter);
+static GMimeFilter *filter_copy (GMimeFilter *filter);
+static void filter_filter (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_complete (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_reset (GMimeFilter *filter);
+
+static GMimeFilter template = {
+ NULL, NULL, NULL, NULL,
+ 0, 0, NULL, 0, 0,
+ filter_destroy,
+ filter_copy,
+ filter_filter,
+ filter_complete,
+ filter_reset,
+};
+
+
+/**
+ * g_mime_filter_basic_new_type:
+ * @type:
+ *
+ * Returns a new basic filter of type @type.
+ **/
+GMimeFilter *
+g_mime_filter_basic_new_type (GMimeFilterBasicType type)
+{
+ GMimeFilterBasic *new;
+
+ new = g_new (GMimeFilterBasic, 1);
+
+ new->type = type;
+ new->state = 0;
+ new->save = 0;
+
+ g_mime_filter_construct (GMIME_FILTER (new), &template);
+
+ filter_reset (GMIME_FILTER (new));
+
+ return GMIME_FILTER (new);
+}
+
+
+static void
+filter_destroy (GMimeFilter *filter)
+{
+ g_free (filter);
+}
+
+static GMimeFilter *
+filter_copy (GMimeFilter *filter)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+
+ return g_mime_filter_basic_new_type (basic->type);
+}
+
+/* here we do all of the basic mime filtering */
+static void
+filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+ int newlen;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_BASE64_ENC:
+ /* wont go to more than 2x size (overly conservative) */
+ g_mime_filter_set_size (filter, len * 2 + 6, FALSE);
+ newlen = g_mime_utils_base64_encode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 2 + 6);
+ break;
+ case GMIME_FILTER_BASIC_QP_ENC:
+ /* *4 is overly conservative, but will do */
+ g_mime_filter_set_size (filter, len * 4 + 4, FALSE);
+ newlen = g_mime_utils_quoted_encode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 4 + 4);
+ break;
+ case GMIME_FILTER_BASIC_BASE64_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len + 3, FALSE);
+ newlen = g_mime_utils_base64_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len + 3);
+ break;
+ case GMIME_FILTER_BASIC_QP_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_quoted_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ }
+
+ *out = filter->outbuf;
+ *outlen = newlen;
+ *outprespace = filter->outpre;
+}
+
+static void
+filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+ int newlen;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_BASE64_ENC:
+ /* wont go to more than 2x size (overly conservative) */
+ g_mime_filter_set_size (filter, len*2+6, FALSE);
+ newlen = g_mime_utils_base64_encode_close (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 2 + 6);
+ break;
+ case GMIME_FILTER_BASIC_QP_ENC:
+ /* *4 is definetly more than needed ... */
+ g_mime_filter_set_size (filter, len * 4 + 4, FALSE);
+ newlen = g_mime_utils_quoted_encode_close (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len * 4 + 4);
+ break;
+ case GMIME_FILTER_BASIC_BASE64_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_base64_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ case GMIME_FILTER_BASIC_QP_DEC:
+ /* output can't possibly exceed the input size */
+ g_mime_filter_set_size (filter, len, FALSE);
+ newlen = g_mime_utils_quoted_decode_step (in, len, filter->outbuf, &basic->state, &basic->save);
+ g_assert (newlen <= len);
+ break;
+ }
+
+ *out = filter->outbuf;
+ *outlen = newlen;
+ *outprespace = filter->outpre;
+}
+
+/* should this 'flush' outstanding state/data bytes? */
+static void
+filter_reset (GMimeFilter *filter)
+{
+ GMimeFilterBasic *basic = (GMimeFilterBasic *) filter;
+
+ switch (basic->type) {
+ case GMIME_FILTER_BASIC_QP_ENC:
+ basic->state = -1;
+ break;
+ default:
+ basic->state = 0;
+ }
+ basic->save = 0;
+}
diff --git a/gmime/gmime-filter-basic.h b/gmime/gmime-filter-basic.h
new file mode 100644
index 00000000..f220fd18
--- /dev/null
+++ b/gmime/gmime-filter-basic.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __G_MIME_FILTER_BASIC_H__
+#define __G_MIME_FILTER_BASIC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include "gmime-filter.h"
+
+typedef enum {
+ GMIME_FILTER_BASIC_BASE64_ENC = 1,
+ GMIME_FILTER_BASIC_BASE64_DEC,
+ GMIME_FILTER_BASIC_QP_ENC,
+ GMIME_FILTER_BASIC_QP_DEC,
+} GMimeFilterBasicType;
+
+typedef struct _GMimeFilterBasic {
+ GMimeFilter parent;
+
+ GMimeFilterBasicType type;
+
+ int state;
+ int save;
+} GMimeFilterBasic;
+
+GMimeFilter *g_mime_filter_basic_new_type (GMimeFilterBasicType type);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_FILTER_BASIC_H__ */
diff --git a/gmime/gmime-filter-crlf.c b/gmime/gmime-filter-crlf.c
new file mode 100644
index 00000000..5954ad3d
--- /dev/null
+++ b/gmime/gmime-filter-crlf.c
@@ -0,0 +1,175 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "gmime-filter-crlf.h"
+
+static void filter_destroy (GMimeFilter *filter);
+static GMimeFilter *filter_copy (GMimeFilter *filter);
+static void filter_filter (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_complete (GMimeFilter *filter, char *in, size_t len,
+ size_t prespace, char **out,
+ size_t *outlen, size_t *outprespace);
+static void filter_reset (GMimeFilter *filter);
+
+static GMimeFilter template = {
+ NULL, NULL, NULL, NULL,
+ 0, 0, NULL, 0, 0,
+ filter_destroy,
+ filter_copy,
+ filter_filter,
+ filter_complete,
+ filter_reset,
+};
+
+
+/**
+ * g_mime_filter_crlf_new_type:
+ * @direction:
+ * @mode:
+ *
+ * Returns a new crlf(/dot) filter.
+ **/
+GMimeFilter *
+g_mime_filter_crlf_new (GMimeFilterCRLFDirection direction, GMimeFilterCRLFMode mode)
+{
+ GMimeFilterCRLF *new;
+
+ new = g_new (GMimeFilterCRLF, 1);
+
+ new->direction = direction;
+ new->mode = mode;
+ new->saw_cr = FALSE;
+ new->saw_lf = FALSE;
+ new->saw_dot = FALSE;
+
+ g_mime_filter_construct (GMIME_FILTER (new), &template);
+
+ return GMIME_FILTER (new);
+}
+
+
+static void
+filter_destroy (GMimeFilter *filter)
+{
+ g_free (filter);
+}
+
+static GMimeFilter *
+filter_copy (GMimeFilter *filter)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+
+ return g_mime_filter_crlf_new (crlf->direction, crlf->mode);
+}
+
+static void
+filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+ gboolean do_dots;
+ char *p, *q;
+
+ do_dots = crlf->mode == GMIME_FILTER_CRLF_MODE_CRLF_DOTS;
+
+ if (crlf->direction == GMIME_FILTER_CRLF_ENCODE) {
+ g_mime_filter_set_size (filter, 3 * len, FALSE);
+
+ p = in;
+ q = filter->outbuf;
+ while (p < in + len) {
+ if (*p == '\n') {
+ crlf->saw_lf = TRUE;
+ *q++ = '\r';
+ } else {
+ if (do_dots && *p == '.' && crlf->saw_lf)
+ *q++ = '.';
+
+ crlf->saw_lf = FALSE;
+ }
+
+ *q++ = *p++;
+ }
+ } else {
+ g_mime_filter_set_size (filter, len, FALSE);
+
+ p = in;
+ q = filter->outbuf;
+ while (p < in + len) {
+ if (*p == '\r') {
+ crlf->saw_cr = TRUE;
+ } else {
+ if (crlf->saw_cr) {
+ crlf->saw_cr = FALSE;
+
+ if (*p == '\n') {
+ crlf->saw_lf = TRUE;
+ *q++ = *p++;
+ continue;
+ } else
+ *q++ = '\r';
+ }
+
+ *q++ = *p;
+ }
+
+ if (do_dots && *p == '.') {
+ if (crlf->saw_lf) {
+ crlf->saw_dot = TRUE;
+ crlf->saw_lf = FALSE;
+ p++;
+ } else if (crlf->saw_dot) {
+ crlf->saw_dot = FALSE;
+ }
+ }
+
+ crlf->saw_lf = FALSE;
+
+ p++;
+ }
+ }
+
+ *out = filter->outbuf;
+ *outlen = q - filter->outbuf;
+ *outprespace = filter->outpre;
+}
+
+static void
+filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace)
+{
+ if (in && len)
+ filter_filter (filter, in, len, prespace, out, outlen, outprespace);
+}
+
+static void
+filter_reset (GMimeFilter *filter)
+{
+ GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter;
+
+ crlf->saw_cr = FALSE;
+ crlf->saw_lf = TRUE;
+ crlf->saw_dot = FALSE;
+}
diff --git a/gmime/gmime-filter-crlf.h b/gmime/gmime-filter-crlf.h
new file mode 100644
index 00000000..52bcb5cc
--- /dev/null
+++ b/gmime/gmime-filter-crlf.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __G_MIME_FILTER_CRLF_H__
+#define __G_MIME_FILTER_CRLF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include "gmime-filter.h"
+
+typedef enum {
+ GMIME_FILTER_CRLF_ENCODE,
+ GMIME_FILTER_CRLF_DECODE
+} GMimeFilterCRLFDirection;
+
+typedef enum {
+ GMIME_FILTER_CRLF_MODE_CRLF_DOTS,
+ GMIME_FILTER_CRLF_MODE_CRLF_ONLY,
+} GMimeFilterCRLFMode;
+
+typedef struct _GMimeFilterCRLF {
+ GMimeFilter parent;
+
+ GMimeFilterCRLFDirection direction;
+ GMimeFilterCRLFMode mode;
+ gboolean saw_cr;
+ gboolean saw_lf;
+ gboolean saw_dot;
+} GMimeFilterCRLF;
+
+GMimeFilter *g_mime_filter_crlf_new_type (GMimeFilterCRLFDirection direction, GMimeFilterCRLFMode mode);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_FILTER_CRLF_H__ */
diff --git a/gmime/gmime-filter.c b/gmime/gmime-filter.c
index 00709db3..aaf9fa2f 100644
--- a/gmime/gmime-filter.c
+++ b/gmime/gmime-filter.c
@@ -192,10 +192,10 @@ g_mime_filter_reset (GMimeFilter *filter)
{
g_return_if_fail (filter != NULL);
- filter->reset (f);
+ filter->reset (filter);
/* could free some buffers, if they are really big? */
- f->backlen = 0;
+ filter->backlen = 0;
}
@@ -255,6 +255,6 @@ g_mime_filter_set_size (GMimeFilter *filter, size_t size, gboolean keep)
/* this could be offset from the end of the structure, but
this should be good enough */
- f->outpre = PRE_HEAD * 4;
+ filter->outpre = PRE_HEAD * 4;
}
}
diff --git a/gmime/gmime-filter.h b/gmime/gmime-filter.h
index 09bd145b..2d55922f 100644
--- a/gmime/gmime-filter.h
+++ b/gmime/gmime-filter.h
@@ -30,6 +30,7 @@ extern "C" {
#endif /* __cplusplus */
#include <glib.h>
+#include <sys/types.h>
typedef struct _GMimeFilter GMimeFilter;
@@ -62,6 +63,7 @@ struct _GMimeFilter {
void (*reset) (GMimeFilter *filter);
};
+#define GMIME_FILTER(filter) ((GMimeFilter *) filter)
void g_mime_filter_construct (GMimeFilter *filter, GMimeFilter *template);
diff --git a/gmime/gmime-part.c b/gmime/gmime-part.c
index 6b1b3dd3..c1dd7f13 100644
--- a/gmime/gmime-part.c
+++ b/gmime/gmime-part.c
@@ -31,12 +31,18 @@
#include <unistd.h>
#include <string.h>
#include <ctype.h>
+
#include "gmime-part.h"
#include "gmime-utils.h"
#include "gmime-stream-mem.h"
+#include "gmime-stream-filter.h"
+#include "gmime-filter-basic.h"
#include "md5-utils.h"
+#define NEEDS_DECODING(encoding) (((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_BASE64 || \
+ ((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_QUOTEDPRINTABLE)
+
/**
* g_mime_part_new: Create a new MIME Part object
*
@@ -235,19 +241,19 @@ g_mime_part_set_content_md5 (GMimePart *mime_part, const char *content_md5)
if (content_md5) {
mime_part->content_md5 = g_strdup (content_md5);
- } else if (mime_part->content) {
+ } else if (mime_part->content->stream) {
char digest[16], b64digest[32];
int len, state, save;
GMimeStream *stream;
GByteArray *buf;
- if (GMIME_IS_STREAM_MEM (mime_part->content->stream)) {
- stream = mime_part->content->stream;
- g_mime_stream_ref (mime_part->content->stream);
- } else {
+ stream = mime_part->content->stream;
+ if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
stream = g_mime_stream_mem_new ();
- g_mime_stream_write_to_stream (mime_part->content->stream, stream);
- g_mime_stream_reset (mime_part->content->stream);
+ g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
+ } else {
+ stream = mime_part->content->stream;
+ g_mime_stream_ref (stream);
}
buf = GMIME_STREAM_MEM (stream)->buffer;
@@ -285,15 +291,16 @@ g_mime_part_verify_content_md5 (GMimePart *mime_part)
GByteArray *buf;
g_return_val_if_fail (mime_part != NULL, FALSE);
+ g_return_val_if_fail (mime_part->content != NULL, FALSE);
g_return_val_if_fail (mime_part->content_md5 != NULL, FALSE);
- if (GMIME_IS_STREAM_MEM (mime_part->content)) {
+ stream = mime_part->content->stream;
+ if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
+ stream = g_mime_stream_mem_new ();
+ g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
+ } else {
stream = mime_part->content->stream;
g_mime_stream_ref (stream);
- } else {
- stream = g_mime_stream_mem_new ();
- g_mime_stream_write_to_stream (mime_part->content->stream, GMIME_STREAM (stream));
- g_mime_stream_reset (mime_part->content->stream);
}
buf = GMIME_STREAM_MEM (stream)->buffer;
@@ -844,9 +851,6 @@ g_mime_part_set_content_object (GMimePart *mime_part, GMimeDataWrapper *content)
}
-#define NEEDS_DECODING(encoding) (((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_BASE64 || \
- ((GMimePartEncodingType) encoding) == GMIME_PART_ENCODING_QUOTEDPRINTABLE)
-
/**
* g_mime_part_get_content:
* @mime_part: the GMimePart to be decoded.
@@ -858,6 +862,7 @@ g_mime_part_set_content_object (GMimePart *mime_part, GMimeDataWrapper *content)
const char *
g_mime_part_get_content (const GMimePart *mime_part, guint *len)
{
+ GMimeStream *stream;
GByteArray *buf;
g_return_val_if_fail (mime_part != NULL, NULL);
@@ -869,34 +874,12 @@ g_mime_part_get_content (const GMimePart *mime_part, guint *len)
if (stream && (!GMIME_IS_STREAM_MEM (stream) || NEEDS_DECODING (mime_part->content->encoding))) {
/* Decode and cache this mime part's contents... */
GMimeStream *cache;
- int len, save = 0, state = 0;
- char inbuf[4096], outbuf[4096];
- ssize_t nread;
buf = g_byte_array_new ();
-
- while (!g_mime_stream_eos (stream)) {
- nread = g_mime_stream_read (stream, inbuf, sizeof (inbuf));
- if (nread > 0) {
- switch (mime_part->content->encoding) {
- case GMIME_PART_ENCODING_BASE64:
- len = g_mime_utils_base64_decode_step (inbuf, nread, outbuf,
- &state, &save);
- g_byte_array_append (buf, outbuf, len);
- break;
- case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
- len = g_mime_utils_quoted_decode_step (inbuf, nread, outbuf,
- &state, &save);
- g_byte_array_append (buf, outbuf, len);
- break;
- default:
- g_byte_array_append (buf, inbuf, nread);
- }
- }
- }
-
cache = g_mime_stream_mem_new_with_byte_array (buf);
+ g_mime_data_wrapper_write_to_stream (mime_part->content, cache);
+
g_mime_data_wrapper_set_stream (mime_part->content, cache);
g_mime_data_wrapper_set_encoding (mime_part->content, GMIME_PART_ENCODING_DEFAULT);
g_mime_stream_unref (cache);
@@ -1022,38 +1005,32 @@ get_content_type (GMimeContentType *mime_type)
static void
write_content (GMimePart *part, GMimeStream *stream)
{
- const char *content;
- int save = 0, state = 0;
- char *outbuf;
- int len;
+ GMimeStream *filtered_stream;
+ GMimeFilter *filter;
+ ssize_t written;
if (!part->content || !part->content->stream)
return;
- content = g_mime_part_get_content (part, &len);
- if (!content)
- return;
-
+ filtered_stream = g_mime_stream_filter_new_with_stream (stream);
switch (part->encoding) {
case GMIME_PART_ENCODING_BASE64:
- outbuf = g_malloc (BASE64_ENCODE_LEN (len));
- len = g_mime_utils_base64_encode_close (content, len, outbuf, &state, &save);
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_BASE64_ENC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
break;
case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
- state = -1;
- outbuf = g_malloc (QP_ENCODE_LEN (len));
- len = g_mime_utils_quoted_encode_close (content, len, outbuf, &state, &save);
+ filter = g_mime_filter_basic_new_type (GMIME_FILTER_BASIC_QP_ENC);
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
break;
default:
- outbuf = g_malloc (len);
- memcpy (outbuf, content, len);
+ break;
}
- g_warning ("write_content(): writing outbuf...%.*s", 20, outbuf);
- g_mime_stream_write (stream, outbuf, len);
- g_warning ("write_content(): done.");
+ written = g_mime_data_wrapper_write_to_stream (part->content, filtered_stream);
+ g_mime_stream_unref (filtered_stream);
- g_free (outbuf);
+ /* this is just so that I get a warning on fail... */
+ g_return_if_fail (written != -1);
}
diff --git a/gmime/gmime-stream-filter.c b/gmime/gmime-stream-filter.c
index 62bdf03e..9d4bf5f8 100644
--- a/gmime/gmime-stream-filter.c
+++ b/gmime/gmime-stream-filter.c
@@ -73,7 +73,7 @@ static void
stream_destroy (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *fn, *f;
f = p->filters;
@@ -96,7 +96,7 @@ static ssize_t
stream_read (GMimeStream *stream, char *buf, size_t len)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _CamelStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
ssize_t size;
@@ -137,7 +137,7 @@ stream_read (GMimeStream *stream, char *buf, size_t len)
}
size = MIN (len, p->filteredlen);
- memcpy (buffer, p->filtered, size);
+ memcpy (buf, p->filtered, size);
p->filteredlen -= size;
p->filtered += size;
@@ -148,7 +148,7 @@ static ssize_t
stream_write (GMimeStream *stream, char *buf, size_t len)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
char *buffer;
int presize;
@@ -162,12 +162,12 @@ stream_write (GMimeStream *stream, char *buf, size_t len)
f = p->filters;
presize = 0;
while (f) {
- g_mime_mime_filter_filter (f->filter, buffer, n, presize, &buffer, &n, &presize);
+ g_mime_filter_filter (f->filter, buffer, n, presize, &buffer, &n, &presize);
f = f->next;
}
- if (gmime_stream_write (filter->source, buffer, n) != n)
+ if (g_mime_stream_write (filter->source, buffer, n) != n)
return -1;
/* return 'len' because that's what our caller expects */
@@ -178,7 +178,7 @@ static int
stream_flush (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
int len, presize;
char *buffer;
@@ -209,7 +209,7 @@ static int
stream_close (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
if (!p->last_was_read) {
stream_flush (stream);
@@ -222,7 +222,7 @@ static gboolean
stream_eos (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
if (p->filteredlen > 0)
return FALSE;
@@ -234,7 +234,7 @@ static int
stream_reset (GMimeStream *stream)
{
GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (filter);
+ struct _GMimeStreamFilterPrivate *p = filter->priv;
struct _filter *f;
p->filteredlen = 0;
@@ -272,33 +272,56 @@ stream_length (GMimeStream *stream)
static GMimeStream *
stream_substream (GMimeStream *stream, off_t start, off_t end)
{
- GMimeStreamFilter *filter;
- struct _filters *f, *fn;
+ GMimeStreamFilter *filter = (GMimeStreamFilter *) stream;
+ GMimeStreamFilter *sub;
+ struct _filter *f, *fn;
- filter = g_new (GMimeStreamFilter, 1);
- filter->source = GMIME_STREAM_FILTER (stream)->source;
- g_mime_stream_ref (filter->source);
+ sub = g_new (GMimeStreamFilter, 1);
+ sub->source = filter->source;
+ g_mime_stream_ref (sub->source);
- filter->priv = g_new (struct _GMimeStreamFilterPrivate, 1);
- filter->priv->filters = NULL;
- filter->priv->filterid = 0;
- filter->priv->realbuffer = g_malloc (READ_SIZE + READ_PAD);
- filter->priv->buffer = filter->priv->realbuffer + READ_PAD;
- filter->priv->last_was_read = TRUE;
- filter->priv->filteredlen = 0;
+ sub->priv = g_new (struct _GMimeStreamFilterPrivate, 1);
+ sub->priv->filters = NULL;
+ sub->priv->filterid = 0;
+ sub->priv->realbuffer = g_malloc (READ_SIZE + READ_PAD);
+ sub->priv->buffer = sub->priv->realbuffer + READ_PAD;
+ sub->priv->last_was_read = TRUE;
+ sub->priv->filteredlen = 0;
- /* FIXME: copy the filters... */
+ if (filter->priv->filters) {
+ struct _filter *f, *sn, *s = NULL;
+
+ f = filter->priv->filters;
+ while (f) {
+ sn = g_new (struct _filter, 1);
+ sn->filter = g_mime_filter_copy (f->filter);
+ sn->id = f->id;
+
+ if (s) {
+ s->next = sn;
+ s = sn;
+ } else {
+ s = sub->priv->filters = sn;
+ }
+
+ f = f->next;
+ }
+
+ s->next = NULL;
+
+ sub->priv->filterid = filter->priv->filterid;
+ }
g_mime_stream_construct (GMIME_STREAM (filter), &template,
GMIME_STREAM_FILTER_TYPE,
- filter->source->bound_start,
- filter->source->bound_end);
+ sub->source->bound_start,
+ sub->source->bound_end);
- return GMIME_STREAM (filter);
+ return GMIME_STREAM (sub);
}
-GMimeStreamFilter *
+GMimeStream *
g_mime_stream_filter_new_with_stream (GMimeStream *stream)
{
GMimeStreamFilter *filter;
@@ -329,11 +352,14 @@ g_mime_stream_filter_new_with_stream (GMimeStream *stream)
int
g_mime_stream_filter_add (GMimeStreamFilter *fstream, GMimeFilter *filter)
{
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (fstream);
+ struct _GMimeStreamFilterPrivate *p;
struct _filter *f, *fn;
+ g_return_val_if_fail (fstream != NULL, -1);
g_return_val_if_fail (filter != NULL, -1);
+ p = fstream->priv;
+
fn = g_new (struct _filter, 1);
fn->next = NULL;
fn->filter = filter;
@@ -353,10 +379,12 @@ g_mime_stream_filter_add (GMimeStreamFilter *fstream, GMimeFilter *filter)
void
g_mime_stream_filter_remove (GMimeStreamFilter *fstream, int id)
{
- struct _GMimeStreamFilterPrivate *p = _PRIVATE (fstream);
+ struct _GMimeStreamFilterPrivate *p;
struct _filter *f, *fn;
- g_return_val_if_fail (filter != NULL, -1);
+ g_return_if_fail (fstream != NULL);
+
+ p = fstream->priv;
if (id == -1)
return;
diff --git a/gmime/gmime-stream-filter.h b/gmime/gmime-stream-filter.h
index c30f07f4..93da9931 100644
--- a/gmime/gmime-stream-filter.h
+++ b/gmime/gmime-stream-filter.h
@@ -42,7 +42,7 @@ typedef struct _GMimeStreamFilter {
#define GMIME_STREAM_FILTER_TYPE g_str_hash ("GMimeStreamFilter")
#define GMIME_IS_STREAM_FILTER(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILTER_TYPE)
-#define GMIME_STREAM_FILTER(stream) ((GMimeStreamMem *) stream)
+#define GMIME_STREAM_FILTER(stream) ((GMimeStreamFilter *) stream)
GMimeStream *g_mime_stream_filter_new_with_stream (GMimeStream *stream);