From 6d8e4afc9e9cc9bac9807115b85aac4d2c3eb59b Mon Sep 17 00:00:00 2001 From: bertrand Date: Thu, 2 Sep 1999 16:06:55 +0000 Subject: Added (experimental) maildir provider written by Jukka Zitting 1999-09-02 bertrand * camel/providers/maildir: Added (experimental) maildir provider written by Jukka Zitting * camel/providers/Makefile.am (SUBDIRS): build maildir provider. * camel/camel-provider.c (camel_provider_get_for_protocol): bug fix. patch from Jukka Zitting svn path=/trunk/; revision=1168 --- ChangeLog | 9 + camel/camel-provider.c | 2 +- camel/providers/Makefile.am | 2 +- camel/providers/maildir/.cvsignore | 6 + camel/providers/maildir/Makefile.am | 23 + camel/providers/maildir/camel-maildir-folder.c | 701 +++++++++++++++++++++++ camel/providers/maildir/camel-maildir-folder.h | 66 +++ camel/providers/maildir/camel-maildir-provider.c | 46 ++ camel/providers/maildir/camel-maildir-store.c | 126 ++++ camel/providers/maildir/camel-maildir-store.h | 69 +++ configure.in | 1 + 11 files changed, 1049 insertions(+), 2 deletions(-) create mode 100644 camel/providers/maildir/.cvsignore create mode 100644 camel/providers/maildir/Makefile.am create mode 100644 camel/providers/maildir/camel-maildir-folder.c create mode 100644 camel/providers/maildir/camel-maildir-folder.h create mode 100644 camel/providers/maildir/camel-maildir-provider.c create mode 100644 camel/providers/maildir/camel-maildir-store.c create mode 100644 camel/providers/maildir/camel-maildir-store.h diff --git a/ChangeLog b/ChangeLog index 3a9a2fde68..df950c5b6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 1999-09-02 bertrand + * camel/providers/maildir: Added (experimental) maildir + provider written by Jukka Zitting + + * camel/providers/Makefile.am (SUBDIRS): build maildir + provider. + + * camel/camel-provider.c (camel_provider_get_for_protocol): + bug fix. patch from Jukka Zitting + * 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 . + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 . + * + * 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 +#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 . + * + * 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 . + * + * 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 . + * + * 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 +#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 -- cgit v1.2.3