From ca7044930f42a698fd88f914c2512a20e2eeaae9 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Wed, 17 Nov 1999 14:39:25 +0000 Subject: 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 --- camel/Makefile.am | 5 + camel/camel-data-wrapper.c | 13 ++ camel/camel-data-wrapper.h | 2 + camel/camel-mime-message.c | 5 + camel/camel-mime-part.c | 102 ++++++++---- camel/camel-mime-part.h | 26 ++- camel/camel-simple-data-wrapper-stream.c | 276 +++++++++++++++++++++++++++++++ camel/camel-simple-data-wrapper-stream.h | 74 +++++++++ camel/camel-simple-data-wrapper.c | 34 +++- camel/camel-simple-data-wrapper.h | 2 +- camel/camel-stream-data-wrapper.c | 209 +++++++++++++++++++++++ camel/camel-stream-data-wrapper.h | 75 +++++++++ camel/gmime-base64.c | 21 ++- camel/gmime-base64.h | 16 ++ 14 files changed, 805 insertions(+), 55 deletions(-) create mode 100644 camel/camel-simple-data-wrapper-stream.c create mode 100644 camel/camel-simple-data-wrapper-stream.h create mode 100644 camel/camel-stream-data-wrapper.c create mode 100644 camel/camel-stream-data-wrapper.h create mode 100644 camel/gmime-base64.h (limited to 'camel') 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 +#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 +#endif + +#include + +#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 + #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 +#endif + +#include + +#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 +#endif + +#include +#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 -- cgit v1.2.3