summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@ximian.com>2001-09-17 05:42:00 +0000
committerJeffrey Stedfast <fejj@src.gnome.org>2001-09-17 05:42:00 +0000
commit49b708d32b2d05fde967fdc9d3ee68d36f91ce5e (patch)
tree5998431fe3cb65de7bdaa33a1e0204e333a7bf7d
parent54064169b6c139cd8d0f548b98261542bb0b6922 (diff)
downloadgmime-49b708d32b2d05fde967fdc9d3ee68d36f91ce5e.tar.gz
Abstract stream class.
2001-09-17 Jeffrey Stedfast <fejj@ximian.com> * gmime-stream.[c,h]: Abstract stream class. * gmime-stream-mem.[c,h]: Memory stream. * gmime-stream-file.[c,h]: File stream. * gmime-data-wrapper.[c,h]: Data wrapper class. Will be used as the content object in MIME parts.
-rw-r--r--ChangeLog11
-rw-r--r--gmime-data-wrapper.c75
-rw-r--r--gmime-data-wrapper.h62
-rw-r--r--gmime-stream-file.c246
-rw-r--r--gmime-stream-file.h53
-rw-r--r--gmime-stream-mem.c286
-rw-r--r--gmime-stream-mem.h56
-rw-r--r--gmime-stream.c328
-rw-r--r--gmime-stream.h94
-rw-r--r--gmime/gmime-data-wrapper.c75
-rw-r--r--gmime/gmime-data-wrapper.h62
-rw-r--r--gmime/gmime-stream-file.c246
-rw-r--r--gmime/gmime-stream-file.h53
-rw-r--r--gmime/gmime-stream-mem.c286
-rw-r--r--gmime/gmime-stream-mem.h56
-rw-r--r--gmime/gmime-stream.c328
-rw-r--r--gmime/gmime-stream.h94
17 files changed, 2411 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index fe0dbf82..cc9c055f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2001-09-17 Jeffrey Stedfast <fejj@ximian.com>
+
+ * gmime-stream.[c,h]: Abstract stream class.
+
+ * gmime-stream-mem.[c,h]: Memory stream.
+
+ * gmime-stream-file.[c,h]: File stream.
+
+ * gmime-data-wrapper.[c,h]: Data wrapper class. Will be used as
+ the content object in MIME parts.
+
2001-08-23 Jeffrey Stedfast <fejj@ximian.com>
* gmime-utils.c (encode_8bit_word): Oops. Add the closing ? char.
diff --git a/gmime-data-wrapper.c b/gmime-data-wrapper.c
new file mode 100644
index 00000000..493803b0
--- /dev/null
+++ b/gmime-data-wrapper.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-data-wrapper.h"
+
+
+GMimeDataWrapper *
+g_mime_data_wrapper_new (void)
+{
+ return g_new0 (GMimeDataWrapper, 1);
+}
+
+
+GMimeDataWrapper *
+g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding)
+{
+ GMimeDataWrapper *wrapper;
+
+ wrapper = g_new (GMimeDataWrapper, 1);
+ wrapper->encoding = encoding;
+ wrapper->stream = stream;
+
+ return wrapper;
+}
+
+
+void
+g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper)
+{
+ if (wrapper) {
+ if (wrapper->stream)
+ g_mime_stream_unref (wrapper->stream);
+ g_free (wrapper);
+ }
+}
+
+
+void
+g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream)
+{
+ g_return_if_fail (wrapper != NULL);
+
+ if (wrapper->stream)
+ g_mime_stream_unref (wrapper->stream);
+ wrapper->stream = stream;
+}
+
+
+void
+g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding)
+{
+ g_return_if_fail (wrapper != NULL);
+
+ wrapper->encoding = encoding;
+}
diff --git a/gmime-data-wrapper.h b/gmime-data-wrapper.h
new file mode 100644
index 00000000..55b9a9c7
--- /dev/null
+++ b/gmime-data-wrapper.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_DATA_WRAPPER_H__
+#define __GMIME_DATA_WRAPPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <gmime-content-type.h>
+#include <gmime-stream.h>
+
+typedef enum {
+ GMIME_PART_ENCODING_DEFAULT,
+ GMIME_PART_ENCODING_7BIT,
+ GMIME_PART_ENCODING_8BIT,
+ GMIME_PART_ENCODING_BASE64,
+ GMIME_PART_ENCODING_QUOTEDPRINTABLE,
+ GMIME_PART_NUM_ENCODINGS
+} GMimePartEncodingType;
+
+typedef struct _GMimeDataWrapper {
+ GMimePartEncodingType encoding;
+ GMimeStream *stream;
+} GMimeDataWrapper;
+
+GMimeDataWrapper *g_mime_data_wrapper_new (void);
+GMimeDataWrapper *g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding);
+
+void g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper);
+
+void g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream);
+void g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_DATA_WRAPPER_H__ */
diff --git a/gmime-stream-file.c b/gmime-stream-file.c
new file mode 100644
index 00000000..a2cdd57b
--- /dev/null
+++ b/gmime-stream-file.c
@@ -0,0 +1,246 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream-file.h"
+
+
+static void
+stream_destroy (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (fstream->fp)
+ fclose (fstream->fp);
+
+ g_free (fstream);
+}
+
+static ssize_t
+stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (stream->bound_end == -1 && stream->position > stream->bound_end)
+ return -1;
+
+ if (stream->bound_end != -1)
+ len = MIN (stream->bound_end - stream->position, len);
+
+ /* make sure we are at the right position */
+ fseek (fstream->fp, stream->position, SEEK_SET);
+
+ return fread (buf, 1, len, fstream->fp);
+}
+
+static ssize_t
+stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (stream->bound_end == -1 && stream->position > stream->bound_end)
+ return -1;
+
+ if (stream->bound_end != -1)
+ len = MIN (stream->bound_end - stream->position, len);
+
+ return fwrite (buf, 1, len, fstream->fp);
+}
+
+static int
+stream_flush (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ return fflush (fstream->fp);
+}
+
+static int
+stream_close (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ int ret;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ ret = fclose (fstream->fp);
+ if (ret != -1)
+ fstream->fs = NULL;
+
+ return ret;
+}
+
+static gboolean
+stream_eos (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_if_fail (fstream->fp != NULL, TRUE);
+
+ return feof (fstream->fp) ? TRUE : FALSE;
+}
+
+static int
+stream_reset (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ return fseek (fstream->fp, stream->bound_start, SEEK_SET);
+}
+
+static off_t
+stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ off_t ret;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ switch (whence) {
+ case GMIME_STREAM_SEEK_SET:
+ ret = fseek (fstream->fp, offset + stream->bound_start, SEEK_SET);
+ break;
+ case GMIME_STREAM_SEEK_END:
+ if (offset < 0) {
+ offset += stream->bound_end;
+ ret = fseek (fstream->fp, offset, SEEK_SET);
+ } else {
+ ret = fseek (fstream->fp, stream->bound_end, SEEK_SET);
+ }
+ break;
+ case GMIME_STREAM_SEEK_CUR:
+ offset += stream->position;
+ if (offset < stream->bound_start) {
+ ret = fseek (fstream->fp, stream->bound_start, SEEK_SET);
+ } else if (offset > stream->bound_end) {
+ ret = fseek (fstream->fp, stream->bound_end, SEEK_SET);
+ } else {
+ ret = fseek (fstream->fp, offset, SEEK_CUR);
+ }
+ }
+
+ stream->position = ftell (fstream->fp);
+
+ return ret;
+}
+
+static off_t
+stream_tell (GMimeStream *stream)
+{
+ return stream->position - stream->bound_start;
+}
+
+static ssize_t
+stream_length (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ off_t len;
+
+ if (stream->bound_start != -1 && stream->bound_end != -1)
+ return stream->bound_end - stream->bound_start;
+
+ fseek (fstream->fp, 0, SEEK_END);
+ len = ftell (fstream->fp);
+ fseek (fstream->fp, stream->position, SEEK_SET);
+
+ return len;
+}
+
+
+/**
+ * g_mime_stream_file_new:
+ * @fp:
+ *
+ **/
+GMimeStream *
+g_mime_stream_file_new (FILE *fp)
+{
+ GMimeStreamFile *fstream;
+ GMimeStream *stream;
+
+ fstream = g_new0 (GMimeStreamFile, 1);
+ fstream->fp = fp;
+
+ stream = (GMimeStream *) fstream;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_FILE_TYPE;
+
+ stream->position = ftell (fp);
+ stream->bound_start = stream->position;
+ stream->bound_end = -1;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->reset = stream_reset;
+ stream->eos = stream_eos;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_file_new_with_bounds:
+ * @fp:
+ * @start:
+ * @end:
+ *
+ **/
+GMimeStream *
+g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end)
+{
+ GMimeStreamFile *fstream;
+ GMimeStream *stream;
+
+ file = g_new0 (GMimeStreamFile, 1);
+ fstream->fp = fp;
+
+ stream = (GMimeStream *) fstream;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_FILE_TYPE;
+
+ stream->position = start;
+ stream->bound_start = start;
+ stream->bound_end = end;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->reset = stream_reset;
+ stream->eos = stream_eos;
+
+ return stream;
+}
diff --git a/gmime-stream-file.h b/gmime-stream-file.h
new file mode 100644
index 00000000..65ff3910
--- /dev/null
+++ b/gmime-stream-file.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_STREAM_FILE_H__
+#define __GMIME_STREAM_FILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <stdio.h>
+#include <gmime-stream.h>
+
+typedef struct _GMimeStreamFile {
+ GMimeStream parent;
+
+ FILE *fp;
+} GMimeStreamFile;
+
+#define GMIME_STREAM_FILE_TYPE g_str_hash ("GMimeStreamFile")
+#define GMIME_IS_STREAM_FILE(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILE)
+#define GMIME_STREAM_FILE(stream) ((GMimeStreamFile *) stream)
+
+GMimeStream *g_mime_stream_file_new (FILE *fp);
+GMimeStream *g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_FILE_H__ */
diff --git a/gmime-stream-mem.c b/gmime-stream-mem.c
new file mode 100644
index 00000000..f2b5cb62
--- /dev/null
+++ b/gmime-stream-mem.c
@@ -0,0 +1,286 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream-mem.h"
+
+
+static void
+stream_destroy (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ if (mem->owner && mem->buffer)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ g_free (mem);
+}
+
+static ssize_t
+stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+ ssize_t n;
+
+ g_return_val_if_fail (stream->position <= stream->bound_end, -1);
+
+ n = MIN (stream->bound_end - stream->position, len);
+ if (n > 0) {
+ memcpy (buf, mem->buffer->data, n);
+ stream->position += n;
+ }
+
+ return n;
+}
+
+static ssize_t
+stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ g_byte_array_append (mem->buffer, buf, len);
+ stream->bound_end = mem->buffer->len;
+
+ return len;
+}
+
+static int
+stream_flush (GMimeStream *stream)
+{
+ /* no-op */
+}
+
+static int
+stream_close (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ if (mem->owner)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ mem->buffer = NULL;
+ stream->position = 0;
+
+ return 0;
+}
+
+static gboolean
+stream_eos (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ return mem->buffer ? stream->position == stream->bound_end : TRUE;
+}
+
+static int
+stream_reset (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ stream->position = stream->bound_start;
+
+ return 0;
+}
+
+static off_t
+stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ g_return_val_if_fail (mem->buffer != NULL, -1);
+
+ switch (whence) {
+ case GMIME_STREAM_SEEK_SET:
+ stream->position = MIN (offset + stream->bound_start, stream->bound_end);
+ break;
+ case GMIME_STREAM_SEEK_END:
+ stream->position = MAX (offset + stream->bound_end, 0);
+ break;
+ case GMIME_STREAM_SEEK_CUR:
+ stream->position += offset;
+ if (stream->position < stream->bound_start)
+ stream->position = stream->bound_start;
+ else if (stream->position > stream->bound_end)
+ stream->position = stream->bound_end;
+ }
+
+ return 0;
+}
+
+static off_t
+stream_tell (GMimeStream *stream)
+{
+ return stream->position - stream->bound_start;
+}
+
+static ssize_t
+stream_length (GMimeStream *stream)
+{
+ return stream->bound_end - stream->bound_start;
+}
+
+
+/**
+ * g_mime_stream_mem_new:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new (void)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ xmem->buffer = g_byte_array_new ();
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = 0;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_new_with_byte_array:
+ * @array:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new_with_byte_array (GByteArray *array)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ mem->buffer = array;
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = array->len;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_new_with_buffer:
+ * @buffer:
+ * @len:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ mem->buffer = g_byte_array_new ();
+
+ g_byte_array_append (mem->buffer, buffer, len);
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = len;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_set_byte_array:
+ * @mem:
+ * @array:
+ *
+ **/
+void
+g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array)
+{
+ GMimeStream *stream;
+
+ g_return_if_fail (mem != NULL);
+ g_return_if_fail (array != NULL);
+
+ if (mem->buffer)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ mem->buffer = array;
+ mem->owner = FALSE;
+
+ stream = (GMimeStream *) mem;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = array->len;
+}
diff --git a/gmime-stream-mem.h b/gmime-stream-mem.h
new file mode 100644
index 00000000..d4fe4e54
--- /dev/null
+++ b/gmime-stream-mem.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 Ximain, 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 __GMIME_STREAM_MEM_H__
+#define __GMIME_STREAM_MEM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <gmime-stream.h>
+
+typedef struct _GMimeStreamMem {
+ GMimeStream parent;
+
+ gboolean owner;
+ GByteArray *buffer;
+} GMimeStreamMem;
+
+#define GMIME_STREAM_MEM_TYPE g_str_hash ("GMimeStreamMem")
+#define GMIME_IS_STREAM_MEM(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_MEM)
+#define GMIME_STREAM_MEM(stream) ((GMimeStreamMem *) stream)
+
+GMimeStream *g_mime_stream_mem_new (void);
+GMimeStream *g_mime_stream_mem_new_with_byte_array (GByteArray *array);
+GMimeStream *g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len);
+
+void g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_MEM_H__ */
diff --git a/gmime-stream.c b/gmime-stream.c
new file mode 100644
index 00000000..4798d6d9
--- /dev/null
+++ b/gmime-stream.c
@@ -0,0 +1,328 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream.h"
+#include <string.h>
+
+/**
+ * g_mime_stream_read:
+ * @stream:
+ * @buf:
+ * @len:
+ *
+ * Attempts to read up to @len bytes from @stream into @buf.
+ *
+ * Returns the number of bytes read or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+ g_return_val_if_fail (buf != NULL, -1);
+
+ return *(stream->read) (stream, buf, len);
+}
+
+
+/**
+ * g_mime_stream_write:
+ * @stream:
+ * @buf:
+ * @len:
+ *
+ * Attempts to write up to @len bytes of @buf to @stream.
+ *
+ * Returns the number of bytes written or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+ g_return_val_if_fail (buf != NULL, -1);
+
+ return *(stream->write) (stream, buf, len);
+}
+
+
+/**
+ * g_mime_stream_flush:
+ * @stream:
+ *
+ * Sync's the stream to disk.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_flush (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->flush) (stream);
+}
+
+
+/**
+ * g_mime_stream_close:
+ * @stream:
+ *
+ * Closes the stream.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_close (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->close) (stream);
+}
+
+
+/**
+ * g_mime_stream_eos:
+ * @stream:
+ *
+ * Tests the end-of-stream indicator for @stream.
+ *
+ * Returns TRUE on EOS or FALSE otherwise.
+ **/
+gboolean
+g_mime_stream_eos (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, TRUE);
+
+ return *(stream->eos) (stream);
+}
+
+
+/**
+ * g_mime_stream_reset:
+ * @stream:
+ *
+ * Resets the stream.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_reset (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->reset) (stream);
+}
+
+
+/**
+ * g_mime_stream_seek:
+ * @stream:
+ * @offset:
+ * @whence:
+ *
+ * Seek to a position in the stream.
+ **/
+off_t
+g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->seek) (stream, offset, whence);
+}
+
+
+/**
+ * g_mime_stream_tell:
+ * @stream:
+ *
+ * Returns the current position within the stream.
+ **/
+off_t
+g_mime_stream_tell (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->tell) (stream);
+}
+
+
+/**
+ * g_mime_stream_length:
+ * @stream:
+ *
+ * Returns the length of the stream or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_length (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->length) (stream);
+}
+
+
+/**
+ * g_mime_stream_ref:
+ * @stream:
+ *
+ * Ref's a stream.
+ **/
+void
+g_mime_stream_ref (GMimeStream *stream)
+{
+ g_return_if_fail (stream != NULL);
+
+ stream->refcount++;
+}
+
+
+/**
+ * g_mime_stream_unref:
+ * @stream:
+ *
+ * Unref's a stream.
+ **/
+void
+g_mime_stream_unref (GMimeStream *stream)
+{
+ g_return_if_fail (stream != NULL);
+
+ if (stream->refcount <= 1) {
+ if (stream->user_data && stream->user_data_destroy)
+ *(stream->user_data_destroy) (stream->user_data);
+
+ *(stream->destroy) (stream);
+ } else {
+ stream->refcount--;
+ }
+}
+
+
+/**
+ * g_mime_stream_set_bounds:
+ * @stream:
+ * @start:
+ * @end:
+ *
+ * Set the bounds on a stream.
+ **/
+void
+g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end)
+{
+ g_return_if_fail (stream != NULL);
+
+ stream->bound_start = start;
+ stream->bound_end = end;
+
+ if (stream->position < start)
+ stream->position = start;
+ else if (stream->position > end)
+ stream->position = end;
+}
+
+
+/**
+ * g_mime_stream_write_string:
+ * @stream:
+ * @string:
+ *
+ * Write's @string to @stream.
+ *
+ * Returns the number of bytes written.
+ **/
+ssize_t
+g_mime_stream_write_string (GMimeStream *stream, const char *string)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return g_mime_stream_write (stream, string, strlen (string));
+}
+
+
+/**
+ * g_mime_stream_printf:
+ * @stream:
+ * @fmt:
+ * @args:
+ *
+ **/
+ssize_t
+g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...)
+{
+ va_list args;
+ char *string;
+ ssize_t ret;
+
+ g_return_val_if_fail (stream != NULL, -1);
+
+ va_start (args, fmt);
+ string = g_strdup_vprintf (args);
+ va_end (args);
+
+ if (!string)
+ return -1;
+
+ ret = g_mime_stream_write (stream, string, strlen (string));
+ g_free (string);
+
+ return ret;
+}
+
+
+/**
+ * g_mime_stream_write_to_stream:
+ * @src:
+ * @dest:
+ *
+ * Attempts to write stream @src to stream @dest.
+ *
+ * Returns the number of bytes written.
+ **/
+ssize_t
+g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest)
+{
+ ssize_t nread, nwritten, total = 0;
+ char buf[4096];
+
+ g_return_val_if_fail (src != NULL, -1);
+ g_return_val_if_fail (dest != NULL, -1);
+
+ while (!g_mime_stream_eos (src)) {
+ nwritten = 0;
+ nread = g_mime_stream_read (src, buf, sizeof (buf));
+ if (nread < 0)
+ return -1;
+
+ while (nwritten < nread) {
+ ssize_t len;
+
+ len = g_mime_stream_write (dest, buf + nwritten, nread - nwritten);
+ if (len < 0)
+ return -1;
+
+ nwritten += len;
+ }
+
+ total += nwritten;
+ }
+
+ return total;
+}
diff --git a/gmime-stream.h b/gmime-stream.h
new file mode 100644
index 00000000..8c61099f
--- /dev/null
+++ b/gmime-stream.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_STREAM_H__
+#define __GMIME_STREAM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+typedef enum {
+ GMIME_STREAM_SEEK_SET = SEEK_SET,
+ GMIME_STREAM_SEEK_CUR = SEEK_CUR,
+ GMIME_STREAM_SEEK_END = SEEK_END,
+} GMimeSeekWhence;
+
+typedef struct _GMimeStream {
+ int type;
+ int refcount;
+
+ off_t position;
+ off_t bound_start;
+ off_t bound_end;
+
+ void *user_data;
+ void (*user_data_destroy) (void *user_data);
+
+ void (*destroy) (GMimeStream *stream);
+
+ ssize_t (*read) (GMimeStream *stream, char *buf, size_t len);
+ ssize_t (*write) (GMimeStream *stream, char *buf, size_t len);
+ int (*flush) (GMimeStream *stream);
+ int (*close) (GMimeStream *stream);
+ gboolean (*eos) (GMimeStream *stream);
+ int (*reset) (GMimeStream *stream);
+ off_t (*seek) (GMimeStream *stream, off_t offset, GMimeSeekWhence whence);
+ off_t (*tell) (GMimeStream *stream);
+ ssize_t (*length) (GMimeStream *stream);
+} GMimeStream;
+
+#define GMIME_STREAM(stream) ((GMimeStream *) stream)
+
+/* public methods */
+ssize_t g_mime_stream_read (GMimeStream *stream, char *buf, size_t len);
+ssize_t g_mime_stream_write (GMimeStream *stream, char *buf, size_t len);
+int g_mime_stream_flush (GMimeStream *stream);
+int g_mime_stream_close (GMimeStream *stream);
+gboolean g_mime_stream_eos (GMimeStream *stream);
+int g_mime_stream_reset (GMimeStream *stream);
+off_t g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence);
+off_t g_mime_stream_tell (GMimeStream *stream);
+ssize_t g_mime_stream_length (GMimeStream *stream);
+
+void g_mime_stream_ref (GMimeStream *stream);
+void g_mime_stream_unref (GMimeStream *stream);
+
+void g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end);
+
+ssize_t g_mime_stream_write_string (GMimeStream *stream, const char *string);
+ssize_t g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
+
+ssize_t g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_H__ */
diff --git a/gmime/gmime-data-wrapper.c b/gmime/gmime-data-wrapper.c
new file mode 100644
index 00000000..493803b0
--- /dev/null
+++ b/gmime/gmime-data-wrapper.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-data-wrapper.h"
+
+
+GMimeDataWrapper *
+g_mime_data_wrapper_new (void)
+{
+ return g_new0 (GMimeDataWrapper, 1);
+}
+
+
+GMimeDataWrapper *
+g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding)
+{
+ GMimeDataWrapper *wrapper;
+
+ wrapper = g_new (GMimeDataWrapper, 1);
+ wrapper->encoding = encoding;
+ wrapper->stream = stream;
+
+ return wrapper;
+}
+
+
+void
+g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper)
+{
+ if (wrapper) {
+ if (wrapper->stream)
+ g_mime_stream_unref (wrapper->stream);
+ g_free (wrapper);
+ }
+}
+
+
+void
+g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream)
+{
+ g_return_if_fail (wrapper != NULL);
+
+ if (wrapper->stream)
+ g_mime_stream_unref (wrapper->stream);
+ wrapper->stream = stream;
+}
+
+
+void
+g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding)
+{
+ g_return_if_fail (wrapper != NULL);
+
+ wrapper->encoding = encoding;
+}
diff --git a/gmime/gmime-data-wrapper.h b/gmime/gmime-data-wrapper.h
new file mode 100644
index 00000000..55b9a9c7
--- /dev/null
+++ b/gmime/gmime-data-wrapper.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_DATA_WRAPPER_H__
+#define __GMIME_DATA_WRAPPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <gmime-content-type.h>
+#include <gmime-stream.h>
+
+typedef enum {
+ GMIME_PART_ENCODING_DEFAULT,
+ GMIME_PART_ENCODING_7BIT,
+ GMIME_PART_ENCODING_8BIT,
+ GMIME_PART_ENCODING_BASE64,
+ GMIME_PART_ENCODING_QUOTEDPRINTABLE,
+ GMIME_PART_NUM_ENCODINGS
+} GMimePartEncodingType;
+
+typedef struct _GMimeDataWrapper {
+ GMimePartEncodingType encoding;
+ GMimeStream *stream;
+} GMimeDataWrapper;
+
+GMimeDataWrapper *g_mime_data_wrapper_new (void);
+GMimeDataWrapper *g_mime_data_wrapper_new_with_stream (GMimeStream *stream, GMimePartEncodingType encoding);
+
+void g_mime_data_wrapper_destroy (GMimeDataWrapper *wrapper);
+
+void g_mime_data_wrapper_set_stream (GMimeDataWrapper *wrapper, GMimeStream *stream);
+void g_mime_data_wrapper_set_encoding (GMimeDataWrapper *wrapper, GMimePartEncodingType encoding);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_DATA_WRAPPER_H__ */
diff --git a/gmime/gmime-stream-file.c b/gmime/gmime-stream-file.c
new file mode 100644
index 00000000..a2cdd57b
--- /dev/null
+++ b/gmime/gmime-stream-file.c
@@ -0,0 +1,246 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream-file.h"
+
+
+static void
+stream_destroy (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (fstream->fp)
+ fclose (fstream->fp);
+
+ g_free (fstream);
+}
+
+static ssize_t
+stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (stream->bound_end == -1 && stream->position > stream->bound_end)
+ return -1;
+
+ if (stream->bound_end != -1)
+ len = MIN (stream->bound_end - stream->position, len);
+
+ /* make sure we are at the right position */
+ fseek (fstream->fp, stream->position, SEEK_SET);
+
+ return fread (buf, 1, len, fstream->fp);
+}
+
+static ssize_t
+stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ if (stream->bound_end == -1 && stream->position > stream->bound_end)
+ return -1;
+
+ if (stream->bound_end != -1)
+ len = MIN (stream->bound_end - stream->position, len);
+
+ return fwrite (buf, 1, len, fstream->fp);
+}
+
+static int
+stream_flush (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ return fflush (fstream->fp);
+}
+
+static int
+stream_close (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ int ret;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ ret = fclose (fstream->fp);
+ if (ret != -1)
+ fstream->fs = NULL;
+
+ return ret;
+}
+
+static gboolean
+stream_eos (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_if_fail (fstream->fp != NULL, TRUE);
+
+ return feof (fstream->fp) ? TRUE : FALSE;
+}
+
+static int
+stream_reset (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ return fseek (fstream->fp, stream->bound_start, SEEK_SET);
+}
+
+static off_t
+stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ off_t ret;
+
+ g_return_val_if_fail (fstream->fp != NULL, -1);
+
+ switch (whence) {
+ case GMIME_STREAM_SEEK_SET:
+ ret = fseek (fstream->fp, offset + stream->bound_start, SEEK_SET);
+ break;
+ case GMIME_STREAM_SEEK_END:
+ if (offset < 0) {
+ offset += stream->bound_end;
+ ret = fseek (fstream->fp, offset, SEEK_SET);
+ } else {
+ ret = fseek (fstream->fp, stream->bound_end, SEEK_SET);
+ }
+ break;
+ case GMIME_STREAM_SEEK_CUR:
+ offset += stream->position;
+ if (offset < stream->bound_start) {
+ ret = fseek (fstream->fp, stream->bound_start, SEEK_SET);
+ } else if (offset > stream->bound_end) {
+ ret = fseek (fstream->fp, stream->bound_end, SEEK_SET);
+ } else {
+ ret = fseek (fstream->fp, offset, SEEK_CUR);
+ }
+ }
+
+ stream->position = ftell (fstream->fp);
+
+ return ret;
+}
+
+static off_t
+stream_tell (GMimeStream *stream)
+{
+ return stream->position - stream->bound_start;
+}
+
+static ssize_t
+stream_length (GMimeStream *stream)
+{
+ GMimeStreamFile *fstream = (GMimeStreamFile *) stream;
+ off_t len;
+
+ if (stream->bound_start != -1 && stream->bound_end != -1)
+ return stream->bound_end - stream->bound_start;
+
+ fseek (fstream->fp, 0, SEEK_END);
+ len = ftell (fstream->fp);
+ fseek (fstream->fp, stream->position, SEEK_SET);
+
+ return len;
+}
+
+
+/**
+ * g_mime_stream_file_new:
+ * @fp:
+ *
+ **/
+GMimeStream *
+g_mime_stream_file_new (FILE *fp)
+{
+ GMimeStreamFile *fstream;
+ GMimeStream *stream;
+
+ fstream = g_new0 (GMimeStreamFile, 1);
+ fstream->fp = fp;
+
+ stream = (GMimeStream *) fstream;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_FILE_TYPE;
+
+ stream->position = ftell (fp);
+ stream->bound_start = stream->position;
+ stream->bound_end = -1;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->reset = stream_reset;
+ stream->eos = stream_eos;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_file_new_with_bounds:
+ * @fp:
+ * @start:
+ * @end:
+ *
+ **/
+GMimeStream *
+g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end)
+{
+ GMimeStreamFile *fstream;
+ GMimeStream *stream;
+
+ file = g_new0 (GMimeStreamFile, 1);
+ fstream->fp = fp;
+
+ stream = (GMimeStream *) fstream;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_FILE_TYPE;
+
+ stream->position = start;
+ stream->bound_start = start;
+ stream->bound_end = end;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->reset = stream_reset;
+ stream->eos = stream_eos;
+
+ return stream;
+}
diff --git a/gmime/gmime-stream-file.h b/gmime/gmime-stream-file.h
new file mode 100644
index 00000000..65ff3910
--- /dev/null
+++ b/gmime/gmime-stream-file.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_STREAM_FILE_H__
+#define __GMIME_STREAM_FILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <stdio.h>
+#include <gmime-stream.h>
+
+typedef struct _GMimeStreamFile {
+ GMimeStream parent;
+
+ FILE *fp;
+} GMimeStreamFile;
+
+#define GMIME_STREAM_FILE_TYPE g_str_hash ("GMimeStreamFile")
+#define GMIME_IS_STREAM_FILE(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_FILE)
+#define GMIME_STREAM_FILE(stream) ((GMimeStreamFile *) stream)
+
+GMimeStream *g_mime_stream_file_new (FILE *fp);
+GMimeStream *g_mime_stream_file_new_with_bounds (FILE *fp, off_t start, off_t end);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_FILE_H__ */
diff --git a/gmime/gmime-stream-mem.c b/gmime/gmime-stream-mem.c
new file mode 100644
index 00000000..f2b5cb62
--- /dev/null
+++ b/gmime/gmime-stream-mem.c
@@ -0,0 +1,286 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream-mem.h"
+
+
+static void
+stream_destroy (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ if (mem->owner && mem->buffer)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ g_free (mem);
+}
+
+static ssize_t
+stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+ ssize_t n;
+
+ g_return_val_if_fail (stream->position <= stream->bound_end, -1);
+
+ n = MIN (stream->bound_end - stream->position, len);
+ if (n > 0) {
+ memcpy (buf, mem->buffer->data, n);
+ stream->position += n;
+ }
+
+ return n;
+}
+
+static ssize_t
+stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ g_byte_array_append (mem->buffer, buf, len);
+ stream->bound_end = mem->buffer->len;
+
+ return len;
+}
+
+static int
+stream_flush (GMimeStream *stream)
+{
+ /* no-op */
+}
+
+static int
+stream_close (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ if (mem->owner)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ mem->buffer = NULL;
+ stream->position = 0;
+
+ return 0;
+}
+
+static gboolean
+stream_eos (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ return mem->buffer ? stream->position == stream->bound_end : TRUE;
+}
+
+static int
+stream_reset (GMimeStream *stream)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ stream->position = stream->bound_start;
+
+ return 0;
+}
+
+static off_t
+stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ GMimeStreamMem *mem = (GMimeStreamMem *) stream;
+
+ g_return_val_if_fail (mem->buffer != NULL, -1);
+
+ switch (whence) {
+ case GMIME_STREAM_SEEK_SET:
+ stream->position = MIN (offset + stream->bound_start, stream->bound_end);
+ break;
+ case GMIME_STREAM_SEEK_END:
+ stream->position = MAX (offset + stream->bound_end, 0);
+ break;
+ case GMIME_STREAM_SEEK_CUR:
+ stream->position += offset;
+ if (stream->position < stream->bound_start)
+ stream->position = stream->bound_start;
+ else if (stream->position > stream->bound_end)
+ stream->position = stream->bound_end;
+ }
+
+ return 0;
+}
+
+static off_t
+stream_tell (GMimeStream *stream)
+{
+ return stream->position - stream->bound_start;
+}
+
+static ssize_t
+stream_length (GMimeStream *stream)
+{
+ return stream->bound_end - stream->bound_start;
+}
+
+
+/**
+ * g_mime_stream_mem_new:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new (void)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ xmem->buffer = g_byte_array_new ();
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = 0;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_new_with_byte_array:
+ * @array:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new_with_byte_array (GByteArray *array)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ mem->buffer = array;
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = array->len;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_new_with_buffer:
+ * @buffer:
+ * @len:
+ *
+ **/
+GMimeStream *
+g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len)
+{
+ GMimeStreamMem *mem;
+ GMimeStream *stream;
+
+ mem = g_new0 (GMimeStreamMem, 1);
+ mem->owner = TRUE;
+ mem->buffer = g_byte_array_new ();
+
+ g_byte_array_append (mem->buffer, buffer, len);
+
+ stream = (GMimeStream *) mem;
+
+ stream->refcount = 1;
+ stream->type = GMIME_STREAM_MEM_TYPE;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = len;
+
+ stream->destroy = stream_destroy;
+ stream->read = stream_read;
+ stream->write = strea_write;
+ stream->flush = stream_flush;
+ stream->close = stream_close;
+ stream->reset = stream_reset;
+ stream->seek = stream_seek;
+ stream->tell = stream_tell;
+ stream->eos = stream_eos;
+ stream->length = stream_length;
+
+ return stream;
+}
+
+
+/**
+ * g_mime_stream_mem_set_byte_array:
+ * @mem:
+ * @array:
+ *
+ **/
+void
+g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array)
+{
+ GMimeStream *stream;
+
+ g_return_if_fail (mem != NULL);
+ g_return_if_fail (array != NULL);
+
+ if (mem->buffer)
+ g_byte_array_free (mem->buffer, TRUE);
+
+ mem->buffer = array;
+ mem->owner = FALSE;
+
+ stream = (GMimeStream *) mem;
+
+ stream->position = 0;
+ stream->bound_start = 0;
+ stream->bound_end = array->len;
+}
diff --git a/gmime/gmime-stream-mem.h b/gmime/gmime-stream-mem.h
new file mode 100644
index 00000000..d4fe4e54
--- /dev/null
+++ b/gmime/gmime-stream-mem.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 Ximain, 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 __GMIME_STREAM_MEM_H__
+#define __GMIME_STREAM_MEM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <gmime-stream.h>
+
+typedef struct _GMimeStreamMem {
+ GMimeStream parent;
+
+ gboolean owner;
+ GByteArray *buffer;
+} GMimeStreamMem;
+
+#define GMIME_STREAM_MEM_TYPE g_str_hash ("GMimeStreamMem")
+#define GMIME_IS_STREAM_MEM(stream) (((GMimeStream *) stream)->type == GMIME_STREAM_MEM)
+#define GMIME_STREAM_MEM(stream) ((GMimeStreamMem *) stream)
+
+GMimeStream *g_mime_stream_mem_new (void);
+GMimeStream *g_mime_stream_mem_new_with_byte_array (GByteArray *array);
+GMimeStream *g_mime_stream_mem_new_with_buffer (const char *buffer, size_t len);
+
+void g_mime_stream_mem_set_byte_array (GMimeStreamMem *mem, GByteArray *array);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_MEM_H__ */
diff --git a/gmime/gmime-stream.c b/gmime/gmime-stream.c
new file mode 100644
index 00000000..4798d6d9
--- /dev/null
+++ b/gmime/gmime-stream.c
@@ -0,0 +1,328 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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-stream.h"
+#include <string.h>
+
+/**
+ * g_mime_stream_read:
+ * @stream:
+ * @buf:
+ * @len:
+ *
+ * Attempts to read up to @len bytes from @stream into @buf.
+ *
+ * Returns the number of bytes read or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+ g_return_val_if_fail (buf != NULL, -1);
+
+ return *(stream->read) (stream, buf, len);
+}
+
+
+/**
+ * g_mime_stream_write:
+ * @stream:
+ * @buf:
+ * @len:
+ *
+ * Attempts to write up to @len bytes of @buf to @stream.
+ *
+ * Returns the number of bytes written or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_write (GMimeStream *stream, char *buf, size_t len)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+ g_return_val_if_fail (buf != NULL, -1);
+
+ return *(stream->write) (stream, buf, len);
+}
+
+
+/**
+ * g_mime_stream_flush:
+ * @stream:
+ *
+ * Sync's the stream to disk.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_flush (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->flush) (stream);
+}
+
+
+/**
+ * g_mime_stream_close:
+ * @stream:
+ *
+ * Closes the stream.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_close (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->close) (stream);
+}
+
+
+/**
+ * g_mime_stream_eos:
+ * @stream:
+ *
+ * Tests the end-of-stream indicator for @stream.
+ *
+ * Returns TRUE on EOS or FALSE otherwise.
+ **/
+gboolean
+g_mime_stream_eos (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, TRUE);
+
+ return *(stream->eos) (stream);
+}
+
+
+/**
+ * g_mime_stream_reset:
+ * @stream:
+ *
+ * Resets the stream.
+ *
+ * Returns 0 on success or -1 on fail.
+ **/
+int
+g_mime_stream_reset (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->reset) (stream);
+}
+
+
+/**
+ * g_mime_stream_seek:
+ * @stream:
+ * @offset:
+ * @whence:
+ *
+ * Seek to a position in the stream.
+ **/
+off_t
+g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->seek) (stream, offset, whence);
+}
+
+
+/**
+ * g_mime_stream_tell:
+ * @stream:
+ *
+ * Returns the current position within the stream.
+ **/
+off_t
+g_mime_stream_tell (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->tell) (stream);
+}
+
+
+/**
+ * g_mime_stream_length:
+ * @stream:
+ *
+ * Returns the length of the stream or -1 on fail.
+ **/
+ssize_t
+g_mime_stream_length (GMimeStream *stream)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return *(stream->length) (stream);
+}
+
+
+/**
+ * g_mime_stream_ref:
+ * @stream:
+ *
+ * Ref's a stream.
+ **/
+void
+g_mime_stream_ref (GMimeStream *stream)
+{
+ g_return_if_fail (stream != NULL);
+
+ stream->refcount++;
+}
+
+
+/**
+ * g_mime_stream_unref:
+ * @stream:
+ *
+ * Unref's a stream.
+ **/
+void
+g_mime_stream_unref (GMimeStream *stream)
+{
+ g_return_if_fail (stream != NULL);
+
+ if (stream->refcount <= 1) {
+ if (stream->user_data && stream->user_data_destroy)
+ *(stream->user_data_destroy) (stream->user_data);
+
+ *(stream->destroy) (stream);
+ } else {
+ stream->refcount--;
+ }
+}
+
+
+/**
+ * g_mime_stream_set_bounds:
+ * @stream:
+ * @start:
+ * @end:
+ *
+ * Set the bounds on a stream.
+ **/
+void
+g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end)
+{
+ g_return_if_fail (stream != NULL);
+
+ stream->bound_start = start;
+ stream->bound_end = end;
+
+ if (stream->position < start)
+ stream->position = start;
+ else if (stream->position > end)
+ stream->position = end;
+}
+
+
+/**
+ * g_mime_stream_write_string:
+ * @stream:
+ * @string:
+ *
+ * Write's @string to @stream.
+ *
+ * Returns the number of bytes written.
+ **/
+ssize_t
+g_mime_stream_write_string (GMimeStream *stream, const char *string)
+{
+ g_return_val_if_fail (stream != NULL, -1);
+
+ return g_mime_stream_write (stream, string, strlen (string));
+}
+
+
+/**
+ * g_mime_stream_printf:
+ * @stream:
+ * @fmt:
+ * @args:
+ *
+ **/
+ssize_t
+g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...)
+{
+ va_list args;
+ char *string;
+ ssize_t ret;
+
+ g_return_val_if_fail (stream != NULL, -1);
+
+ va_start (args, fmt);
+ string = g_strdup_vprintf (args);
+ va_end (args);
+
+ if (!string)
+ return -1;
+
+ ret = g_mime_stream_write (stream, string, strlen (string));
+ g_free (string);
+
+ return ret;
+}
+
+
+/**
+ * g_mime_stream_write_to_stream:
+ * @src:
+ * @dest:
+ *
+ * Attempts to write stream @src to stream @dest.
+ *
+ * Returns the number of bytes written.
+ **/
+ssize_t
+g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest)
+{
+ ssize_t nread, nwritten, total = 0;
+ char buf[4096];
+
+ g_return_val_if_fail (src != NULL, -1);
+ g_return_val_if_fail (dest != NULL, -1);
+
+ while (!g_mime_stream_eos (src)) {
+ nwritten = 0;
+ nread = g_mime_stream_read (src, buf, sizeof (buf));
+ if (nread < 0)
+ return -1;
+
+ while (nwritten < nread) {
+ ssize_t len;
+
+ len = g_mime_stream_write (dest, buf + nwritten, nread - nwritten);
+ if (len < 0)
+ return -1;
+
+ nwritten += len;
+ }
+
+ total += nwritten;
+ }
+
+ return total;
+}
diff --git a/gmime/gmime-stream.h b/gmime/gmime-stream.h
new file mode 100644
index 00000000..8c61099f
--- /dev/null
+++ b/gmime/gmime-stream.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximain, 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 __GMIME_STREAM_H__
+#define __GMIME_STREAM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+typedef enum {
+ GMIME_STREAM_SEEK_SET = SEEK_SET,
+ GMIME_STREAM_SEEK_CUR = SEEK_CUR,
+ GMIME_STREAM_SEEK_END = SEEK_END,
+} GMimeSeekWhence;
+
+typedef struct _GMimeStream {
+ int type;
+ int refcount;
+
+ off_t position;
+ off_t bound_start;
+ off_t bound_end;
+
+ void *user_data;
+ void (*user_data_destroy) (void *user_data);
+
+ void (*destroy) (GMimeStream *stream);
+
+ ssize_t (*read) (GMimeStream *stream, char *buf, size_t len);
+ ssize_t (*write) (GMimeStream *stream, char *buf, size_t len);
+ int (*flush) (GMimeStream *stream);
+ int (*close) (GMimeStream *stream);
+ gboolean (*eos) (GMimeStream *stream);
+ int (*reset) (GMimeStream *stream);
+ off_t (*seek) (GMimeStream *stream, off_t offset, GMimeSeekWhence whence);
+ off_t (*tell) (GMimeStream *stream);
+ ssize_t (*length) (GMimeStream *stream);
+} GMimeStream;
+
+#define GMIME_STREAM(stream) ((GMimeStream *) stream)
+
+/* public methods */
+ssize_t g_mime_stream_read (GMimeStream *stream, char *buf, size_t len);
+ssize_t g_mime_stream_write (GMimeStream *stream, char *buf, size_t len);
+int g_mime_stream_flush (GMimeStream *stream);
+int g_mime_stream_close (GMimeStream *stream);
+gboolean g_mime_stream_eos (GMimeStream *stream);
+int g_mime_stream_reset (GMimeStream *stream);
+off_t g_mime_stream_seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence);
+off_t g_mime_stream_tell (GMimeStream *stream);
+ssize_t g_mime_stream_length (GMimeStream *stream);
+
+void g_mime_stream_ref (GMimeStream *stream);
+void g_mime_stream_unref (GMimeStream *stream);
+
+void g_mime_stream_set_bounds (GMimeStream *stream, off_t start, off_t end);
+
+ssize_t g_mime_stream_write_string (GMimeStream *stream, const char *string);
+ssize_t g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
+
+ssize_t g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GMIME_STREAM_H__ */