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
This commit is contained in:
Ettore Perazzoli
1999-11-17 14:39:25 +00:00
parent 16de3313b7
commit ca7044930f
18 changed files with 925 additions and 58 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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);
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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 **/

View File

@ -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 */

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -53,7 +53,7 @@ typedef struct
CamelDataWrapper parent_object;
GByteArray *byte_array;
CamelStream *stream;
} CamelSimpleDataWrapper;

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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 */

16
camel/gmime-base64.h Normal file
View File

@ -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

View File

@ -3,6 +3,7 @@ CamelProvider
CamelThreadProxy
GtkObject
+ CamelDataWrapper
| + CameStreamDataWrapper
| + CamelMedium
| | + CamelMimePart
| | + CamelMimeBodyPart
@ -16,6 +17,7 @@ GtkObject
| + CamelStore
+ CamelSession
+ CamelStream
| + CameDataWrapperStream
| + CamelStreamFs
| + CamelStreamBufferedFs
| + CamelStreamMem

View File

@ -3,6 +3,7 @@ CamelProvider
CamelThreadProxy
GtkObject
+ CamelDataWrapper
| + CameStreamDataWrapper
| + CamelMedium
| | + CamelMimePart
| | + CamelMimeBodyPart
@ -16,6 +17,7 @@ GtkObject
| + CamelStore
+ CamelSession
+ CamelStream
| + CameDataWrapperStream
| + CamelStreamFs
| + CamelStreamBufferedFs
| + CamelStreamMem

View File

@ -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;