aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbertrand <Bertrand.Guiheneuf@aful.org>1999-09-03 00:06:55 +0800
committerBertrand Guiheneuf <bertrand@src.gnome.org>1999-09-03 00:06:55 +0800
commit6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b (patch)
tree5d4068c160dafdf731729203057346ad5363bcb6
parent5c7fc6df1165a26c7dfca91f9664c4e860856824 (diff)
downloadgsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar.gz
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar.bz2
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar.lz
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar.xz
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.tar.zst
gsoc2013-evolution-6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b.zip
Added (experimental) maildir provider written by Jukka Zitting
1999-09-02 bertrand <Bertrand.Guiheneuf@aful.org> * camel/providers/maildir: Added (experimental) maildir provider written by Jukka Zitting <hukka@greywolves.org> * camel/providers/Makefile.am (SUBDIRS): build maildir provider. * camel/camel-provider.c (camel_provider_get_for_protocol): bug fix. patch from Jukka Zitting <hukka@greywolves.org> svn path=/trunk/; revision=1168
-rw-r--r--ChangeLog9
-rw-r--r--camel/camel-provider.c2
-rw-r--r--camel/providers/Makefile.am2
-rw-r--r--camel/providers/maildir/.cvsignore6
-rw-r--r--camel/providers/maildir/Makefile.am23
-rw-r--r--camel/providers/maildir/camel-maildir-folder.c701
-rw-r--r--camel/providers/maildir/camel-maildir-folder.h66
-rw-r--r--camel/providers/maildir/camel-maildir-provider.c46
-rw-r--r--camel/providers/maildir/camel-maildir-store.c126
-rw-r--r--camel/providers/maildir/camel-maildir-store.h69
-rw-r--r--configure.in1
11 files changed, 1049 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 3a9a2fde68..df950c5b6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
1999-09-02 bertrand <Bertrand.Guiheneuf@aful.org>
+ * camel/providers/maildir: Added (experimental) maildir
+ provider written by Jukka Zitting <hukka@greywolves.org>
+
+ * camel/providers/Makefile.am (SUBDIRS): build maildir
+ provider.
+
+ * camel/camel-provider.c (camel_provider_get_for_protocol):
+ bug fix. patch from Jukka Zitting <hukka@greywolves.org>
+
* camel/camel-mime-message.c (_write_one_recipient_to_stream):
changed decl to fit CRLFunc.
(_write_recipients_to_stream):
diff --git a/camel/camel-provider.c b/camel/camel-provider.c
index 79b9dfd97d..29c8917faa 100644
--- a/camel/camel-provider.c
+++ b/camel/camel-provider.c
@@ -176,7 +176,7 @@ camel_provider_get_for_protocol (const gchar *protocol, ProviderType type)
if (protocol_is_found)
provider_is_found = (current_provider->provider_type == type);
- g_list_next (current_provider_node);
+ current_provider_node = current_provider_node->next;
}
if (provider_is_found) return current_provider;
diff --git a/camel/providers/Makefile.am b/camel/providers/Makefile.am
index 7bdc7a7eab..b9d97b52d4 100644
--- a/camel/providers/Makefile.am
+++ b/camel/providers/Makefile.am
@@ -1,3 +1,3 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = MH
+SUBDIRS = MH maildir
diff --git a/camel/providers/maildir/.cvsignore b/camel/providers/maildir/.cvsignore
new file mode 100644
index 0000000000..2e7b174532
--- /dev/null
+++ b/camel/providers/maildir/.cvsignore
@@ -0,0 +1,6 @@
+Makefile.in
+Makefile
+.deps
+*.lo
+*.la
+.libs
diff --git a/camel/providers/maildir/Makefile.am b/camel/providers/maildir/Makefile.am
new file mode 100644
index 0000000000..51a0d7327b
--- /dev/null
+++ b/camel/providers/maildir/Makefile.am
@@ -0,0 +1,23 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS =
+
+libcamelmaildirincludedir = $(includedir)/camel
+
+lib_LTLIBRARIES = libcamelmaildir.la
+
+INCLUDES = -I.. -I$(srcdir)/.. -I$(top_srcdir)/intl -I$(top_srcdir)/camel \
+ $(GTK_INCLUDEDIR) -I$(includedir)
+
+libcamelmaildir_la_SOURCES = \
+ camel-maildir-folder.c \
+ camel-maildir-provider.c \
+ camel-maildir-store.c
+
+libcamelmaildirinclude_HEADERS = \
+ camel-maildir-folder.h \
+ camel-maildir-store.h
+
+libcamelmaildir_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir)
+
+EXTRA_DIST =
diff --git a/camel/providers/maildir/camel-maildir-folder.c b/camel/providers/maildir/camel-maildir-folder.c
new file mode 100644
index 0000000000..489fd37009
--- /dev/null
+++ b/camel/providers/maildir/camel-maildir-folder.c
@@ -0,0 +1,701 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-maildir-folder.c : camel-folder subclass for maildir folders */
+
+/*
+ *
+ * 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 <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include "camel-maildir-folder.h"
+#include "camel-maildir-store.h"
+#include "camel-stream-fs.h"
+#include "camel-log.h"
+
+static CamelFolderClass *parent_class=NULL;
+
+/* Returns the class for a CamelMaildirFolder */
+#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (GTK_OBJECT(so)->klass)
+#define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass)
+#define CMAILDIRS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass)
+
+#define INIWTST "CamelMaildirFolder::init_with_store"
+#define SETNAME "CamelMaildirFolder::set_name"
+#define EXISTS "CamelMaildirFolder::exists"
+#define CREATE "CamelMaildirFolder::create"
+#define DELETE "CamelMaildirFolder::delete"
+#define DELMESG "CamelMaildirFolder::delete_messages"
+#define EXPUNGE "CamelMaildirFolder::expunge"
+#define GETMSG "CamelMaildirFolder::get_message"
+#define NUMMSGS "CamelMaildirFolder::get_message_count"
+
+static DIR *
+_xopendir (const gchar *path)
+{
+ DIR *handle;
+ g_assert (path);
+
+ handle = opendir (path);
+ if (!handle) {
+ CAMEL_LOG_WARNING ("ERROR: opendir (%s);\n", path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ }
+
+ return handle;
+}
+
+static gboolean
+_xstat (const gchar *path, struct stat *buf)
+{
+ gint stat_error;
+ g_assert (path);
+ g_assert (buf);
+
+ stat_error = stat (path, buf);
+ if (stat_error == 0) {
+ return TRUE;
+ } else if (errno == ENOENT) {
+ buf->st_mode = 0;
+ return TRUE;
+ } else {
+ CAMEL_LOG_WARNING ("ERROR: stat (%s, %p);\n", path, buf);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+}
+
+static gboolean
+_xmkdir (const gchar *path)
+{
+ g_assert (path);
+
+ if (mkdir (path, S_IRWXU) == -1) {
+ CAMEL_LOG_WARNING ("ERROR: mkdir (%s, S_IRWXU);\n", path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+_xlink (const gchar *from, const gchar *to)
+{
+ g_assert (from);
+ g_assert (to);
+
+ if (link (from, to) == 0) {
+ return TRUE;
+ } else {
+ CAMEL_LOG_WARNING ("ERROR: link (%s, %s);\n", from, to);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+}
+
+static gboolean
+_xunlink (const gchar *path)
+{
+ g_assert (path);
+
+ if (unlink (path) == 0) {
+ return TRUE;
+ } else if (errno == ENOENT) {
+ return TRUE;
+ } else {
+ CAMEL_LOG_WARNING ("ERROR: unlink (%s);\n", path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+}
+
+static gboolean
+_xrmdir (const gchar *path)
+{
+ DIR *dir_handle;
+ struct dirent *dir_entry;
+ gchar *file;
+ struct stat statbuf;
+ g_assert (path);
+
+ dir_handle = opendir (path);
+ if (!dir_handle && errno == ENOENT) {
+ return TRUE;
+ } else if (!dir_handle) {
+ CAMEL_LOG_WARNING ("ERROR: opendir (%s);\n", path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+
+ while ((dir_entry = readdir (dir_handle))) {
+ file = g_strconcat (path, G_DIR_SEPARATOR_S, dir_entry->d_name,
+ NULL);
+ if (_xstat (file, &statbuf) && S_ISREG (statbuf.st_mode))
+ _xunlink (file);
+ g_free (file);
+ }
+
+ closedir (dir_handle);
+
+ if (rmdir (path) == 0) {
+ return TRUE;
+ } else if (errno == ENOENT) {
+ return TRUE;
+ } else {
+ CAMEL_LOG_WARNING ("ERROR: rmdir (%s);\n", path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is: (%d) %s\n",
+ errno, strerror(errno));
+ return FALSE;
+ }
+}
+
+/**
+ * CamelMaildirFolder::init_with_store: initializes the folder object
+ * @folder: folder object to initialize
+ * @parent_store: parent store object of the folder
+ *
+ * Simply tells that the folder can contain messages but not subfolders.
+ * Perhaps we'll later implement subfolders too...
+ */
+static void
+camel_maildir_folder_init_with_store (CamelFolder *folder,
+ CamelStore *parent_store)
+{
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::init_with_store\n");
+ g_assert(folder);
+ g_assert(parent_store);
+
+ /* call parent method */
+ parent_class->init_with_store (folder, parent_store);
+
+ folder->can_hold_messages = TRUE;
+ folder->can_hold_folders = FALSE;
+
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::init_with_store\n");
+}
+
+/**
+ * CamelMaildirFolder::set_name: sets the name of the folder
+ * @folder: folder object
+ * @name: name of the folder
+ *
+ * Sets the name of the folder object. The existence of a folder with
+ * the given name is not checked in this function.
+ */
+static void
+camel_maildir_folder_set_name (CamelFolder *folder, const gchar *name)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::set_name\n");
+ g_assert (folder);
+ g_assert (name);
+ g_assert (folder->parent_store);
+
+ /* call default implementation */
+ parent_class->set_name (folder, name);
+
+ if (maildir_folder->directory_path)
+ g_free (maildir_folder->directory_path);
+
+ maildir_folder->directory_path = g_strdup (name);
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::set_name: "
+ "name set to %s\n", name);
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::set_name\n");
+}
+
+/**
+ * CamelMaildirFolder::exists: tests whether the named maildir exists
+ * @folder: folder object
+ *
+ * A created maildir folder object doesn't necessarily exist yet in the
+ * filesystem. This function checks whether the maildir exists.
+ * The structure of the maildir is stated in the maildir.5 manpage.
+ *
+ * maildir.5:
+ * A directory in maildir format has three subdirectories,
+ * all on the same filesystem: tmp, new, and cur.
+ *
+ * Return value: TRUE if the maildir exists, FALSE otherwise
+ */
+static gboolean
+camel_maildir_folder_exists (CamelFolder *folder)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
+ static const gchar *dir[3] = { "new", "cur", "tmp" };
+ gint i;
+ struct stat statbuf;
+ const gchar *maildir;
+ gchar *path;
+ gboolean rv = TRUE;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::exists\n");
+ g_assert (folder);
+ g_return_val_if_fail (maildir_folder->directory_path, FALSE);
+
+ maildir = maildir_folder->directory_path;
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMailFolder::exists: checking maildir %s\n",
+ maildir);
+
+ /* check whether the toplevel directory exists */
+ rv = _xstat (maildir, &statbuf) && S_ISDIR (statbuf.st_mode);
+
+ /* check whether the maildir subdirectories exist */
+ for (i = 0; rv && i < 3; i++) {
+ path = g_strconcat (maildir, G_DIR_SEPARATOR_S, dir[i], NULL);
+
+ rv = _xstat (path, &statbuf) && S_ISDIR (statbuf.st_mode);
+
+ g_free (path);
+ }
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::exists: %s\n",
+ (rv) ? "maildir found" : "maildir not found");
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::exists\n");
+ return rv;
+}
+
+/**
+ * CamelMaildirFolder::create: creates the named maildir
+ * @folder: folder object
+ *
+ * A created maildir folder object doesn't necessarily exist yet in the
+ * filesystem. This function creates the maildir if it doesn't yet exist.
+ * The structure of the maildir is stated in the maildir.5 manpage.
+ *
+ * maildir.5:
+ * A directory in maildir format has three subdirectories,
+ * all on the same filesystem: tmp, new, and cur.
+ *
+ * Return value: TRUE if the maildir existed already or was created,
+ * FALSE otherwise
+ */
+static gboolean
+camel_maildir_folder_create (CamelFolder *folder)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
+ static const gchar *dir[3] = { "new", "cur", "tmp" };
+ gint i;
+ const gchar *maildir;
+ gchar *path;
+ gboolean rv = TRUE;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::create\n");
+ g_assert (folder);
+
+ /* check whether the maildir already exists */
+ if (camel_folder_exists (folder)) return TRUE;
+
+ maildir = maildir_folder->directory_path;
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMailFolder::create: creating maildir %s\n",
+ maildir);
+
+ /* create the toplevel directory */
+ rv = _xmkdir (maildir);
+
+ /* create the maildir subdirectories */
+ for (i = 0; rv && i < 3; i++) {
+ path = g_strconcat (maildir, G_DIR_SEPARATOR_S, dir[i], NULL);
+
+ rv = _xmkdir (path);
+
+ g_free (path);
+ }
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::create: %s\n",
+ rv ? "maildir created" : "an error occurred");
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::create\n");
+ return rv;
+}
+
+/**
+ * CamelMaildirFolder::delete: delete the maildir folder
+ * @folder: the folder object
+ * @recurse:
+ *
+ * This function empties and deletes the maildir folder. The subdirectories
+ * "tmp", "cur", and "new" are removed first and then the toplevel maildir
+ * directory is deleted. All files from the directories are deleted as well,
+ * so you should be careful when using this function. If a subdirectory cannot
+ * be deleted, then the operation it is stopped. Thus if an error occurs, the
+ * maildir directory won't be removed, but it might no longer be a valid maildir.
+ */
+static gboolean
+camel_maildir_folder_delete (CamelFolder *folder, gboolean recurse)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
+ static const gchar *dir[3] = { "new", "cur", "tmp" };
+ gint i;
+ const gchar *maildir;
+ gchar *path;
+ gboolean rv = TRUE;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::create\n");
+ g_assert (folder);
+
+ /* check whether the maildir already exists */
+ if (!camel_folder_exists (folder)) return TRUE;
+
+ maildir = maildir_folder->directory_path;
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMailFolder::delete: deleting maildir %s\n",
+ maildir);
+
+ /* delete the maildir subdirectories */
+ for (i = 0; rv && i < 3; i++) {
+ path = g_strconcat (maildir, G_DIR_SEPARATOR_S, dir[i], NULL);
+
+ rv = _xrmdir (path);
+
+ g_free (path);
+ }
+
+ /* create the toplevel directory */
+ if (rv)
+ rv = _xrmdir (maildir);
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::delete: %s\n",
+ rv ? "maildir deleted" : "an error occurred");
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::delete\n");
+ return rv;
+}
+
+/**
+ * CamelMaildirFolder::delete_messages: empty the maildir folder
+ * @folder: the folder object
+ *
+ * This function empties the maildir folder. All messages from the
+ * "cur" subdirectory are deleted. If a message cannot be deleted, then
+ * it is just skipped and the rest of the messages are still deleted.
+ * Files with names starting with a dot are skipped as described in the
+ * maildir.5 manpage.
+ *
+ * maildir.5:
+ * It is a good idea for readers to skip all filenames in new
+ * and cur starting with a dot. Other than this, readers
+ * should not attempt to parse filenames.
+ *
+ * Return value: FALSE on error and if some messages could not be deleted.
+ * TRUE otherwise.
+ */
+static gboolean
+camel_maildir_folder_delete_messages (CamelFolder *folder)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
+ const gchar *maildir;
+ gchar *curdir, *file;
+ DIR *dir_handle;
+ struct dirent *dir_entry;
+ gboolean rv = TRUE;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::delete_messages\n");
+ g_assert (folder);
+
+ /* call default implementation */
+ parent_class->delete_messages (folder);
+
+ /* Check if the folder didn't exist */
+ if (!camel_folder_exists (folder)) return TRUE;
+
+ maildir = maildir_folder->directory_path;
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::delete_messages: "
+ "deleting messages from %s\n", maildir);
+
+ /* delete messages from the maildir subdirectory "cur" */
+ curdir = g_strconcat (maildir, G_DIR_SEPARATOR_S, "cur", NULL);
+
+ dir_handle = _xopendir (curdir);
+ if (dir_handle) {
+ while ((dir_entry = readdir (dir_handle))) {
+ if (dir_entry->d_name[0] == '.') continue;
+ file = g_strconcat (curdir, G_DIR_SEPARATOR_S,
+ dir_entry->d_name, NULL);
+
+ if (!_xunlink (file)) rv = FALSE;
+
+ g_free (file);
+ }
+ closedir (dir_handle);
+ } else
+ rv = FALSE;
+
+ g_free (curdir);
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::delete_messages: %s\n",
+ rv ? "messages deleted" : "an error occurred");
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::delete_messages\n");
+ return rv;
+}
+
+/**
+ * CamelMaildirFolder::get_message: get a message from maildir
+ * @folder: the folder object
+ * @number: number of the message within the folder
+ *
+ * Return value: the message, NULL on error
+ */
+static CamelMimeMessage *
+camel_maildir_folder_get_message (CamelFolder *folder, gint number)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER(folder);
+ DIR *dir_handle;
+ struct dirent *dir_entry;
+ CamelStream *stream;
+ CamelMimeMessage *message = NULL;
+ const gchar *maildir;
+ gchar *curdir, *file = NULL;
+ gint count = -1;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::get_message\n");
+ g_assert(folder);
+
+ /* Check if the folder exists */
+ if (!camel_folder_exists (folder)) return NULL;
+
+ maildir = maildir_folder->directory_path;
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::get_message: "
+ "getting message #%d from %s\n", number, maildir);
+
+ /* Count until the desired message is reached */
+ curdir = g_strconcat (maildir, G_DIR_SEPARATOR_S, "cur", NULL);
+ if ((dir_handle = _xopendir (curdir))) {
+ while ((count < number) && (dir_entry = readdir (dir_handle)))
+ if (dir_entry->d_name[0] != '.') count++;
+
+ if (count == number)
+ file = g_strconcat (curdir, G_DIR_SEPARATOR_S,
+ dir_entry->d_name, NULL);
+
+ closedir (dir_handle);
+ }
+ g_free (curdir);
+ if (!file) return NULL;
+
+ /* Create the message object */
+#warning use session field here
+ message = camel_mime_message_new_with_session ((CamelSession *) NULL);
+ stream = camel_stream_fs_new_with_name (file, CAMEL_STREAM_FS_READ);
+
+ if (!message || !stream) {
+ g_free (file);
+ if (stream) gtk_object_unref (GTK_OBJECT (stream));
+ if (message) gtk_object_unref (GTK_OBJECT (message));
+ return NULL;
+ }
+
+ camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (message),
+ stream);
+ gtk_object_unref (GTK_OBJECT (stream));
+ gtk_object_set_data_full (GTK_OBJECT (message),
+ "fullpath", file, g_free);
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::get_message: "
+ "message %p created from %s\n", message, file);
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::get_message\n");
+ return message;
+}
+
+/**
+ * CamelMaildirFolder::get_message_count: count messages in maildir
+ * @folder: the folder object
+ *
+ * Returns the number of messages in the maildir folder. New messages
+ * are included in this count.
+ *
+ * Return value: number of messages in the maildir, -1 on error
+ */
+static gint
+camel_maildir_folder_get_message_count (CamelFolder *folder)
+{
+ CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER(folder);
+ const gchar *maildir;
+ gchar *newdir, *curdir, *newfile, *curfile;
+ DIR *dir_handle;
+ struct dirent *dir_entry;
+ guint count = 0;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering "
+ "CamelMaildirFolder::get_message_count\n");
+ g_assert(folder);
+
+ /* check if the maildir exists */
+ if (!camel_folder_exists (folder)) return -1;
+
+ maildir = maildir_folder->directory_path;
+
+ newdir = g_strconcat (maildir, G_DIR_SEPARATOR_S, "new", NULL);
+ curdir = g_strconcat (maildir, G_DIR_SEPARATOR_S, "cur", NULL);
+
+ /* Check new messages */
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::get_message_count: "
+ "getting new messages from %s\n", newdir);
+ if ((dir_handle = _xopendir (newdir))) {
+ while ((dir_entry = readdir (dir_handle))) {
+ if (dir_entry->d_name[0] == '.') continue;
+ newfile = g_strconcat (newdir, G_DIR_SEPARATOR_S,
+ dir_entry->d_name, NULL);
+ curfile = g_strconcat (curdir, G_DIR_SEPARATOR_S,
+ dir_entry->d_name, ":2,", NULL);
+
+ if (_xlink (newfile, curfile)) _xunlink (newfile);
+
+ g_free (curfile);
+ g_free (newfile);
+ }
+ closedir (dir_handle);
+ }
+
+ /* Count messages */
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::get_message_count: "
+ "counting messages in %s\n", curdir);
+ if ((dir_handle = _xopendir (curdir))) {
+ while ((dir_entry = readdir (dir_handle)))
+ if (dir_entry->d_name[0] != '.') count++;
+ closedir (dir_handle);
+ }
+
+ g_free (curdir);
+ g_free (newdir);
+
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::get_message_count: "
+ " found %d messages\n", count);
+ CAMEL_LOG_FULL_DEBUG ("Leaving "
+ "CamelMaildirFolder::get_message_count\n");
+ return count;
+}
+
+/**
+ * CamelMaildirFolder::expunge: expunge messages marked as deleted
+ * @folder: the folder object
+ *
+ * Physically deletes the messages marked as deleted in the folder.
+ */
+static void
+camel_maildir_folder_expunge (CamelFolder *folder)
+{
+ CamelMimeMessage *message;
+ GList *node;
+ gchar *fullpath;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::expunge\n");
+ g_assert(folder);
+
+ /* expunge messages marked for deletion */
+ for (node = folder->message_list; node; node = g_list_next(node)) {
+ message = CAMEL_MIME_MESSAGE (node->data);
+ if (!message) {
+ CAMEL_LOG_WARNING ("CamelMaildirFolder::expunge: "
+ "null message in node %p\n", node);
+ continue;
+ }
+
+ if (camel_mime_message_get_flag (message, "DELETED")) {
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::expunge: "
+ "expunging message #%d\n",
+ message->message_number);
+
+ /* expunge the message */
+ fullpath = gtk_object_get_data (GTK_OBJECT (message),
+ "fullpath");
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::expunge: "
+ "message fullpath is %s\n",
+ fullpath);
+
+ if (_xunlink (fullpath))
+ message->expunged = TRUE;
+ } else {
+ CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::expunge: "
+ "skipping message #%d\n",
+ message->message_number);
+ }
+ }
+
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::expunge\n");
+}
+
+static void
+camel_maildir_folder_class_init (
+ CamelMaildirFolderClass *camel_maildir_folder_class)
+{
+ CamelFolderClass *camel_folder_class =
+ CAMEL_FOLDER_CLASS (camel_maildir_folder_class);
+
+ parent_class = gtk_type_class (camel_folder_get_type ());
+
+ /* virtual method definition */
+ /* virtual method overload */
+ camel_folder_class->
+ init_with_store = camel_maildir_folder_init_with_store;
+ camel_folder_class->set_name = camel_maildir_folder_set_name;
+ camel_folder_class->exists = camel_maildir_folder_exists;
+ camel_folder_class->create = camel_maildir_folder_create;
+ camel_folder_class->delete = camel_maildir_folder_delete;
+ camel_folder_class->
+ delete_messages = camel_maildir_folder_delete_messages;
+ camel_folder_class->expunge = camel_maildir_folder_expunge;
+ camel_folder_class->
+ get_message = camel_maildir_folder_get_message;
+ camel_folder_class->
+ get_message_count = camel_maildir_folder_get_message_count;
+}
+
+GtkType
+camel_maildir_folder_get_type (void)
+{
+ static GtkType camel_maildir_folder_type = 0;
+
+ if (!camel_maildir_folder_type) {
+ GtkTypeInfo camel_maildir_folder_info =
+ {
+ "CamelMaildirFolder",
+ sizeof (CamelMaildirFolder),
+ sizeof (CamelMaildirFolderClass),
+ (GtkClassInitFunc) camel_maildir_folder_class_init,
+ (GtkObjectInitFunc) NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ camel_maildir_folder_type =
+ gtk_type_unique (CAMEL_FOLDER_TYPE,
+ &camel_maildir_folder_info);
+ }
+
+ return camel_maildir_folder_type;
+}
diff --git a/camel/providers/maildir/camel-maildir-folder.h b/camel/providers/maildir/camel-maildir-folder.h
new file mode 100644
index 0000000000..0d9cb21a36
--- /dev/null
+++ b/camel/providers/maildir/camel-maildir-folder.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-maildir-folder.h : Abstract class for an email folder */
+
+/*
+ *
+ * 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_MAILDIR_FOLDER_H
+#define CAMEL_MAILDIR_FOLDER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <gtk/gtk.h>
+#include "camel-folder.h"
+/* #include "camel-store.h" */
+
+#define CAMEL_MAILDIR_FOLDER_TYPE (camel_maildir_folder_get_type ())
+#define CAMEL_MAILDIR_FOLDER(obj) (GTK_CHECK_CAST((obj), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolder))
+#define CAMEL_MAILDIR_FOLDER_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolderClass))
+#define IS_CAMEL_MAILDIR_FOLDER(o) (GTK_CHECK_TYPE((o), CAMEL_MAILDIR_FOLDER_TYPE))
+
+
+typedef struct {
+ CamelFolder parent_object;
+
+ gchar *directory_path;
+} CamelMaildirFolder;
+
+
+
+typedef struct {
+ CamelFolderClass parent_class;
+
+ /* Virtual methods */
+
+} CamelMaildirFolderClass;
+
+
+/* public methods */
+
+/* Standard Gtk function */
+GtkType camel_maildir_folder_get_type (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_MAILDIR_FOLDER_H */
diff --git a/camel/providers/maildir/camel-maildir-provider.c b/camel/providers/maildir/camel-maildir-provider.c
new file mode 100644
index 0000000000..cd5521adc0
--- /dev/null
+++ b/camel/providers/maildir/camel-maildir-provider.c
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-maildir-provider.c: maildir provider registration code */
+
+/*
+ *
+ * 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-maildir-store.h"
+#include "camel-provider.h"
+#include "camel-log.h"
+
+
+static CamelProvider _maildir_provider = {
+ (GtkType) 0,
+ PROVIDER_STORE,
+ "maildir",
+ "Maildir provider for Camel",
+ "This maildir provider is based on the default MH provider of Camel",
+ (GModule *) NULL
+};
+
+
+
+CamelProvider *
+camel_provider_module_init ()
+{
+ _maildir_provider.object_type = camel_maildir_store_get_type();
+ return &_maildir_provider;
+}
diff --git a/camel/providers/maildir/camel-maildir-store.c b/camel/providers/maildir/camel-maildir-store.c
new file mode 100644
index 0000000000..7c416e90b4
--- /dev/null
+++ b/camel/providers/maildir/camel-maildir-store.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-maildir-store.c : class for an maildir store */
+
+/*
+ *
+ * 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 "camel-maildir-store.h"
+#include "camel-maildir-folder.h"
+#include "url-util.h"
+
+static CamelStoreClass *parent_class=NULL;
+
+/* Returns the class for a CamelMaildirStore */
+#define CMAILDIRS_CLASS(so) CAMEL_MAILDIR_STORE_CLASS (GTK_OBJECT(so)->klass)
+#define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass)
+#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (GTK_OBJECT(so)->klass)
+
+static void _init (CamelStore *store, CamelSession *session,
+ const gchar *url_name);
+static CamelFolder *_get_folder (CamelStore *store, const gchar *folder_name);
+
+static void
+camel_maildir_store_class_init (
+ CamelMaildirStoreClass *camel_maildir_store_class)
+{
+ CamelStoreClass *camel_store_class =
+ CAMEL_STORE_CLASS (camel_maildir_store_class);
+
+ parent_class = gtk_type_class (camel_store_get_type ());
+
+ /* virtual method definition */
+ /* virtual method overload */
+ camel_store_class->init = _init;
+ camel_store_class->get_folder = _get_folder;
+}
+
+static void
+camel_maildir_store_init (gpointer object, gpointer klass)
+{
+ CamelMaildirStore *maildir_store = CAMEL_MAILDIR_STORE (object);
+ CamelStore *store = CAMEL_STORE (object);
+
+ store->separator = G_DIR_SEPARATOR;
+}
+
+GtkType
+camel_maildir_store_get_type (void)
+{
+ static GtkType camel_maildir_store_type = 0;
+
+ if (!camel_maildir_store_type) {
+ GtkTypeInfo camel_maildir_store_info =
+ {
+ "CamelMaildirStore",
+ sizeof (CamelMaildirStore),
+ sizeof (CamelMaildirStoreClass),
+ (GtkClassInitFunc) camel_maildir_store_class_init,
+ (GtkObjectInitFunc) camel_maildir_store_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ camel_maildir_store_type =
+ gtk_type_unique (CAMEL_STORE_TYPE,
+ &camel_maildir_store_info);
+ }
+
+ return camel_maildir_store_type;
+}
+
+static void
+_init (CamelStore *store, CamelSession *session, const gchar *url_name)
+{
+ CamelMaildirStore *maildir_store = CAMEL_MAILDIR_STORE (store);
+ Gurl *store_url;
+
+ g_assert (url_name);
+
+ /* call parent implementation */
+ parent_class->init (store, session, url_name);
+
+ /* find the path in the URL*/
+ store_url = g_url_new (url_name);
+
+ g_return_if_fail (store_url);
+ g_return_if_fail (store_url->path);
+
+ maildir_store->toplevel_dir = g_strdup (store_url->path);
+
+ g_url_free (store_url);
+}
+
+static CamelFolder *
+_get_folder (CamelStore *store, const gchar *folder_name)
+{
+ CamelMaildirStore *maildir_store = CAMEL_MAILDIR_STORE (store);
+ CamelMaildirFolder *new_maildir_folder;
+ CamelFolder *new_folder;
+ gchar *maildir = g_strconcat (maildir_store->toplevel_dir, G_DIR_SEPARATOR_S, folder_name, NULL);
+
+ new_maildir_folder = gtk_type_new (CAMEL_MAILDIR_FOLDER_TYPE);
+ new_folder = CAMEL_FOLDER (new_maildir_folder);
+
+ CF_CLASS (new_folder)->init_with_store (new_folder, store);
+ CF_CLASS (new_folder)->set_name (new_folder, maildir);
+
+ return new_folder;
+}
diff --git a/camel/providers/maildir/camel-maildir-store.h b/camel/providers/maildir/camel-maildir-store.h
new file mode 100644
index 0000000000..1a95ed1436
--- /dev/null
+++ b/camel/providers/maildir/camel-maildir-store.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-maildirstore.h : class for an maildir store */
+
+/*
+ *
+ * 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_MAILDIR_STORE_H
+#define CAMEL_MAILDIR_STORE_H 1
+
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <gtk/gtk.h>
+#include "camel-store.h"
+
+#define CAMEL_MAILDIR_STORE_TYPE (camel_maildir_store_get_type ())
+#define CAMEL_MAILDIR_STORE(obj) (GTK_CHECK_CAST((obj), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStore))
+#define CAMEL_MAILDIR_STORE_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStoreClass))
+#define IS_CAMEL_MAILDIR_STORE(o) (GTK_CHECK_TYPE((o), CAMEL_MAILDIR_STORE_TYPE))
+
+
+typedef struct {
+ CamelStore parent_object;
+
+ gchar *toplevel_dir;
+} CamelMaildirStore;
+
+
+
+typedef struct {
+ CamelStoreClass parent_class;
+
+
+} CamelMaildirStoreClass;
+
+
+/* public methods */
+
+/* Standard Gtk function */
+GtkType camel_maildir_store_get_type (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_MAILDIR_STORE_H */
+
+
diff --git a/configure.in b/configure.in
index 72ec0d463c..a7de8ace46 100644
--- a/configure.in
+++ b/configure.in
@@ -88,6 +88,7 @@ po/Makefile.in
camel/Makefile
camel/providers/Makefile
camel/providers/MH/Makefile
+camel/providers/maildir/Makefile
devel-docs/Makefile
devel-docs/camel/Makefile
tests/Makefile