From 6881fd1bf710f0ce0bd55f9975855bb23622077a Mon Sep 17 00:00:00 2001 From: bertrand Date: Tue, 24 Aug 1999 21:01:10 +0000 Subject: new class. Will handle all sort of information media (Mime mail messages, 1999-08-24 bertrand * camel/camel-medium.c (camel_medium_class_init): new class. Will handle all sort of information media (Mime mail messages, Lotus Notes mail messages, postit notes, faxes, who knows .... :) CamelMimePart will inherit from it. * camel/camel-mime-part.c (_set_disposition): (_set_description): description and disposition parameters are now const. * camel/gmime-content-field.c (gmime_content_field_free): added assertion code. * camel/providers/MH/camel-mh-folder.c (_get_message): uses buffered stream. * camel/camel-stream-buffered-fs.c: new stream to accelerate file ops. Thanks to jwz, I've decided to add a level of abstraction to Camel. In the future, it should be able to handle other mail systems, but also non-mail information vehicles. Enough for today. Roller time! svn path=/trunk/; revision=1140 --- camel/Makefile.am | 4 + camel/camel-medium.c | 197 ++++++++++++++++++++++++++ camel/camel-medium.h | 87 ++++++++++++ camel/camel-mime-part.c | 29 ++-- camel/camel-mime-part.h | 8 +- camel/camel-stream-buffered-fs.c | 259 +++++++++++++++++++++++++++++++++++ camel/camel-stream-buffered-fs.h | 88 ++++++++++++ camel/camel-stream-fs.c | 50 +++++-- camel/camel-stream-fs.h | 2 + camel/gmime-content-field.c | 5 +- camel/providers/MH/camel-mh-folder.c | 67 ++++----- camel/providers/MH/camel-mh-folder.h | 1 + 12 files changed, 740 insertions(+), 57 deletions(-) create mode 100644 camel/camel-medium.c create mode 100644 camel/camel-medium.h create mode 100644 camel/camel-stream-buffered-fs.c create mode 100644 camel/camel-stream-buffered-fs.h (limited to 'camel') diff --git a/camel/Makefile.am b/camel/Makefile.am index 5f23d2ee9c..c6860a6845 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -17,6 +17,7 @@ libcamel_la_SOURCES = \ camel-data-wrapper.c \ camel-simple-data-wrapper.c \ camel-folder.c \ + camel-medium.c \ camel-mime-body-part.c \ camel-mime-message.c \ camel-mime-part.c \ @@ -26,6 +27,7 @@ libcamel_la_SOURCES = \ camel-session.c \ camel-store.c \ camel-stream.c \ + camel-stream-buffered-fs.c \ camel-stream-fs.c \ camel-stream-mem.c \ data-wrapper-repository.c \ @@ -43,6 +45,7 @@ libcamelinclude_HEADERS = \ camel-simple-data-wrapper.h \ camel-folder.h \ camel-mime-body-part.h \ + camel-medium.h \ camel-mime-message.h \ camel-mime-part.h \ camel-multipart.h \ @@ -51,6 +54,7 @@ libcamelinclude_HEADERS = \ camel-session.h \ camel-store.h \ camel-stream.h \ + camel-stream-buffered-fs.h \ camel-stream-fs.h \ camel-stream-mem.h \ data-wrapper-repository.h \ diff --git a/camel/camel-medium.c b/camel/camel-medium.c new file mode 100644 index 0000000000..8414432a07 --- /dev/null +++ b/camel/camel-medium.c @@ -0,0 +1,197 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camelMedium.c : Abstract class for a medium */ + + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 + */ +#include +#include "camel-medium.h" +#include +#include "gmime-content-field.h" +#include "string-utils.h" +#include "camel-log.h" +#include "gmime-utils.h" +#include "camel-simple-data-wrapper.h" + + + + + +static CamelDataWrapperClass *parent_class=NULL; + +/* Returns the class for a CamelMedium */ +#define CMP_CLASS(so) CAMEL_MEDIUM_CLASS (GTK_OBJECT(so)->klass) + +static void _add_header (CamelMedium *medium, gchar *header_name, gchar *header_value); +static void _remove_header (CamelMedium *medium, const gchar *header_name); +static const gchar *_get_header (CamelMedium *medium, const gchar *header_name); + + +static void _finalize (GtkObject *object); + +static void +camel_medium_class_init (CamelMediumClass *camel_medium_class) +{ + CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_medium_class); + GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_data_wrapper_class); + + parent_class = gtk_type_class (camel_data_wrapper_get_type ()); + + /* virtual method definition */ + camel_medium_class->add_header = _add_header; + camel_medium_class->remove_header = _remove_header; + camel_medium_class->get_header = _get_header; + + + + /* virtual method overload */ + // camel_data_wrapper_class->write_to_stream = _write_to_stream; + //camel_data_wrapper_class->construct_from_stream = _construct_from_stream; + + gtk_object_class->finalize = _finalize; +} + +static void +camel_medium_init (gpointer object, gpointer klass) +{ + CamelMedium *camel_medium = CAMEL_MEDIUM (object); + + camel_medium->headers = g_hash_table_new (g_str_hash, g_str_equal); +} + + + + +GtkType +camel_medium_get_type (void) +{ + static GtkType camel_medium_type = 0; + + if (!camel_medium_type) { + GtkTypeInfo camel_medium_info = + { + "CamelMedium", + sizeof (CamelMedium), + sizeof (CamelMediumClass), + (GtkClassInitFunc) camel_medium_class_init, + (GtkObjectInitFunc) camel_medium_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_medium_type = gtk_type_unique (camel_data_wrapper_get_type (), &camel_medium_info); + } + + return camel_medium_type; +} + + +static void +_finalize (GtkObject *object) +{ + CamelMedium *medium = CAMEL_MEDIUM (object); + + + CAMEL_LOG_FULL_DEBUG ("Entering CamelMedium::finalize\n"); + + if (medium->headers) { + g_hash_table_destroy (medium->headers); + } + + GTK_OBJECT_CLASS (parent_class)->finalize (object); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelMedium::finalize\n"); +} + + +static void +_add_header (CamelMedium *medium, gchar *header_name, gchar *header_value) +{ + gboolean header_exists; + gchar *old_header_name; + gchar *old_header_value; + + + header_exists = g_hash_table_lookup_extended (medium->headers, header_name, + (gpointer *) &old_header_name, + (gpointer *) &old_header_value); + if (header_exists) { + g_free (old_header_name); + g_free (old_header_value); + } + + g_hash_table_insert (medium->headers, header_name, header_value); +} + + +void +camel_medium_add_header (CamelMedium *medium, gchar *header_name, gchar *header_value) +{ + CMP_CLASS(medium)->add_header(medium, header_name, header_value); +} + + + +static void +_remove_header (CamelMedium *medium, const gchar *header_name) +{ + + gboolean header_exists; + gchar *old_header_name; + gchar *old_header_value; + + header_exists = g_hash_table_lookup_extended (medium->headers, header_name, + (gpointer *) &old_header_name, + (gpointer *) &old_header_value); + if (header_exists) { + g_free (old_header_name); + g_free (old_header_value); + } + + g_hash_table_remove (medium->headers, header_name); + +} + +void +camel_medium_remove_header (CamelMedium *medium, const gchar *header_name) +{ + CMP_CLASS(medium)->remove_header(medium, header_name); +} + + + +static const gchar * +_get_header (CamelMedium *medium, const gchar *header_name) +{ + + gchar *old_header_name; + gchar *old_header_value; + gchar *header_value; + + header_value = (gchar *)g_hash_table_lookup (medium->headers, header_name); + return header_value; +} + +const gchar * +camel_medium_get_header (CamelMedium *medium, const gchar *header_name) +{ + return CMP_CLASS(medium)->get_header (medium, header_name); +} + diff --git a/camel/camel-medium.h b/camel/camel-medium.h new file mode 100644 index 0000000000..c35466336c --- /dev/null +++ b/camel/camel-medium.h @@ -0,0 +1,87 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-medium.h : class for a medium object */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 + */ + + +#ifndef CAMEL_MEDIUM_H +#define CAMEL_MEDIUM_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include +#include "camel-data-wrapper.h" +#include "camel-stream.h" + + +#define CAMEL_MEDIUM_TYPE (camel_medium_get_type ()) +#define CAMEL_MEDIUM(obj) (GTK_CHECK_CAST((obj), CAMEL_MEDIUM_TYPE, CamelMedium)) +#define CAMEL_MEDIUM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MEDIUM_TYPE, CamelMediumClass)) +#define IS_CAMEL_MEDIUM(o) (GTK_CHECK_TYPE((o), CAMEL_MEDIUM_TYPE)) + + +typedef struct +{ + CamelDataWrapper parent_object; + + GHashTable *headers; + + GMimeContentField *content_type; + CamelDataWrapper *content; /* part real content */ + +} CamelMedium; + + + +typedef struct { + CamelDataWrapperClass parent_class; + + /* Virtual methods */ + void (*add_header) (CamelMedium *medium, gchar *header_name, gchar *header_value); + void (*remove_header) (CamelMedium *medium, const gchar *header_name); + const gchar * (*get_header) (CamelMedium *medium, const gchar *header_name); + +} CamelMediumClass; + + + +/* Standard Gtk function */ +GtkType camel_medium_get_type (void); + + +/* public methods */ +void camel_medium_add_header (CamelMedium *medium, gchar *header_name, gchar *header_value); +void camel_medium_remove_header (CamelMedium *medium, const gchar *header_name); +const gchar *camel_medium_get_header (CamelMedium *medium, const gchar *header_name); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_MEDIUM_H */ + diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index fb1caaa70c..edab1636b6 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -54,9 +54,9 @@ static CamelDataWrapperClass *parent_class=NULL; static void _add_header (CamelMimePart *mime_part, gchar *header_name, gchar *header_value); static void _remove_header (CamelMimePart *mime_part, const gchar *header_name); static const gchar *_get_header (CamelMimePart *mime_part, const gchar *header_name); -static void _set_description (CamelMimePart *mime_part, gchar *description); +static void _set_description (CamelMimePart *mime_part, const gchar *description); static const gchar *_get_description (CamelMimePart *mime_part); -static void _set_disposition (CamelMimePart *mime_part, gchar *disposition); +static void _set_disposition (CamelMimePart *mime_part, const gchar *disposition); static const gchar *_get_disposition (CamelMimePart *mime_part); static void _set_filename (CamelMimePart *mime_part, gchar *filename); static const gchar *_get_filename (CamelMimePart *mime_part); @@ -150,6 +150,15 @@ camel_mime_part_init (gpointer object, gpointer klass) camel_mime_part->headers = g_hash_table_new (g_str_hash, g_str_equal); camel_mime_part->content_type = gmime_content_field_new (NULL, NULL); + camel_mime_part->description = NULL; + camel_mime_part->disposition = NULL; + 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->filename = NULL; + camel_mime_part->header_lines = NULL; + camel_mime_part->content = NULL; } @@ -296,14 +305,14 @@ camel_mime_part_get_header (CamelMimePart *mime_part, const gchar *header_name) static void -_set_description (CamelMimePart *mime_part, gchar *description) +_set_description (CamelMimePart *mime_part, const gchar *description) { if (mime_part->description) g_free (mime_part->description); - mime_part->description = description; + mime_part->description = g_strdup (description); } void -camel_mime_part_set_description (CamelMimePart *mime_part, gchar *description) +camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description) { CMP_CLASS(mime_part)->set_description (mime_part, description); } @@ -326,19 +335,19 @@ camel_mime_part_get_description (CamelMimePart *mime_part) static void -_set_disposition (CamelMimePart *mime_part, gchar *disposition) +_set_disposition (CamelMimePart *mime_part, const gchar *disposition) { #warning Do not use MimeContentfield here !!! - //if (mime_part->disposition) g_free(mime_part->disposition); + if (mime_part->disposition) g_free(mime_part->disposition); if (!mime_part->disposition) - mime_part->disposition = g_new (GMimeContentField,1); + mime_part->disposition = g_new0 (GMimeContentField,1); if ((mime_part->disposition)->type) g_free ((mime_part->disposition)->type); - (mime_part->disposition)->type = disposition; + (mime_part->disposition)->type = g_strdup (disposition); } void -camel_mime_part_set_disposition (CamelMimePart *mime_part, gchar *disposition) +camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition) { CMP_CLASS(mime_part)->set_disposition (mime_part, disposition); } diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h index 5b07491dcf..65f60f9851 100644 --- a/camel/camel-mime-part.h +++ b/camel/camel-mime-part.h @@ -72,9 +72,9 @@ typedef struct { void (*add_header) (CamelMimePart *mime_part, gchar *header_name, gchar *header_value); void (*remove_header) (CamelMimePart *mime_part, const gchar *header_name); const gchar * (*get_header) (CamelMimePart *mime_part, const gchar *header_name); - void (*set_description) (CamelMimePart *mime_part, gchar *description); + void (*set_description) (CamelMimePart *mime_part, const gchar *description); const gchar * (*get_description) (CamelMimePart *mime_part); - void (*set_disposition) (CamelMimePart *mime_part, gchar *disposition); + void (*set_disposition) (CamelMimePart *mime_part, const gchar *disposition); const gchar * (*get_disposition) (CamelMimePart *mime_part); void (*set_filename) (CamelMimePart *mime_part, gchar *filename); const gchar * (*get_filename) (CamelMimePart *mime_part); @@ -108,9 +108,9 @@ GtkType camel_mime_part_get_type (void); void camel_mime_part_add_header (CamelMimePart *mime_part, gchar *header_name, gchar *header_value); void camel_mime_part_remove_header (CamelMimePart *mime_part, const gchar *header_name); const gchar *camel_mime_part_get_header (CamelMimePart *mime_part, const gchar *header_name); -void camel_mime_part_set_description (CamelMimePart *mime_part, gchar *description); +void camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description); const gchar *camel_mime_part_get_description (CamelMimePart *mime_part); -void camel_mime_part_set_disposition (CamelMimePart *mime_part, gchar *disposition); +void camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition); const gchar *camel_mime_part_get_disposition (CamelMimePart *mime_part); void camel_mime_part_set_filename (CamelMimePart *mime_part, gchar *filename); const gchar *camel_mime_part_get_filename (CamelMimePart *mime_part); diff --git a/camel/camel-stream-buffered-fs.c b/camel/camel-stream-buffered-fs.c new file mode 100644 index 0000000000..ac22df7dee --- /dev/null +++ b/camel/camel-stream-buffered-fs.c @@ -0,0 +1,259 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-stream-buffered-fs.c : file system based stream with buffer*/ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 + */ +#include +#include "camel-stream-buffered-fs.h" +#include +#include +#include +#include +#include "camel-log.h" + +static CamelStreamFsClass *parent_class=NULL; + + +/* Returns the class for a CamelStreamBufferedFs */ +#define CSBFS_CLASS(so) CAMEL_STREAM_BUFFERED_FS_CLASS (GTK_OBJECT(so)->klass) +#define CSFS_CLASS(so) CAMEL_STREAM_FS_CLASS (GTK_OBJECT(so)->klass) +#define CS_CLASS(so) CAMEL_STREAM_CLASS (GTK_OBJECT(so)->klass) + +static gint _read (CamelStream *stream, gchar *buffer, gint n); +static gint _write (CamelStream *stream, const gchar *buffer, gint n); +static void _flush (CamelStream *stream); +static gint _available (CamelStream *stream); +static gboolean _eos (CamelStream *stream); +static void _close (CamelStream *stream); +static gint _seek (CamelStream *stream, gint offset, CamelStreamSeekPolicy policy); + +static void _finalize (GtkObject *object); +static void _destroy (GtkObject *object); + +static void +camel_stream_buffered_fs_class_init (CamelStreamBufferedFsClass *camel_stream_buffered_fs_class) +{ + CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_stream_buffered_fs_class); + GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_stream_buffered_fs_class); + + parent_class = gtk_type_class (camel_stream_fs_get_type ()); + + /* virtual method definition */ + + /* virtual method overload */ + camel_stream_class->read = _read; + + gtk_object_class->finalize = _finalize; + gtk_object_class->destroy = _destroy; + +} + +static void +camel_stream_buffered_fs_init (gpointer object, gpointer klass) +{ + CamelStreamBufferedFs *stream = CAMEL_STREAM_BUFFERED_FS (object); + + stream->buffer_size = 200; + stream->read_buffer = g_new (gchar, stream->buffer_size); + stream->write_buffer = g_new (gchar, stream->buffer_size); + stream->read_pos = 0; + stream->read_pos_max = 0; + stream->write_pos = 0; + stream->write_pos_max = stream->buffer_size; +} + +GtkType +camel_stream_buffered_fs_get_type (void) +{ + static GtkType camel_stream_buffered_fs_type = 0; + + gdk_threads_enter (); + if (!camel_stream_buffered_fs_type) { + GtkTypeInfo camel_stream_buffered_fs_info = + { + "CamelStreamBufferedFs", + sizeof (CamelStreamBufferedFs), + sizeof (CamelStreamBufferedFsClass), + (GtkClassInitFunc) camel_stream_buffered_fs_class_init, + (GtkObjectInitFunc) camel_stream_buffered_fs_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_stream_buffered_fs_type = gtk_type_unique (camel_stream_fs_get_type (), &camel_stream_buffered_fs_info); + } + gdk_threads_leave (); + return camel_stream_buffered_fs_type; +} + + +static void +_destroy (GtkObject *object) +{ + CamelStreamBufferedFs *stream_buffered_fs = CAMEL_STREAM_BUFFERED_FS (object); + + CAMEL_LOG_FULL_DEBUG ("Entering CamelStreamBufferedFs::destroy\n"); + + + GTK_OBJECT_CLASS (parent_class)->destroy (object); + + CAMEL_LOG_FULL_DEBUG ("Leaving CamelStreamBufferedFs::destroy\n"); +} + + +static void +_finalize (GtkObject *object) +{ + CamelStreamBufferedFs *stream_buffered_fs = CAMEL_STREAM_BUFFERED_FS (object); + + + CAMEL_LOG_FULL_DEBUG ("Entering CamelStreamBufferedFs::finalize\n"); + + g_free (stream_buffered_fs->read_buffer); + g_free (stream_buffered_fs->write_buffer); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelStreamBufferedFs::finalize\n"); +} + + + +CamelStream * +camel_stream_buffered_fs_new_with_name (const gchar *name, CamelStreamFsMode mode) +{ + CamelStreamFs *stream_buffered_fs; + stream_buffered_fs = gtk_type_new (camel_stream_buffered_fs_get_type ()); + CSFS_CLASS (stream_buffered_fs)->init_with_name (stream_buffered_fs, name, mode); + + return CAMEL_STREAM (stream_buffered_fs); + +} + +CamelStream * +camel_stream_buffered_fs_new_with_fd (int fd) +{ + CamelStreamFs *stream_buffered_fs; + + CAMEL_LOG_FULL_DEBUG ( "Entering CamelStream::new_with_fd fd=%d\n",fd); + stream_buffered_fs = gtk_type_new (camel_stream_buffered_fs_get_type ()); + CSFS_CLASS (stream_buffered_fs)->init_with_fd (stream_buffered_fs, fd); + + + return CAMEL_STREAM (stream_buffered_fs); +} + +/** + * _read: read bytes from a stream + * @stream: stream + * @buffer: buffer where bytes are stored + * @n: max number of bytes to read + * + * + * + * Return value: number of bytes actually read. + **/ +static gint +_read (CamelStream *stream, gchar *buffer, gint n) +{ + CamelStreamBufferedFs *sbf = CAMEL_STREAM_BUFFERED_FS (stream); + gint v; + gint nb_bytes_buffered; + gint nb_bytes_to_read = n; + gint nb_bytes_read = 0; + gint bytes_chunk; + gboolean eof = FALSE; + + g_return_val_if_fail (n>0, n); + + nb_bytes_buffered = sbf->read_pos_max - sbf->read_pos; + while ( (!eof) && (nb_bytes_to_read>0)) { + if (nb_bytes_buffered <= 0) { + /* have to read some data on disk */ + v = CAMEL_STREAM_CLASS (parent_class)->read (stream, sbf->read_buffer, sbf->buffer_size); + nb_bytes_buffered = v; + sbf->read_pos_max = v; + sbf->read_pos = 0; + } + + /* nb of bytes to put inside buffer */ + bytes_chunk = MIN (nb_bytes_buffered, nb_bytes_to_read); + + if (bytes_chunk > 0) { + /* copy some bytes from the cache */ + memcpy (buffer, sbf->read_buffer + sbf->read_pos, bytes_chunk); + nb_bytes_buffered -= bytes_chunk; + nb_bytes_to_read -= bytes_chunk; + nb_bytes_read += bytes_chunk; + sbf->read_pos += bytes_chunk; + + } else /* nb_bytes_to_read is >0 so if bytes_chunk is <0 + * there was no data available */ + eof = TRUE; + } + + + + return nb_bytes_read; +} + + +static gint +_write (CamelStream *stream, const gchar *buffer, gint n) +{ + return 0; +} + + + +static void +_flush (CamelStream *stream) +{ + +} + + + +static gint +_available (CamelStream *stream) +{ + return 0; +} + + +static gboolean +_eos (CamelStream *stream) +{ +} + + + +static void +_close (CamelStream *stream) +{ + +} + + +static gint +_seek (CamelStream *stream, gint offset, CamelStreamSeekPolicy policy) +{ + return 0; +} diff --git a/camel/camel-stream-buffered-fs.h b/camel/camel-stream-buffered-fs.h new file mode 100644 index 0000000000..45da443eff --- /dev/null +++ b/camel/camel-stream-buffered-fs.h @@ -0,0 +1,88 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-stream-bufered-fs.h :stream based on unix filesystem */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 + */ + + +#ifndef CAMEL_STREAM_BUFFERED_FS_H +#define CAMEL_STREAM_BUFFERED_FS_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include +#include +#include "camel-stream-fs.h" + +#define CAMEL_STREAM_BUFFERED_FS_TYPE (camel_stream_buffered_fs_get_type ()) +#define CAMEL_STREAM_BUFFERED_FS(obj) (GTK_CHECK_CAST((obj), CAMEL_STREAM_BUFFERED_FS_TYPE, CamelStreamBufferedFs)) +#define CAMEL_STREAM_BUFFERED_FS_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_STREAM_BUFFERED_FS_TYPE, CamelStreamBufferedFsClass)) +#define IS_CAMEL_STREAM_BUFFERED_FS(o) (GTK_CHECK_TYPE((o), CAMEL_STREAM_BUFFERED_FS_TYPE)) + +typedef enum +{ + CAMEL_STREAM_BUFFERED_FS_READ = 1, + CAMEL_STREAM_BUFFERED_FS_WRITE = 2 +} CamelStreamBufferedFsMode; + + +typedef struct +{ + CamelStreamFs parent_object; + + gint buffer_size; + gchar *read_buffer; + gint read_pos; + gint read_pos_max; + + gchar *write_buffer; + gint write_pos; + gint write_pos_max; + +} CamelStreamBufferedFs; + + + +typedef struct { + CamelStreamFsClass parent_class; + + /* Virtual methods */ + +} CamelStreamBufferedFsClass; + + + +/* Standard Gtk function */ +GtkType camel_stream_buffered_fs_get_type (void); + + +/* public methods */ +CamelStream *camel_stream_buffered_fs_new_with_name (const gchar *name, CamelStreamBufferedFsMode mode); +CamelStream *camel_stream_buffered_fs_new_with_fd (int fd); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_STREAM_BUFFERED_FS_H */ diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c index e96250bd29..e540665dd3 100644 --- a/camel/camel-stream-fs.c +++ b/camel/camel-stream-fs.c @@ -33,7 +33,7 @@ static CamelStreamClass *parent_class=NULL; /* Returns the class for a CamelStreamFS */ -#define CS_CLASS(so) CAMEL_STREAM_FS_CLASS (GTK_OBJECT(so)->klass) +#define CSFS_CLASS(so) CAMEL_STREAM_FS_CLASS (GTK_OBJECT(so)->klass) static gint _read (CamelStream *stream, gchar *buffer, gint n); static gint _write (CamelStream *stream, const gchar *buffer, gint n); @@ -46,6 +46,9 @@ static gint _seek (CamelStream *stream, gint offset, CamelStreamSeekPolicy polic static void _finalize (GtkObject *object); static void _destroy (GtkObject *object); +static void _init_with_fd (CamelStreamFs *stream_fs, int fd); +static void _init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode); + static void camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class) { @@ -55,6 +58,8 @@ camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class) parent_class = gtk_type_class (camel_stream_get_type ()); /* virtual method definition */ + camel_stream_fs_class->init_with_fd = _init_with_fd; + camel_stream_fs_class->init_with_name = _init_with_name; /* virtual method overload */ camel_stream_class->read = _read; @@ -70,6 +75,13 @@ camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class) } +static void +camel_stream_fs_init (gpointer object, gpointer klass) +{ + CamelStreamFs *stream = CAMEL_STREAM_FS (object); + + stream->name = NULL; +} GtkType @@ -84,7 +96,7 @@ camel_stream_fs_get_type (void) sizeof (CamelStreamFs), sizeof (CamelStreamFsClass), (GtkClassInitFunc) camel_stream_fs_class_init, - (GtkObjectInitFunc) NULL, + (GtkObjectInitFunc) camel_stream_fs_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, @@ -130,14 +142,18 @@ _finalize (GtkObject *object) CAMEL_LOG_FULL_DEBUG ("Leaving CamelStreamFs::finalize\n"); } +static void +_init_with_fd (CamelStreamFs *stream_fs, int fd) +{ + stream_fs->fd = fd; +} -CamelStream * -camel_stream_fs_new_with_name (const gchar *name, CamelStreamFsMode mode) +static void +_init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode) { struct stat s; int v, fd; int flags; - CamelStreamFs *stream_fs; g_assert (name); CAMEL_LOG_FULL_DEBUG ( "Entering CamelStream::new_with_name, name=\"%s\", mode=%d\n", name, mode); @@ -152,21 +168,33 @@ camel_stream_fs_new_with_name (const gchar *name, CamelStreamFsMode mode) if (mode & CAMEL_STREAM_FS_WRITE) flags = O_WRONLY | O_CREAT; else - return NULL; + return; } if ( (mode & CAMEL_STREAM_FS_READ) && !(mode & CAMEL_STREAM_FS_WRITE) ) - if (v == -1) return NULL; + if (v == -1) return; fd = open (name, flags, 0600); if (fd==-1) { CAMEL_LOG_WARNING ( "CamelStreamFs::new_with_name can not obtain fd for file \"%s\"\n", name); CAMEL_LOG_FULL_DEBUG ( " Full error text is : %s\n", strerror(errno)); - return NULL; + return; } - stream_fs = CAMEL_STREAM_FS (camel_stream_fs_new_with_fd (fd)); stream_fs->name = g_strdup (name); + CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd); + + + +} + +CamelStream * +camel_stream_fs_new_with_name (const gchar *name, CamelStreamFsMode mode) +{ + CamelStreamFs *stream_fs; + stream_fs = gtk_type_new (camel_stream_fs_get_type ()); + CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, mode); + return CAMEL_STREAM (stream_fs); } @@ -178,7 +206,9 @@ camel_stream_fs_new_with_fd (int fd) CAMEL_LOG_FULL_DEBUG ( "Entering CamelStream::new_with_fd fd=%d\n",fd); stream_fs = gtk_type_new (camel_stream_fs_get_type ()); - stream_fs->fd = fd; + CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd); + + return CAMEL_STREAM (stream_fs); } diff --git a/camel/camel-stream-fs.h b/camel/camel-stream-fs.h index 86d955cc1c..c068a460dd 100644 --- a/camel/camel-stream-fs.h +++ b/camel/camel-stream-fs.h @@ -60,6 +60,8 @@ typedef struct { CamelStreamClass parent_class; /* Virtual methods */ + void (*init_with_fd) (CamelStreamFs *stream_fs, int fd); + void (*init_with_name) (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode); } CamelStreamFsClass; diff --git a/camel/gmime-content-field.c b/camel/gmime-content-field.c index a499ec6a9e..a92fd63511 100644 --- a/camel/gmime-content-field.c +++ b/camel/gmime-content-field.c @@ -74,9 +74,10 @@ _free_parameter (gpointer name, gpointer value, gpointer user_data) void gmime_content_field_free (GMimeContentField *content_field) { + g_assert (content_field); g_hash_table_foreach (content_field->parameters, _free_parameter, NULL); - g_free (content_field->type); - g_free (content_field->subtype); + if (content_field->type) g_free (content_field->type); + if (content_field->subtype) g_free (content_field->subtype); g_hash_table_destroy (content_field->parameters); g_free (content_field); } diff --git a/camel/providers/MH/camel-mh-folder.c b/camel/providers/MH/camel-mh-folder.c index 9bb2f36c82..fe297c70a8 100644 --- a/camel/providers/MH/camel-mh-folder.c +++ b/camel/providers/MH/camel-mh-folder.c @@ -34,6 +34,7 @@ #include "gstring-util.h" #include "camel-log.h" #include "camel-stream-fs.h" +#include "camel-stream-buffered-fs.h" static CamelFolderClass *parent_class=NULL; @@ -57,6 +58,7 @@ static gint _append_message (CamelFolder *folder, CamelMimeMessage *message); static void _expunge (CamelFolder *folder); static void _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder); +static gboolean _is_a_message_file (const gchar *file_name, const gchar *file_path); static void camel_mh_folder_class_init (CamelMhFolderClass *camel_mh_folder_class) @@ -126,6 +128,16 @@ _init_with_store (CamelFolder *folder, CamelStore *parent_store) +static gint +_message_name_compare (gconstpointer a, gconstpointer b) +{ + gchar *m1 = (gchar *)a; + gchar *m2 = (gchar *)b; + gint len_diff; + + return (atoi (m1) - atoi (m2)); +} + /** * camel_mh_folder_set_name: set the name of an MH folder * @folder: the folder to set the name @@ -142,6 +154,8 @@ _set_name (CamelFolder *folder, const gchar *name) gchar *full_name; const gchar *parent_full_name; gchar separator; + struct dirent *dir_entry; + DIR *dir_handle; CAMEL_LOG_FULL_DEBUG ("Entering CamelMhFolder::set_name\n"); g_assert(folder); @@ -161,7 +175,25 @@ _set_name (CamelFolder *folder, const gchar *name) CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::separator is %c\n", separator); mh_folder->directory_path = g_strdup_printf ("%s%c%s", root_dir_path, separator, folder->full_name); + + if (!camel_folder_exists (folder)) return; + + /* create message list */ + /* read the whole folder and sort message names */ + dir_handle = opendir (mh_folder->directory_path); + /* read first entry in the directory */ + dir_entry = readdir (dir_handle); + while (dir_entry != NULL) { + /* tests if the entry correspond to a message file */ + if (_is_a_message_file (dir_entry->d_name, mh_folder->directory_path)) + mh_folder->file_name_list = g_list_insert_sorted (mh_folder->file_name_list, g_strdup (dir_entry->d_name), + _message_name_compare); + /* read next entry */ + dir_entry = readdir (dir_handle); + } + closedir (dir_handle); + CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::set_name mh_folder->directory_path is %s\n", mh_folder->directory_path); CAMEL_LOG_FULL_DEBUG ("Leaving CamelMhFolder::set_name\n"); @@ -391,16 +423,6 @@ _is_a_message_file (const gchar *file_name, const gchar *file_path) } -static gint -_message_name_compare (gconstpointer a, gconstpointer b) -{ - gchar *m1 = (gchar *)a; - gchar *m2 = (gchar *)b; - gint len_diff; - - return (atoi (m1) - atoi (m2)); -} - static void _filename_free (gpointer data) { @@ -417,8 +439,6 @@ _get_message (CamelFolder *folder, gint number) const gchar *directory_path; gchar *message_name; gchar *message_file_name; - struct dirent *dir_entry; - DIR *dir_handle; CamelStream *input_stream = NULL; CamelMimeMessage *message = NULL; GList *message_list = NULL; @@ -428,31 +448,16 @@ _get_message (CamelFolder *folder, gint number) directory_path = mh_folder->directory_path; if (!directory_path) return NULL; - if (!camel_folder_exists (folder)) return NULL; - - /* read the whole folder and sort message names */ - dir_handle = opendir (directory_path); - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while (dir_entry != NULL) { - /* tests if the entry correspond to a message file */ - if (_is_a_message_file (dir_entry->d_name, directory_path)) - message_list = g_list_insert_sorted (message_list, g_strdup (dir_entry->d_name), - _message_name_compare); - /* read next entry */ - dir_entry = readdir (dir_handle); - } - closedir (dir_handle); - - message_name = g_list_nth_data (message_list, number); + + message_name = g_list_nth_data (mh_folder->file_name_list, number); if (message_name != NULL) { CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, name = %s\n", number, message_name); message_file_name = g_strdup_printf ("%s/%s", directory_path, message_name); - input_stream = camel_stream_fs_new_with_name (message_file_name, CAMEL_STREAM_FS_READ); + input_stream = camel_stream_buffered_fs_new_with_name (message_file_name, CAMEL_STREAM_BUFFERED_FS_READ); if (input_stream != NULL) { #warning use session field here @@ -468,7 +473,7 @@ _get_message (CamelFolder *folder, gint number) g_free (message_file_name); } else CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, not found\n", number); - string_list_free (message_list); + return message; } diff --git a/camel/providers/MH/camel-mh-folder.h b/camel/providers/MH/camel-mh-folder.h index 332698bdba..b06e7724ad 100644 --- a/camel/providers/MH/camel-mh-folder.h +++ b/camel/providers/MH/camel-mh-folder.h @@ -45,6 +45,7 @@ typedef struct { CamelFolder parent_object; gchar *directory_path; + GList *file_name_list; } CamelMhFolder; -- cgit v1.2.3