aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEttore Perazzoli <ettore@src.gnome.org>1999-11-17 22:39:25 +0800
committerEttore Perazzoli <ettore@src.gnome.org>1999-11-17 22:39:25 +0800
commitca7044930f42a698fd88f914c2512a20e2eeaae9 (patch)
tree522962a77005d741097713e87de1d50353b17768
parent16de3313b700cb56ab9e829d1e9b7e7d2c81241b (diff)
downloadgsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.gz
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.bz2
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.lz
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.xz
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.zst
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.zip
Added streaming capability to CamelDataWrapper. This makes it possible, for
example, to build multipart messages out of files that are on disk without loading them in memory. svn path=/trunk/; revision=1394
-rw-r--r--ChangeLog67
-rw-r--r--camel/Makefile.am5
-rw-r--r--camel/camel-data-wrapper.c13
-rw-r--r--camel/camel-data-wrapper.h2
-rw-r--r--camel/camel-mime-message.c5
-rw-r--r--camel/camel-mime-part.c102
-rw-r--r--camel/camel-mime-part.h26
-rw-r--r--camel/camel-simple-data-wrapper-stream.c276
-rw-r--r--camel/camel-simple-data-wrapper-stream.h74
-rw-r--r--camel/camel-simple-data-wrapper.c34
-rw-r--r--camel/camel-simple-data-wrapper.h2
-rw-r--r--camel/camel-stream-data-wrapper.c209
-rw-r--r--camel/camel-stream-data-wrapper.h75
-rw-r--r--camel/gmime-base64.c21
-rw-r--r--camel/gmime-base64.h16
-rw-r--r--doc/Camel-Classes2
-rw-r--r--help/Camel-Classes2
-rw-r--r--tests/test1.c52
18 files changed, 925 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c89092878..e0ed428fdb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,70 @@
+1999-11-17 Ettore Perazzoli <ettore@gnu.org>
+
+ * camel/camel-mime-message.c (_write_to_stream): Write
+ "Mime-Version: 1.0" to the stream.
+
+ * tests/test1.c: If executed with a file name parameter, attach a
+ file with with that name to the email without loading it into
+ core, thus demonstrating usage of my latest changes.
+
+ * camel/camel-mime-part.c (_set_encoding): Updated to use
+ `CamelMimePartEncodingType'.
+ (camel_mime_part_set_encoding): Likewise.
+ (_get_encoding): Likewise.
+ (camel_mime_part_get_encoding): Likewise.
+ (_write_content_to_stream): Honour the `encoding' member.
+ (_construct_from_stream): Made static.
+ (camel_mime_part_encoding_to_string): New function.
+ (_write_to_stream): Write the encoding string using it.
+ (camel_mime_part_init): Set encoding to
+ `CAMEL_MIME_PART_ENCODING_DEFAULT'.
+ (_finalize): Don't free `encoding' anymore.
+ (camel_mime_part_encoding_from_string): New function.
+ (_parse_header_pair): Use it.
+
+ * camel/camel-mime-part.h: New enum `CamelMimePartEncodingType'.
+ Member `encoding' of `struct _CamelMimePart' changed from `gchar
+ *' to `CamelMimePartEncodingType'. All the encoding-related
+ methods changed to use this type instead of `gchar *'.
+
+ * camel/gmime-base64.c (gmime_encode_base64): Got it to work.
+
+ * camel/Makefile.am (libcamel_la_SOURCES): Compile
+ `gmime-base64.c'.
+
+ * camel/gmime-base64.h: New, previously missing, header.
+
+ * camel/camel-stream-data-wrapper.c: New file implementing the
+ `CamelStreamDataWrapper' class.
+ * camel/camel-stream-data-wrapper.h: Corresponding header.
+
+ * camel/camel-simple-data-wrapper.c: Implemented the `get_stream'
+ virtual method.
+ (_get_stream): New function implementing the method.
+ (camel_simple_data_wrapper_class_init): Install it in the class
+ struct.
+ (camel_simple_data_wrapper_init): New function initializing the
+ `stream' member to NULL,
+ (camel_simple_data_wrapper_class_init): Set it as the
+ GtkObjectInitFunc.
+
+ * camel/camel-simple-data-wrapper.h: New member `stream' in
+ `struct _CamelSimpleDataWrapper'.
+
+ * camel/camel-simple-data-wrapper-stream.c: New file implementing
+ the `CamelSimpleDataWrapperStream' class.
+ * camel/camel-simple-data-wrapper-stream.h: Corresponding header.
+
+ * camel/camel-data-wrapper.c (camel_data_wrapper_get_stream): New
+ function.
+ (_get_stream): New private function, just returning NULL.
+ (camel_data_wrapper_class_init): Install it as the default
+ `get_stream' virtual method.
+
+ * camel/camel-data-wrapper.h: New virtual method `get_stream' in
+ `CamelDataWrapperClass'.
+ (camel_data_wrapper_get_stream): New function prototype.
+
1999-11-05 Ettore Perazzoli <ettore@gnu.org>
* tests/ui-tests/msg-composer-test.c: New file for testing the
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 0f5a4227b2..63303f4384 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -36,6 +36,8 @@ libcamel_la_SOURCES = \
camel-data-wrapper.c \
camel-exception.c \
camel-simple-data-wrapper.c \
+ camel-simple-data-wrapper-stream.c \
+ camel-stream-data-wrapper.c \
camel-folder.c \
camel-folder-summary.c \
camel-medium.c \
@@ -56,6 +58,7 @@ libcamel_la_SOURCES = \
camel-stream-fs.c \
camel-stream-mem.c \
data-wrapper-repository.c \
+ gmime-base64.c \
gmime-content-field.c \
gmime-utils.c \
gstring-util.c \
@@ -71,6 +74,8 @@ libcamelinclude_HEADERS = \
camel-data-wrapper.h \
camel-exception.h \
camel-simple-data-wrapper.h \
+ camel-simple-data-wrapper-stream.h \
+ camel-stream-data-wrapper.h \
camel-folder.h \
camel-folder-summary.h \
camel-mime-body-part.h \
diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c
index 35d34051de..5c5ac86eef 100644
--- a/camel/camel-data-wrapper.c
+++ b/camel/camel-data-wrapper.c
@@ -41,6 +41,7 @@ static void _set_mime_type (CamelDataWrapper *data_wrapper, gchar *mime_type);
static gchar *_get_mime_type (CamelDataWrapper *data_wrapper);
static GMimeContentField *_get_mime_type_field (CamelDataWrapper *data_wrapper);
static void _set_mime_type_field (CamelDataWrapper *data_wrapper, GMimeContentField *mime_type);
+static CamelStream *_get_stream (CamelDataWrapper *data_wrapper);
static void _finalize (GtkObject *object);
static void
@@ -57,6 +58,7 @@ camel_data_wrapper_class_init (CamelDataWrapperClass *camel_data_wrapper_class)
camel_data_wrapper_class->get_mime_type = _get_mime_type;
camel_data_wrapper_class->get_mime_type_field = _get_mime_type_field;
camel_data_wrapper_class->set_mime_type_field = _set_mime_type_field;
+ camel_data_wrapper_class->get_stream = _get_stream;
/* virtual method overload */
gtk_object_class->finalize = _finalize;
@@ -236,4 +238,15 @@ camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper, GMimeCon
CDW_CLASS(data_wrapper)->set_mime_type_field (data_wrapper, mime_type);
}
+static CamelStream *
+_get_stream (CamelDataWrapper *data_wrapper)
+{
+ /* This needs to be implemented in subclasses. */
+ return NULL;
+}
+CamelStream *
+camel_data_wrapper_get_stream (CamelDataWrapper *data_wrapper)
+{
+ CDW_CLASS(data_wrapper)->get_stream (data_wrapper);
+}
diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h
index 2f56ed2000..e5a97f0f78 100644
--- a/camel/camel-data-wrapper.h
+++ b/camel/camel-data-wrapper.h
@@ -66,6 +66,7 @@ typedef struct {
gchar * (*get_mime_type) (CamelDataWrapper *data_wrapper);
GMimeContentField * (*get_mime_type_field) (CamelDataWrapper *data_wrapper);
void (*set_mime_type_field) (CamelDataWrapper *data_wrapper, GMimeContentField *mime_type_field);
+ CamelStream * (*get_stream) (CamelDataWrapper *data_wrapper);
} CamelDataWrapperClass;
@@ -82,6 +83,7 @@ void camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper, gchar *mi
gchar *camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper);
GMimeContentField *camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper);
void camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper, GMimeContentField *mime_type);
+CamelStream *camel_data_wrapper_get_stream (CamelDataWrapper *data_wrapper);
#ifdef __cplusplus
}
diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c
index 582f9265fe..4742dea638 100644
--- a/camel/camel-mime-message.c
+++ b/camel/camel-mime-message.c
@@ -599,6 +599,11 @@ _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
WHPT (stream, "Date", mm->received_date);
CAMEL_LOG_FULL_DEBUG ( "CamelMimeMessage:: Writing \"Subject\"\n");
WHPT (stream, "Subject", mm->subject);
+
+ /* FIXME correct to do it here? */
+ CAMEL_LOG_FULL_DEBUG ( "CamelMimeMessage:: Writing \"Mime-Version\"\n");
+ WHPT (stream, "Mime-Version:", "1.0");
+
CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream);
}
diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c
index 180a843c02..fbf7c89591 100644
--- a/camel/camel-mime-part.c
+++ b/camel/camel-mime-part.c
@@ -60,7 +60,7 @@ static void _finalize (GtkObject *object);
/* from CamelDataWrapper */
static void _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-void _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
+static void _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
/* from CamelMedia */
static void _add_header (CamelMedium *medium, gchar *header_name, gchar *header_value);
@@ -79,8 +79,8 @@ static void _set_content_id (CamelMimePart *mime_part, gchar *content_id);
static const gchar *_get_content_id (CamelMimePart *mime_part);
static void _set_content_MD5 (CamelMimePart *mime_part, gchar *content_MD5);
static const gchar *_get_content_MD5 (CamelMimePart *mime_part);
-static void _set_encoding (CamelMimePart *mime_part, gchar *encoding);
-static const gchar *_get_encoding (CamelMimePart *mime_part);
+static void _set_encoding (CamelMimePart *mime_part, CamelMimePartEncodingType encoding);
+static CamelMimePartEncodingType _get_encoding (CamelMimePart *mime_part);
static void _set_content_languages (CamelMimePart *mime_part, GList *content_languages);
static const GList *_get_content_languages (CamelMimePart *mime_part);
static void _set_header_lines (CamelMimePart *mime_part, GList *header_lines);
@@ -162,7 +162,7 @@ camel_mime_part_init (gpointer object, gpointer klass)
camel_mime_part->content_id = NULL;
camel_mime_part->content_MD5 = NULL;
camel_mime_part->content_languages = NULL;
- camel_mime_part->encoding = NULL;
+ camel_mime_part->encoding = CAMEL_MIME_PART_ENCODING_DEFAULT;
camel_mime_part->filename = NULL;
camel_mime_part->header_lines = NULL;
@@ -214,7 +214,6 @@ _finalize (GtkObject *object)
g_free (mime_part->content_id);
g_free (mime_part->content_MD5);
string_list_free (mime_part->content_languages);
- g_free (mime_part->encoding);
g_free (mime_part->filename);
if (mime_part->header_lines) string_list_free (mime_part->header_lines);
@@ -416,14 +415,14 @@ camel_mime_part_get_content_MD5 (CamelMimePart *mime_part)
static void
-_set_encoding (CamelMimePart *mime_part, gchar *encoding)
+_set_encoding (CamelMimePart *mime_part, CamelMimePartEncodingType encoding)
{
- g_free(mime_part->encoding);
mime_part->encoding = encoding;
}
void
-camel_mime_part_set_encoding (CamelMimePart *mime_part, gchar *encoding)
+camel_mime_part_set_encoding (CamelMimePart *mime_part,
+ CamelMimePartEncodingType encoding)
{
CMP_CLASS(mime_part)->set_encoding (mime_part, encoding);
}
@@ -433,13 +432,13 @@ camel_mime_part_set_encoding (CamelMimePart *mime_part, gchar *encoding)
-static const gchar *
+static CamelMimePartEncodingType
_get_encoding (CamelMimePart *mime_part)
{
return mime_part->encoding;
}
-const gchar *
+const CamelMimePartEncodingType
camel_mime_part_get_encoding (CamelMimePart *mime_part)
{
return CMP_CLASS(mime_part)->get_encoding (mime_part);
@@ -620,6 +619,7 @@ static void
_write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream)
{
CamelMedium *medium = CAMEL_MEDIUM (mime_part);
+ CamelStream *wrapper_stream;
guint buffer_size;
gchar *buffer;
gchar *encoded_buffer;
@@ -629,23 +629,27 @@ _write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream)
CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::_write_content_to_stream, content=%p\n", content);
if (!content) return;
- /* buffer_size = camel_data_wrapper_size (content); */
- /* buffer = g_malloc (buffer_size); */
-
- camel_data_wrapper_write_to_stream (content, stream);
-
-#if 0
- //if (mime_part->encoding) {
- // encoded_buffer_size = gmime_encoded_size(buffer, buffer_size, encoding);
- // encoded_buffer = g_malloc (encoded_buffer_size);
- // gmime_encode_buffer (buffer, encoded_buffer, encoding);
- // camel_stream_write (stream, encoded_buffer, encoded_buffer_size);
- // g_free (encoded_buffer);
- //} else
- //fwrite (buffer, buffer_size, 1, file);
- //camel_stream_write (stream, buffer, buffer_size);
- //g_free (buffer);
-#endif
+ switch (mime_part->encoding) {
+ case CAMEL_MIME_PART_ENCODING_DEFAULT:
+ case CAMEL_MIME_PART_ENCODING_7BIT:
+ case CAMEL_MIME_PART_ENCODING_8BIT:
+ camel_data_wrapper_write_to_stream (content, stream);
+ break;
+ case CAMEL_MIME_PART_ENCODING_BASE64:
+ wrapper_stream = camel_data_wrapper_get_stream (content);
+ if (wrapper_stream == NULL) {
+ /* FIXME in this case, we should probably copy stuff
+ in-memory and make sure things work anyway. */
+ g_warning ("Class `%s' does not implement `get_stream'",
+ gtk_type_name (GTK_OBJECT (content)->klass->type));
+ }
+ gmime_encode_base64 (wrapper_stream, stream);
+ break;
+ default:
+ g_warning ("Encoding type `%s' not supported.",
+ camel_mime_part_encoding_to_string
+ (mime_part->encoding));
+ }
CAMEL_LOG_FULL_DEBUG ( "Leaving CamelMimePart::_write_content_to_stream\n");
}
@@ -665,7 +669,8 @@ _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::write_to_stream writing content-disposition\n");
gmime_content_field_write_to_stream(mp->disposition, stream);
CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::write_to_stream writing content-transfer-encoding\n");
- WHPT (stream, "Content-Transfer-Encoding", mp->encoding);
+ WHPT (stream, "Content-Transfer-Encoding",
+ camel_mime_part_encoding_to_string (mp->encoding));
CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::write_to_stream writing content-description\n");
WHPT (stream, "Content-Description", mp->description);
CAMEL_LOG_FULL_DEBUG ( "CamelMimePart::write_to_stream writing content-MD5\n");
@@ -733,7 +738,9 @@ _parse_header_pair (CamelMimePart *mime_part, gchar *header_name, gchar *header_
"CamelMimePart::parse_header_pair found HEADER_ENCODING: %s\n",
header_value);
- camel_mime_part_set_encoding (mime_part, header_value);
+ camel_mime_part_set_encoding
+ (mime_part,
+ camel_mime_part_encoding_from_string (header_value));
header_handled = TRUE;
break;
@@ -767,7 +774,7 @@ _parse_header_pair (CamelMimePart *mime_part, gchar *header_name, gchar *header_
}
-void
+static void
_construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
{
@@ -782,6 +789,41 @@ _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
}
+const gchar *
+camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding)
+{
+ switch (encoding) {
+ case CAMEL_MIME_PART_ENCODING_DEFAULT:
+ case CAMEL_MIME_PART_ENCODING_7BIT:
+ return "7bit";
+ case CAMEL_MIME_PART_ENCODING_8BIT:
+ return "8bit";
+ case CAMEL_MIME_PART_ENCODING_BASE64:
+ return "base64";
+ case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE:
+ return "quoted-printable";
+ }
+}
+
+
+/* FIXME I am not sure this is the correct way to do this. */
+CamelMimePartEncodingType
+camel_mime_part_encoding_from_string (const gchar *string)
+{
+ if (strncmp (string, "7bit") == 0)
+ return CAMEL_MIME_PART_ENCODING_7BIT;
+ else if (strncmp (string, "8bit") == 0)
+ return CAMEL_MIME_PART_ENCODING_8BIT;
+ else if (strncmp (string, "base64") == 0)
+ return CAMEL_MIME_PART_ENCODING_BASE64;
+ else if (strncmp (string, "quoted-printable") == 0)
+ return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE;
+ else
+ /* FIXME? Spit a warning? */
+ return CAMEL_MIME_PART_ENCODING_DEFAULT;
+}
+
+
/******************************/
/** Misc utility functions **/
diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h
index 37766568f5..375d4aa0e3 100644
--- a/camel/camel-mime-part.h
+++ b/camel/camel-mime-part.h
@@ -45,6 +45,17 @@ extern "C" {
#define IS_CAMEL_MIME_PART(o) (GTK_CHECK_TYPE((o), CAMEL_MIME_PART_TYPE))
+enum _CamelMimePartEncodingType {
+ CAMEL_MIME_PART_ENCODING_DEFAULT,
+ CAMEL_MIME_PART_ENCODING_7BIT,
+ CAMEL_MIME_PART_ENCODING_8BIT,
+ CAMEL_MIME_PART_ENCODING_BASE64,
+ CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE,
+ CAMEL_MIME_PART_NUM_ENCODINGS
+};
+typedef enum _CamelMimePartEncodingType CamelMimePartEncodingType;
+
+
/* Do not change these values directly, you
would regret it one day */
typedef struct
@@ -57,7 +68,7 @@ typedef struct
gchar *content_id;
gchar *content_MD5;
GList *content_languages;
- gchar *encoding;
+ CamelMimePartEncodingType encoding;
gchar *filename;
GList *header_lines;
@@ -82,8 +93,8 @@ typedef struct {
const gchar * (*get_content_id) (CamelMimePart *mime_part);
void (*set_content_MD5) (CamelMimePart *mime_part, gchar *content_MD5);
const gchar * (*get_content_MD5) (CamelMimePart *mime_part);
- void (*set_encoding) (CamelMimePart *mime_part, gchar *encoding);
- const gchar * (*get_encoding) (CamelMimePart *mime_part);
+ void (*set_encoding) (CamelMimePart *mime_part, CamelMimePartEncodingType type);
+ const CamelMimePartEncodingType (*get_encoding) (CamelMimePart *mime_part);
void (*set_content_languages) (CamelMimePart *mime_part, GList *content_languages);
const GList * (*get_content_languages) (CamelMimePart *mime_part);
void (*set_header_lines) (CamelMimePart *mime_part, GList *header_lines);
@@ -116,8 +127,8 @@ const gchar *camel_mime_part_get_filename (CamelMimePart *mime_part);
const gchar *camel_mime_part_get_content_id (CamelMimePart *mime_part);
const gchar *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part);
void camel_mime_part_set_encoding (CamelMimePart *mime_part,
- gchar *encoding);
-const gchar *camel_mime_part_get_encoding (CamelMimePart *mime_part);
+ CamelMimePartEncodingType type);
+CamelMimePartEncodingType camel_mime_part_get_encoding (CamelMimePart *mime_part);
void camel_mime_part_set_content_languages (CamelMimePart *mime_part,
GList *content_languages);
const GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part);
@@ -127,12 +138,13 @@ const GList *camel_mime_part_get_header_lines (CamelMimePart *mime_part);
GMimeContentField *camel_mime_part_get_content_type (CamelMimePart *mime_part);
+const gchar *camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding);
+CamelMimePartEncodingType camel_mime_part_encoding_from_string (const gchar *string);
+
/* utility functions */
void camel_mime_part_set_text (CamelMimePart *camel_mime_part, const gchar *text);
-
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/camel/camel-simple-data-wrapper-stream.c b/camel/camel-simple-data-wrapper-stream.c
new file mode 100644
index 0000000000..8c45c7530d
--- /dev/null
+++ b/camel/camel-simple-data-wrapper-stream.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* camel-simple-data-wrapper-stream.c
+ *
+ * Copyright 1999 International GNOME Support (http://www.gnome-support.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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "camel-simple-data-wrapper-stream.h"
+
+
+static CamelStreamClass *parent_class = NULL;
+
+
+/* CamelStream methods. */
+
+static gint
+read (CamelStream *stream,
+ gchar *buffer,
+ gint n)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint len;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ len = MIN (n, array->len - wrapper_stream->current_position);
+ if (len > 0) {
+ memcpy (buffer, array->data, len);
+ wrapper_stream->current_position += len;
+ return len;
+ } else {
+ return 0;
+ }
+}
+
+static gint
+write (CamelStream *stream,
+ const gchar *buffer,
+ gint n)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint len;
+ const gchar *buffer_next;
+ gint left;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ len = MIN (n, array->len - wrapper_stream->current_position);
+ if (len > 0) {
+ memcpy (array->data, buffer, len);
+ buffer_next = buffer + len;
+ left = n - len;
+ } else {
+ /* If we are past the end of the array, fill with zeros. */
+ if (wrapper_stream->current_position > array->len) {
+ gint saved_length;
+
+ saved_length = array->len;
+ g_byte_array_set_size
+ (array, wrapper_stream->current_position);
+ memset (array->data + saved_length,
+ 0,
+ (wrapper_stream->current_position
+ - saved_length));
+ }
+
+ buffer_next = buffer;
+ left = n;
+ }
+
+ if (n > 0)
+ g_byte_array_append (array, buffer_next, left);
+
+ wrapper_stream->current_position += n;
+ return n;
+}
+
+static void
+flush (CamelStream *stream)
+{
+ /* No op, as we don't do any buffering. */
+}
+
+static gint
+available (CamelStream *stream)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint available;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ available = array->len - wrapper_stream->current_position;
+ return MAX (available, 0);
+}
+
+static gboolean
+eos (CamelStream *stream)
+{
+ if (available (stream) > 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+close (CamelStream *stream)
+{
+ /* Nothing to do, we have no associated file descriptor. */
+}
+
+static gint
+seek (CamelStream *stream,
+ gint offset,
+ CamelStreamSeekPolicy policy)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ gint new_position;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+
+ switch (policy) {
+ case CAMEL_STREAM_SET:
+ new_position = offset;
+ break;
+ case CAMEL_STREAM_CUR:
+ new_position = wrapper_stream->current_position + offset;
+ break;
+ case CAMEL_STREAM_END:
+ new_position = wrapper_stream->wrapper->byte_array->len;
+ break;
+ default:
+ g_warning ("Unknown CamelStreamSeekPolicy %d.", policy);
+ return -1;
+ }
+
+ wrapper_stream->current_position = new_position;
+ return new_position;
+}
+
+
+/* This handles destruction of the associated CamelDataWrapper. */
+/* Hm, this should never happen though, because we gtk_object_ref() the
+ wrapper. */
+static void
+wrapper_destroy_cb (GtkObject *object,
+ gpointer data)
+{
+ CamelSimpleDataWrapperStream *stream;
+
+ g_warning ("CamelSimpleDataWrapperStream: associated CamelSimpleDataWrapper was destroyed.");
+ stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
+ stream->wrapper = NULL;
+}
+
+
+/* GtkObject methods. */
+
+static void
+destroy (GtkObject *object)
+{
+ CamelSimpleDataWrapperStream *stream;
+
+ stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
+
+ gtk_object_unref (GTK_OBJECT (stream->wrapper));
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+static void
+class_init (CamelSimpleDataWrapperStreamClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ parent_class = gtk_type_class (camel_stream_get_type ());
+}
+
+static void
+init (CamelSimpleDataWrapperStream *simple_data_wrapper_stream)
+{
+ simple_data_wrapper_stream->current_position = 0;
+}
+
+
+GtkType
+camel_simple_data_wrapper_stream_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (type == 0) {
+ static const GtkTypeInfo info = {
+ "CamelSimpleDataWrapperStream",
+ sizeof (CamelSimpleDataWrapperStream),
+ sizeof (CamelSimpleDataWrapperStreamClass),
+ (GtkClassInitFunc) class_init,
+ (GtkObjectInitFunc) init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (camel_stream_get_type (), &info);
+ }
+
+ return type;
+}
+
+void
+camel_simple_data_wrapper_stream_construct (CamelSimpleDataWrapperStream *stream,
+ CamelSimpleDataWrapper *wrapper)
+{
+ g_return_if_fail (stream != NULL);
+ g_return_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream));
+ g_return_if_fail (wrapper != NULL);
+ g_return_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER (wrapper));
+
+ gtk_object_ref (GTK_OBJECT (wrapper));
+ stream->wrapper = wrapper;
+ gtk_signal_connect (GTK_OBJECT (wrapper), "destroy",
+ wrapper_destroy_cb, stream);
+}
+
+CamelStream *
+camel_simple_data_wrapper_stream_new (CamelSimpleDataWrapper *wrapper)
+{
+ CamelStream *stream;
+
+ g_return_val_if_fail (wrapper != NULL, NULL);
+ g_return_val_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER (wrapper), NULL);
+
+ stream = gtk_type_new (camel_simple_data_wrapper_stream_get_type ());
+
+ camel_simple_data_wrapper_stream_construct
+ (CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream), wrapper);
+
+ return stream;
+}
diff --git a/camel/camel-simple-data-wrapper-stream.h b/camel/camel-simple-data-wrapper-stream.h
new file mode 100644
index 0000000000..ee24fd71d3
--- /dev/null
+++ b/camel/camel-simple-data-wrapper-stream.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* camel-simple-data-wrapper-stream.h
+ *
+ * Copyright 1999 International GNOME Support (http://www.gnome-support.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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ */
+
+#ifndef __CAMEL_SIMPLE_DATA_WRAPPER_STREAM_H__
+#define __CAMEL_SIMPLE_DATA_WRAPPER_STREAM_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "camel-simple-data-wrapper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define CAMEL_TYPE_SIMPLE_DATA_WRAPPER_STREAM \
+ (camel_simple_data_wrapper_stream_get_type ())
+#define CAMEL_SIMPLE_DATA_WRAPPER_STREAM(obj) \
+ (GTK_CHECK_CAST ((obj), CAMEL_TYPE_SIMPLE_DATA_WRAPPER_STREAM, CamelSimpleDataWrapperStream))
+#define CAMEL_SIMPLE_DATA_WRAPPER_STREAM_CLASS(klass) \
+ (GTK_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_SIMPLE_DATA_WRAPPER_STREAM, CamelSimpleDataWrapperStreamClass))
+#define IS_CAMEL_SIMPLE_DATA_WRAPPER_STREAM(obj) \
+ (GTK_CHECK_TYPE ((obj), CAMEL_TYPE_SIMPLE_DATA_WRAPPER_STREAM))
+#define IS_CAMEL_SIMPLE_DATA_WRAPPER_STREAM_CLASS(klass) \
+ (GTK_CHECK_CLASS_TYPE ((obj), CAMEL_TYPE_SIMPLE_DATA_WRAPPER_STREAM))
+
+
+typedef struct _CamelSimpleDataWrapperStream CamelSimpleDataWrapperStream;
+typedef struct _CamelSimpleDataWrapperStreamClass CamelSimpleDataWrapperStreamClass;
+
+struct _CamelSimpleDataWrapperStream {
+ CamelStream parent;
+
+ CamelSimpleDataWrapper *wrapper;
+ gint current_position;
+};
+
+struct _CamelSimpleDataWrapperStreamClass {
+ CamelStreamClass parent_class;
+};
+
+
+GtkType camel_simple_data_wrapper_stream_get_type (void);
+CamelStream *camel_simple_data_wrapper_stream_new (CamelSimpleDataWrapper *wrapper);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CAMEL_SIMPLE_DATA_WRAPPER_STREAM_H__ */
diff --git a/camel/camel-simple-data-wrapper.c b/camel/camel-simple-data-wrapper.c
index 073561a1a1..fb1c682814 100644
--- a/camel/camel-simple-data-wrapper.c
+++ b/camel/camel-simple-data-wrapper.c
@@ -25,7 +25,9 @@
* USA
*/
#include <config.h>
+
#include "camel-simple-data-wrapper.h"
+#include "camel-simple-data-wrapper-stream.h"
#include "camel-log.h"
static CamelDataWrapperClass *parent_class=NULL;
@@ -36,6 +38,7 @@ static CamelDataWrapperClass *parent_class=NULL;
static void _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
static void _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
static void _finalize (GtkObject *object);
+static CamelStream *_get_stream (CamelDataWrapper *data_wrapper);
static void
camel_simple_data_wrapper_class_init (CamelSimpleDataWrapperClass *camel_simple_data_wrapper_class)
@@ -50,13 +53,17 @@ camel_simple_data_wrapper_class_init (CamelSimpleDataWrapperClass *camel_simple_
camel_data_wrapper_class->write_to_stream = _write_to_stream;
camel_data_wrapper_class->construct_from_stream = _construct_from_stream;
+ camel_data_wrapper_class->get_stream = _get_stream;
+
gtk_object_class->finalize = _finalize;
}
-
-
-
+static void
+camel_simple_data_wrapper_init (CamelSimpleDataWrapper *wrapper)
+{
+ wrapper->stream = NULL;
+}
GtkType
camel_simple_data_wrapper_get_type (void)
@@ -70,7 +77,7 @@ camel_simple_data_wrapper_get_type (void)
sizeof (CamelSimpleDataWrapper),
sizeof (CamelSimpleDataWrapperClass),
(GtkClassInitFunc) camel_simple_data_wrapper_class_init,
- (GtkObjectInitFunc) NULL,
+ (GtkObjectInitFunc) camel_simple_data_wrapper_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
@@ -134,8 +141,6 @@ _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
}
-
-
#define _CMSDW_TMP_BUF_SIZE 100
static void
_construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
@@ -206,3 +211,20 @@ camel_simple_data_wrapper_set_text (CamelSimpleDataWrapper *simple_data_wrapper,
CAMEL_LOG_FULL_DEBUG ("CamelSimpleDataWrapper:: Entering set_text\n");
}
+
+
+static CamelStream *
+_get_stream (CamelDataWrapper *data_wrapper)
+{
+ CamelSimpleDataWrapper *simple_data_wrapper;
+
+ simple_data_wrapper = CAMEL_SIMPLE_DATA_WRAPPER (data_wrapper);
+ if (simple_data_wrapper->stream == NULL) {
+ CamelStream *s;
+
+ s = camel_simple_data_wrapper_stream_new (simple_data_wrapper);
+ simple_data_wrapper->stream = s;
+ }
+
+ return simple_data_wrapper->stream;
+}
diff --git a/camel/camel-simple-data-wrapper.h b/camel/camel-simple-data-wrapper.h
index b999722cc1..b3be850f9d 100644
--- a/camel/camel-simple-data-wrapper.h
+++ b/camel/camel-simple-data-wrapper.h
@@ -53,7 +53,7 @@ typedef struct
CamelDataWrapper parent_object;
GByteArray *byte_array;
-
+ CamelStream *stream;
} CamelSimpleDataWrapper;
diff --git a/camel/camel-stream-data-wrapper.c b/camel/camel-stream-data-wrapper.c
new file mode 100644
index 0000000000..564571cf09
--- /dev/null
+++ b/camel/camel-stream-data-wrapper.c
@@ -0,0 +1,209 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* camel-stream-data-wrapper.c
+ *
+ * Copyright 1999 International GNOME Support (http://www.gnome-support.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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "camel-stream-data-wrapper.h"
+
+
+static CamelDataWrapperClass *parent_class = NULL;
+
+
+/* CamelDataWrapper methods. */
+
+static void
+write_to_stream (CamelDataWrapper *data_wrapper,
+ CamelStream *output_stream)
+{
+#define BUFFER_SIZE 4096
+ gchar buffer[BUFFER_SIZE];
+ CamelStreamDataWrapper *stream_data_wrapper;
+ CamelStream *input_stream;
+
+ stream_data_wrapper = CAMEL_STREAM_DATA_WRAPPER (data_wrapper);
+ input_stream = stream_data_wrapper->stream;
+
+ while (TRUE) {
+ gchar *p;
+ gint read, written;
+
+ read = camel_stream_read (input_stream, buffer, BUFFER_SIZE);
+ if (read == 0)
+ break;
+
+ p = buffer;
+ while (read > 0) {
+ written = camel_stream_write (output_stream, p, read);
+
+ /* FIXME no way to report an error?! */
+ if (written == -1)
+ break;
+
+ p += written;
+ read -= written;
+ }
+ }
+#undef BUFFER_SIZE
+}
+
+static CamelStream *
+get_stream (CamelDataWrapper *data_wrapper)
+{
+ CamelStreamDataWrapper *stream_data_wrapper;
+
+ stream_data_wrapper = CAMEL_STREAM_DATA_WRAPPER (data_wrapper);
+ return stream_data_wrapper->stream;
+}
+
+
+/* GtkObject methods. */
+
+static void
+destroy (GtkObject *object)
+{
+ CamelStreamDataWrapper *stream_data_wrapper;
+ GtkObject *stream_object;
+
+ stream_data_wrapper = CAMEL_STREAM_DATA_WRAPPER (object);
+
+ stream_object = GTK_OBJECT (object);
+ stream_data_wrapper->stream = NULL;
+
+ gtk_object_unref (stream_object);
+}
+
+
+/* This handles destruction of the associated CamelDataWrapper outside
+ CamelStreamDataWrapper, for debuggin purposes (this should never happen). */
+static void
+stream_destroy_cb (GtkObject *object,
+ gpointer data)
+{
+ CamelStreamDataWrapper *wrapper;
+
+ wrapper = CAMEL_STREAM_DATA_WRAPPER (data);
+
+ /* Hack: when we destroy the stream ourselves, we set the `stream'
+ member to NULL first, so that we can recognize when this is done out
+ of our control. */
+ if (wrapper->stream != NULL) {
+ g_warning ("CamelSimpleDataWrapperStream: associated CamelSimpleDataWrapper was destroyed.");
+ wrapper->stream = NULL;
+ }
+}
+
+
+static void
+class_init (CamelStreamDataWrapperClass *class)
+{
+ GtkObjectClass *object_class;
+ CamelDataWrapperClass *data_wrapper_class;
+
+ object_class = GTK_OBJECT_CLASS (class);
+ object_class->destroy = destroy;
+
+ data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
+ data_wrapper_class->write_to_stream = write_to_stream;
+ data_wrapper_class->get_stream = get_stream;
+
+ parent_class = gtk_type_class (camel_data_wrapper_get_type ());
+}
+
+static void
+init (CamelStreamDataWrapper *wrapper)
+{
+ wrapper->stream = NULL;
+}
+
+
+GtkType
+camel_stream_data_wrapper_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (type == 0) {
+ static const GtkTypeInfo info = {
+ "CamelStreamDataWrapper",
+ sizeof (CamelStreamDataWrapper),
+ sizeof (CamelStreamDataWrapperClass),
+ (GtkClassInitFunc) class_init,
+ (GtkObjectInitFunc) init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (camel_data_wrapper_get_type (), &info);
+ }
+
+ return type;
+}
+
+/**
+ * camel_stream_data_wrapper_construct:
+ * @wrapper: A CamelStreamDataWrapper object
+ * @stream: A Camel stream object
+ *
+ * Construct @wrapper associating @stream to it. Notice that, after this call,
+ * @stream is conceptually owned by @wrapper and will be destroyed when
+ * @wrapper is destroyed.
+ **/
+void
+camel_stream_data_wrapper_construct (CamelStreamDataWrapper *wrapper,
+ CamelStream *stream)
+{
+ g_return_if_fail (wrapper != NULL);
+ g_return_if_fail (IS_CAMEL_STREAM_DATA_WRAPPER (wrapper));
+ g_return_if_fail (stream != NULL);
+ g_return_if_fail (IS_CAMEL_STREAM (stream));
+
+ wrapper->stream = stream;
+ gtk_signal_connect (GTK_OBJECT (stream), "destroy",
+ GTK_SIGNAL_FUNC (stream_destroy_cb), wrapper);
+}
+
+/**
+ * camel_stream_data_wrapper_new:
+ * @stream: A Camel stream object
+ *
+ * Create a new stream data wrapper object for @stream. Notice that, after
+ * this call, @stream is conceptually owned by the new wrapper and will be
+ * destroyed when the wrapper is destroyed.
+ *
+ * Return value: A pointer to the new CamelStreamDataWrapper object.
+ **/
+CamelDataWrapper *
+camel_stream_data_wrapper_new (CamelStream *stream)
+{
+ CamelDataWrapper *wrapper;
+
+ wrapper = gtk_type_new (camel_stream_data_wrapper_get_type ());
+ camel_stream_data_wrapper_construct
+ (CAMEL_STREAM_DATA_WRAPPER (wrapper), stream);
+
+ return wrapper;
+}
diff --git a/camel/camel-stream-data-wrapper.h b/camel/camel-stream-data-wrapper.h
new file mode 100644
index 0000000000..3f972a99f9
--- /dev/null
+++ b/camel/camel-stream-data-wrapper.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* camel-stream-data-wrapper.h
+ *
+ * Copyright 1999 International GNOME Support (http://www.gnome-support.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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ */
+
+#ifndef __CAMEL_STREAM_DATA_WRAPPER_H__
+#define __CAMEL_STREAM_DATA_WRAPPER_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include "camel-data-wrapper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+
+#define CAMEL_TYPE_STREAM_DATA_WRAPPER \
+ (camel_stream_data_wrapper_get_type ())
+#define CAMEL_STREAM_DATA_WRAPPER(obj) \
+ (GTK_CHECK_CAST ((obj), CAMEL_TYPE_STREAM_DATA_WRAPPER, CamelStreamDataWrapper))
+#define CAMEL_STREAM_DATA_WRAPPER_CLASS(klass) \
+ (GTK_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_STREAM_DATA_WRAPPER, CamelStreamDataWrapperClass))
+#define IS_CAMEL_STREAM_DATA_WRAPPER(obj) \
+ (GTK_CHECK_TYPE ((obj), CAMEL_TYPE_STREAM_DATA_WRAPPER))
+#define IS_CAMEL_STREAM_DATA_WRAPPER_CLASS(klass) \
+ (GTK_CHECK_CLASS_TYPE ((obj), CAMEL_TYPE_STREAM_DATA_WRAPPER))
+
+
+typedef struct _CamelStreamDataWrapper CamelStreamDataWrapper;
+typedef struct _CamelStreamDataWrapperClass CamelStreamDataWrapperClass;
+
+struct _CamelStreamDataWrapper {
+ CamelDataWrapper parent;
+
+ CamelStream *stream;
+};
+
+struct _CamelStreamDataWrapperClass {
+ CamelDataWrapperClass parent_class;
+};
+
+
+GtkType camel_stream_data_wrapper_get_type (void);
+CamelDataWrapper *camel_stream_data_wrapper_new (CamelStream *stream);
+void camel_stream_data_wrapper_construct (CamelStreamDataWrapper *wrapper,
+ CamelStream *stream);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CAMEL_STREAM_DATA_WRAPPER_H__ */
diff --git a/camel/gmime-base64.c b/camel/gmime-base64.c
index a9e596d2dc..db784f7143 100644
--- a/camel/gmime-base64.c
+++ b/camel/gmime-base64.c
@@ -30,15 +30,12 @@ gmime_encode_base64 (CamelStream *input, CamelStream *output)
char buffer [BSIZE];
char obuf [80]; /* Output is limited to 76 characters, rfc2045 */
int n, i, j, state;
- long bytes;
-
- j = 0;
+ int keep = 0;
+
state = 0;
- bytes = 0;
- while ((n = camel_stream_read (input, &buffer, sizeof (buffer))) > 0){
- int keep = 0;
-
- for (i = 0; i < n; i++, state++, bytes++){
+ j = 0;
+ while ((n = camel_stream_read (input, buffer, sizeof (buffer))) > 0){
+ for (i = 0; i < n; i++, state++){
char c = buffer [i];
switch (state % 3){
@@ -48,21 +45,23 @@ gmime_encode_base64 (CamelStream *input, CamelStream *output)
break;
case 1:
obuf [j++] = base64_alphabet [keep | (c >> 4)];
- keep = (c & 0xf) << 4;
+ keep = (c & 0xf) << 2;
break;
case 2:
obuf [j++] = base64_alphabet [keep | (c >> 6)];
obuf [j++] = base64_alphabet [c & 0x3f];
break;
}
-
- if ((bytes % 72) == 0){
+
+ if (j == 72){
obuf [j++] = '\r';
obuf [j++] = '\n';
camel_stream_write (output, obuf, j);
+ j = 0;
}
}
}
+
switch (state % 3){
case 0:
/* full ouput, nothing left to do */
diff --git a/camel/gmime-base64.h b/camel/gmime-base64.h
new file mode 100644
index 0000000000..58ddd58722
--- /dev/null
+++ b/camel/gmime-base64.h
@@ -0,0 +1,16 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Base64 handlers
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ */
+
+#ifndef _GMIME_BASE64_H
+#define _GMIME_BASE64_H
+
+#include "camel-stream.h"
+
+void gmime_encode_base64 (CamelStream *input, CamelStream *output);
+
+#endif
diff --git a/doc/Camel-Classes b/doc/Camel-Classes
index 32aa0c6029..da32d69460 100644
--- a/doc/Camel-Classes
+++ b/doc/Camel-Classes
@@ -3,6 +3,7 @@ CamelProvider
CamelThreadProxy
GtkObject
+ CamelDataWrapper
+ | + CameStreamDataWrapper
| + CamelMedium
| | + CamelMimePart
| | + CamelMimeBodyPart
@@ -16,6 +17,7 @@ GtkObject
| + CamelStore
+ CamelSession
+ CamelStream
+ | + CameDataWrapperStream
| + CamelStreamFs
| + CamelStreamBufferedFs
| + CamelStreamMem
diff --git a/help/Camel-Classes b/help/Camel-Classes
index 32aa0c6029..da32d69460 100644
--- a/help/Camel-Classes
+++ b/help/Camel-Classes
@@ -3,6 +3,7 @@ CamelProvider
CamelThreadProxy
GtkObject
+ CamelDataWrapper
+ | + CameStreamDataWrapper
| + CamelMedium
| | + CamelMimePart
| | + CamelMimeBodyPart
@@ -16,6 +17,7 @@ GtkObject
| + CamelStore
+ CamelSession
+ CamelStream
+ | + CameDataWrapperStream
| + CamelStreamFs
| + CamelStreamBufferedFs
| + CamelStreamMem
diff --git a/tests/test1.c b/tests/test1.c
index 2ee5241ad1..1adaf0b163 100644
--- a/tests/test1.c
+++ b/tests/test1.c
@@ -1,10 +1,13 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdio.h>
+
#include "camel-mime-message.h"
#include "camel-mime-body-part.h"
#include "camel-multipart.h"
-#include "stdio.h"
#include "camel-stream.h"
#include "camel-stream-fs.h"
+#include "camel-stream-data-wrapper.h"
#include "camel-log.h"
#include "camel.h"
@@ -14,12 +17,33 @@ main (int argc, char**argv)
CamelMimeMessage *message;
CamelMultipart *multipart;
CamelMimeBodyPart *body_part;
+ CamelMimeBodyPart *attachment_part;
+ CamelStream *attachment_stream;
/* FILE *output_file; */
CamelStream *stream;
gtk_init (&argc, &argv);
camel_init ();
+
+ if (argc < 2) {
+ attachment_stream = NULL;
+ } else {
+ if (argc == 2) {
+ attachment_stream = camel_stream_fs_new_with_name
+ (argv[1], CAMEL_STREAM_FS_READ);
+ if (attachment_stream == NULL) {
+ fprintf (stderr, "Cannot open `%s'\n",
+ argv[1]);
+ return 1;
+ }
+ } else {
+ fprintf (stderr, "Usage: %s [<attachment>]\n",
+ argv[0]);
+ return 1;
+ }
+ }
+
message = camel_mime_message_new_with_session ((CamelSession *)NULL);
camel_mime_part_set_description (CAMEL_MIME_PART (message), "a test");
@@ -40,11 +64,29 @@ main (int argc, char**argv)
camel_mime_message_add_recipient (message, RECIPIENT_TYPE_CC, g_strdup ("maury@justmagic.com"));
camel_mime_message_add_recipient (message, RECIPIENT_TYPE_BCC, g_strdup ("Bertrand.Guiheneuf@aful.org"));
-
multipart = camel_multipart_new ();
body_part = camel_mime_body_part_new ();
camel_mime_part_set_text (CAMEL_MIME_PART (body_part), "This is a test.\nThis is only a test.\n");
camel_multipart_add_part (multipart, body_part);
+
+ if (attachment_stream == NULL) {
+ attachment_part = NULL;
+ } else {
+ CamelDataWrapper *stream_wrapper;
+
+ stream_wrapper = camel_stream_data_wrapper_new
+ (attachment_stream);
+
+ attachment_part = camel_mime_body_part_new ();
+ camel_mime_part_set_encoding (CAMEL_MIME_PART (attachment_part),
+ CAMEL_MIME_PART_ENCODING_BASE64);
+ camel_medium_set_content_object (CAMEL_MEDIUM (attachment_part),
+ stream_wrapper);
+ camel_multipart_add_part (multipart, attachment_part);
+
+ gtk_object_unref (GTK_OBJECT (stream_wrapper));
+ }
+
camel_medium_set_content_object (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (multipart));
stream = camel_stream_fs_new_with_name ("mail1.test", CAMEL_STREAM_FS_WRITE );
@@ -53,13 +95,17 @@ main (int argc, char**argv)
exit(2);
}
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message),
+ stream);
camel_stream_close (stream);
gtk_object_unref (GTK_OBJECT (stream));
gtk_object_unref (GTK_OBJECT (message));
gtk_object_unref (GTK_OBJECT (multipart));
gtk_object_unref (GTK_OBJECT (body_part));
+
+ if (attachment_part != NULL)
+ gtk_object_unref (GTK_OBJECT (attachment_part));
printf ("Test1 finished\n");
return 1;