new class. Will handle all sort of information media (Mime mail messages,
authorbertrand <Bertrand.Guiheneuf@aful.org>
Tue, 24 Aug 1999 21:01:10 +0000 (21:01 +0000)
committerBertrand Guiheneuf <bertrand@src.gnome.org>
Tue, 24 Aug 1999 21:01:10 +0000 (21:01 +0000)
1999-08-24  bertrand  <Bertrand.Guiheneuf@aful.org>

* 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!

12 files changed:
camel/Makefile.am
camel/camel-medium.c [new file with mode: 0644]
camel/camel-medium.h [new file with mode: 0644]
camel/camel-mime-part.c
camel/camel-mime-part.h
camel/camel-stream-buffered-fs.c [new file with mode: 0644]
camel/camel-stream-buffered-fs.h [new file with mode: 0644]
camel/camel-stream-fs.c
camel/camel-stream-fs.h
camel/gmime-content-field.c
camel/providers/MH/camel-mh-folder.c
camel/providers/MH/camel-mh-folder.h

index 5f23d2e..c6860a6 100644 (file)
@@ -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 (file)
index 0000000..8414432
--- /dev/null
@@ -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 <Bertrand.Guiheneuf@inria.fr> .
+ *
+ * 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 <config.h>
+#include "camel-medium.h"
+#include <stdio.h>
+#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 (file)
index 0000000..c354663
--- /dev/null
@@ -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 <Bertrand.Guiheneuf@inria.fr> .
+ *
+ * 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 <gtk/gtk.h>
+#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 */
+
index fb1caaa..edab163 100644 (file)
@@ -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);
 }
index 5b07491..65f60f9 100644 (file)
@@ -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 (file)
index 0000000..ac22df7
--- /dev/null
@@ -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 <Bertrand.Guiheneuf@inria.fr> .
+ *
+ * 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 <config.h>
+#include "camel-stream-buffered-fs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#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 (file)
index 0000000..45da443
--- /dev/null
@@ -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 <Bertrand.Guiheneuf@inria.fr> .
+ *
+ * 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 <gtk/gtk.h>
+#include <stdio.h>
+#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 */
index e96250b..e540665 100644 (file)
@@ -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);
 }
 
index 86d955c..c068a46 100644 (file)
@@ -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;
 
index a499ec6..a92fd63 100644 (file)
@@ -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);
 }
index 9bb2f36..fe297c7 100644 (file)
@@ -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;   
 }
index 332698b..b06e772 100644 (file)
@@ -45,6 +45,7 @@ typedef struct {
        CamelFolder parent_object;
        
        gchar *directory_path;
+       GList *file_name_list;
 
 } CamelMhFolder;