Removed these directories since they're unused.

2001-01-02  Christopher James Lahey  <clahey@helixcode.com>

	* providers/maildir/, providers/mbox/, providers/mh/: Removed
	these directories since they're unused.

svn path=/trunk/; revision=7219
This commit is contained in:
Christopher James Lahey
2001-01-02 23:48:27 +00:00
committed by Chris Lahey
parent 02ee28bf77
commit dbad1c19f8
26 changed files with 5 additions and 4611 deletions

View File

@ -1,3 +1,8 @@
2001-01-02 Christopher James Lahey <clahey@helixcode.com>
* providers/maildir/, providers/mbox/, providers/mh/: Removed
these directories since they're unused.
2001-01-02 Dan Winship <danw@helixcode.com>
IMAP randomness.

View File

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
*.lo
*.la
.libs

View File

@ -1,22 +0,0 @@
## Process this file with automake to produce Makefile.in
libcamelmaildirincludedir = $(includedir)/camel
lib_LTLIBRARIES = libcamelmaildir.la
INCLUDES = -I.. -I$(srcdir)/.. -I$(top_srcdir)/intl -I$(top_srcdir)/camel \
$(GTK_INCLUDEDIR) -I$(includedir) \
-DG_LOG_DOMAIN=\"camel-maildir-provider\"
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
EXTRA_DIST =

View File

@ -1,802 +0,0 @@
/* -*- 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
*/
/*
* AUTHORS : Jukka Zitting
*
*/
#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)
static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex);
static void _set_name (CamelFolder *folder, const gchar *name, CamelException *ex);
static gboolean _exists (CamelFolder *folder, CamelException *ex);
static gboolean _create (CamelFolder *folder, CamelException *ex);
static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex);
static gboolean _delete_messages (CamelFolder *folder, CamelException *ex);
static CamelMimeMessage *_get_message (CamelFolder *folder, gint number, CamelException *ex);
static gint _get_message_count (CamelFolder *folder, CamelException *ex);
static void _expunge (CamelFolder *folder, CamelException *ex);
static GList *_list_subfolders (CamelFolder *folder, CamelException *ex);
/* fs utility functions */
static DIR * _xopendir (const gchar *path);
static gboolean _xstat (const gchar *path, struct stat *buf);
static gboolean _xmkdir (const gchar *path);
static gboolean _xrename (const gchar *from, const gchar *to);
static gboolean _xunlink (const gchar *path);
static gboolean _xrmdir (const gchar *path);
/* ** */
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 = _init_with_store;
camel_folder_class->set_name = _set_name;
camel_folder_class->exists = _exists;
camel_folder_class->create = _create;
camel_folder_class->delete = _delete;
camel_folder_class->delete_messages = _delete_messages;
camel_folder_class->expunge = _expunge;
camel_folder_class->get_message = _get_message;
camel_folder_class->get_message_count = _get_message_count;
camel_folder_class->list_subfolders = _list_subfolders;
}
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;
}
/**
* 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
_init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex)
{
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, ex);
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
folder->has_summary_capability = 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
_set_name (CamelFolder *folder, const gchar *name, CamelException *ex)
{
CamelMaildirFolder *maildir_folder;
CamelMaildirStore *maildir_store;
CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::set_name\n");
g_assert (folder);
g_assert (name);
g_assert (folder->parent_store);
maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
maildir_store = CAMEL_MAILDIR_STORE (folder->parent_store);
/* call default implementation */
parent_class->set_name (folder, name, ex);
if (maildir_folder->directory_path)
g_free (maildir_folder->directory_path);
CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::set_name full_name is %s\n", folder->full_name);
CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::set_name toplevel_dir is %s\n", maildir_store->toplevel_dir);
CAMEL_LOG_FULL_DEBUG ("CamelMaildirFolder::set_name separator is %c\n", camel_store_get_separator (folder->parent_store));
if (folder->full_name && folder->full_name[0])
maildir_folder->directory_path =
g_strconcat (maildir_store->toplevel_dir, G_DIR_SEPARATOR_S,
folder->full_name, NULL);
else
maildir_folder->directory_path = g_strdup (maildir_store->toplevel_dir);
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
_exists (CamelFolder *folder, CamelException *ex)
{
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
_create (CamelFolder *folder, CamelException *ex)
{
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, ex)) 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
_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
{
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, ex)) 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
_delete_messages (CamelFolder *folder, CamelException *ex)
{
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, ex);
/* Check if the folder didn't exist */
if (!camel_folder_exists (folder, ex)) 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 *
_get_message (CamelFolder *folder, gint number, CamelException *ex)
{
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, ex)) 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 */
message = camel_mime_message_new ();
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
_get_message_count (CamelFolder *folder, CamelException *ex)
{
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, ex)) 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);
_xrename (newfile, curfile);
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
_expunge (CamelFolder *folder, CamelException *ex)
{
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");
}
/**
* CamelMaildirFolder::list_subfolders: return a list of subfolders
* @folder: the folder object
*
* Returns the names of the maildir subfolders in a list.
*
* Return value: list of subfolder names
*/
static GList *
_list_subfolders (CamelFolder *folder, CamelException *ex)
{
CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER (folder);
const gchar *maildir;
gchar *subdir;
struct stat statbuf;
struct dirent *dir_entry;
DIR *dir_handle;
GList *subfolders = NULL;
CAMEL_LOG_FULL_DEBUG ("Entering CamelMaildirFolder::list_subfolders\n");
g_assert (folder);
/* check if the maildir exists */
if (!camel_folder_exists (folder, ex)) return NULL;
/* scan through the maildir toplevel directory */
maildir = maildir_folder->directory_path;
if ((dir_handle = _xopendir (maildir))) {
while ((dir_entry = readdir (dir_handle))) {
if (dir_entry->d_name[0] == '.') continue;
if (strcmp (dir_entry->d_name, "new") == 0) continue;
if (strcmp (dir_entry->d_name, "cur") == 0) continue;
if (strcmp (dir_entry->d_name, "tmp") == 0) continue;
subdir = g_strconcat (maildir, G_DIR_SEPARATOR_S,
dir_entry->d_name, NULL);
if (_xstat (subdir, &statbuf)
&& S_ISDIR (statbuf.st_mode))
subfolders =
g_list_append (
subfolders,
g_strdup (dir_entry->d_name));
g_free (subdir);
}
closedir (dir_handle);
}
CAMEL_LOG_FULL_DEBUG ("Leaving CamelMaildirFolder::list_subfolders\n");
return subfolders;
}
/*
* fs utility function
*
*/
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
_xrename (const gchar *from, const gchar *to)
{
g_assert (from);
g_assert (to);
if (rename (from, to) == 0) {
return TRUE;
} else {
CAMEL_LOG_WARNING ("ERROR: rename (%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;
}
}
/** *** **/

View File

@ -1,66 +0,0 @@
/* -*- 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 CAMEL_IS_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 */

View File

@ -1,46 +0,0 @@
/* -*- 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;
}

View File

@ -1,124 +0,0 @@
/* -*- 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;
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, NULL);
CF_CLASS (new_folder)->set_name (new_folder, folder_name, NULL);
return new_folder;
}

View File

@ -1,69 +0,0 @@
/* -*- 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 CAMEL_IS_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 */

View File

@ -1,7 +0,0 @@
.deps
Makefile
Makefile.in
.libs
.deps
*.lo
*.la

View File

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
libcamelmboxincludedir = $(includedir)/camel
providerdir = $(pkglibdir)/camel-providers/$(VERSION)
provider_LTLIBRARIES = libcamelmbox.la
provider_DATA = libcamelmbox.urls
INCLUDES = -I.. \
-I$(srcdir)/.. \
-I$(top_srcdir)/camel \
-I$(top_srcdir)/intl \
-I$(top_srcdir)/libibex \
-I$(top_srcdir)/e-util \
-I$(top_srcdir) \
-I$(includedir) \
$(GTK_INCLUDEDIR) \
-DG_LOG_DOMAIN=\"camel-mbox-provider\"
libcamelmbox_la_SOURCES = \
camel-mbox-folder.c \
camel-mbox-provider.c \
camel-mbox-store.c \
camel-mbox-summary.c
libcamelmboxinclude_HEADERS = \
camel-mbox-folder.h \
camel-mbox-store.h \
camel-mbox-summary.h
libcamelmbox_la_LDFLAGS = -version-info 0:0:0
libcamelmbox_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
#libcamelmbox_la_LIBADD = $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
EXTRA_DIST = libcamelmbox.urls

View File

@ -1,620 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/* camel-mbox-folder.c : Abstract class for an email folder */
/*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <notzed@helixcode.com>
* Jeffrey Stedfast <fejj@helixcode.com>
*
* Copyright (C) 1999, 2000 Helix Code Inc.
*
* 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 <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include "camel-mbox-folder.h"
#include "camel-mbox-store.h"
#include "string-utils.h"
#include "camel-stream-fs.h"
#include "camel-mbox-summary.h"
#include "camel-data-wrapper.h"
#include "camel-mime-message.h"
#include "camel-stream-filter.h"
#include "camel-mime-filter-from.h"
#include "camel-exception.h"
#define d(x)
static CamelFolderClass *parent_class = NULL;
/* Returns the class for a CamelMboxFolder */
#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CMBOXS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
static void mbox_sync(CamelFolder *folder, gboolean expunge, CamelException *ex);
static gint mbox_get_message_count(CamelFolder *folder);
static gint mbox_get_unread_message_count(CamelFolder *folder);
static void mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info,
CamelException *ex);
static GPtrArray *mbox_get_uids(CamelFolder *folder);
static GPtrArray *mbox_get_summary(CamelFolder *folder);
static CamelMimeMessage *mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex);
static void mbox_expunge(CamelFolder *folder, CamelException *ex);
static const CamelMessageInfo *mbox_get_message_info(CamelFolder *folder, const char *uid);
static GPtrArray *mbox_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex);
static void mbox_search_free(CamelFolder *folder, GPtrArray * result);
static guint32 mbox_get_message_flags(CamelFolder *folder, const char *uid);
static void mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set);
static gboolean mbox_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name);
static void mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value);
static const char *mbox_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name);
static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value);
static void mbox_finalize(CamelObject * object);
static void
camel_mbox_folder_class_init(CamelMboxFolderClass * camel_mbox_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mbox_folder_class);
parent_class = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs(camel_folder_get_type()));
/* virtual method definition */
/* virtual method overload */
camel_folder_class->sync = mbox_sync;
camel_folder_class->get_message_count = mbox_get_message_count;
camel_folder_class->get_unread_message_count = mbox_get_unread_message_count;
camel_folder_class->append_message = mbox_append_message;
camel_folder_class->get_uids = mbox_get_uids;
camel_folder_class->free_uids = camel_folder_free_deep;
camel_folder_class->get_summary = mbox_get_summary;
camel_folder_class->free_summary = camel_folder_free_nop;
camel_folder_class->expunge = mbox_expunge;
camel_folder_class->get_message = mbox_get_message;
camel_folder_class->search_by_expression = mbox_search_by_expression;
camel_folder_class->search_free = mbox_search_free;
camel_folder_class->get_message_info = mbox_get_message_info;
camel_folder_class->get_message_flags = mbox_get_message_flags;
camel_folder_class->set_message_flags = mbox_set_message_flags;
camel_folder_class->get_message_user_flag = mbox_get_message_user_flag;
camel_folder_class->set_message_user_flag = mbox_set_message_user_flag;
camel_folder_class->get_message_user_tag = mbox_get_message_user_tag;
camel_folder_class->set_message_user_tag = mbox_set_message_user_tag;
}
static void
mbox_init(gpointer object, gpointer klass)
{
CamelFolder *folder = object;
CamelMboxFolder *mbox_folder = object;
folder->has_summary_capability = TRUE;
folder->has_search_capability = TRUE;
folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT |
CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER;
/* FIXME: we don't actually preserve user flags right now. */
mbox_folder->summary = NULL;
mbox_folder->search = NULL;
}
static void
mbox_finalize(CamelObject * object)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(object);
if (mbox_folder->index)
ibex_close(mbox_folder->index);
g_free(mbox_folder->folder_file_path);
g_free(mbox_folder->summary_file_path);
g_free(mbox_folder->folder_dir_path);
g_free(mbox_folder->index_file_path);
camel_folder_change_info_free(mbox_folder->changes);
}
CamelType camel_mbox_folder_get_type(void)
{
static CamelType camel_mbox_folder_type = CAMEL_INVALID_TYPE;
if (camel_mbox_folder_type == CAMEL_INVALID_TYPE) {
camel_mbox_folder_type = camel_type_register(CAMEL_FOLDER_TYPE, "CamelMboxFolder",
sizeof(CamelMboxFolder),
sizeof(CamelMboxFolderClass),
(CamelObjectClassInitFunc) camel_mbox_folder_class_init,
NULL,
(CamelObjectInitFunc) mbox_init,
(CamelObjectFinalizeFunc) mbox_finalize);
}
return camel_mbox_folder_type;
}
CamelFolder *
camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex)
{
CamelFolder *folder;
CamelMboxFolder *mbox_folder;
const char *root_dir_path, *name;
struct stat st;
int forceindex;
folder = CAMEL_FOLDER (camel_object_new (CAMEL_MBOX_FOLDER_TYPE));
mbox_folder = (CamelMboxFolder *)folder;
name = strrchr(full_name, '/');
if (name)
name++;
else
name = full_name;
camel_folder_construct(folder, parent_store, full_name, name);
root_dir_path = camel_mbox_store_get_toplevel_dir(CAMEL_MBOX_STORE(folder->parent_store));
mbox_folder->folder_file_path = g_strdup_printf("%s/%s", root_dir_path, full_name);
mbox_folder->summary_file_path = g_strdup_printf("%s/%s-ev-summary", root_dir_path, full_name);
mbox_folder->folder_dir_path = g_strdup_printf("%s/%s.sdb", root_dir_path, full_name);
mbox_folder->index_file_path = g_strdup_printf("%s/%s.ibex", root_dir_path, full_name);
mbox_folder->changes = camel_folder_change_info_new();
/* if we have no index file, force it */
forceindex = stat(mbox_folder->index_file_path, &st) == -1;
if (flags & CAMEL_STORE_FOLDER_BODY_INDEX) {
mbox_folder->index = ibex_open(mbox_folder->index_file_path, O_CREAT | O_RDWR, 0600);
if (mbox_folder->index == NULL) {
/* yes, this isn't fatal at all */
g_warning("Could not open/create index file: %s: indexing not performed", strerror(errno));
forceindex = FALSE;
}
} else {
/* if we do have an index file, remove it */
if (forceindex == FALSE) {
unlink(mbox_folder->index_file_path);
}
forceindex = FALSE;
}
/* no summary (disk or memory), and we're proverbially screwed */
mbox_folder->summary = camel_mbox_summary_new(mbox_folder->summary_file_path,
mbox_folder->folder_file_path, mbox_folder->index);
if (mbox_folder->summary == NULL || camel_mbox_summary_load(mbox_folder->summary, forceindex) == -1) {
camel_exception_set(ex, CAMEL_EXCEPTION_FOLDER_INVALID, /* FIXME: right error code */
_("Could not create summary"));
camel_object_unref (CAMEL_OBJECT (folder));
return NULL;
}
return folder;
}
static void
mbox_sync(CamelFolder *folder, gboolean expunge, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
if (expunge)
mbox_expunge(folder, ex);
else {
camel_mbox_summary_sync(mbox_folder->summary, FALSE, mbox_folder->changes, ex);
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mbox_folder->changes);
camel_folder_change_info_clear(mbox_folder->changes);
}
/* save index */
if (mbox_folder->index)
ibex_save(mbox_folder->index);
if (mbox_folder->summary)
camel_folder_summary_save(CAMEL_FOLDER_SUMMARY(mbox_folder->summary));
}
static void
mbox_expunge(CamelFolder *folder, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
camel_mbox_summary_sync(mbox_folder->summary, TRUE, mbox_folder->changes, ex);
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mbox_folder->changes);
camel_folder_change_info_clear(mbox_folder->changes);
}
static gint
mbox_get_message_count(CamelFolder *folder)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
g_return_val_if_fail(mbox_folder->summary != NULL, -1);
return camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(mbox_folder->summary));
}
static gint
mbox_get_unread_message_count(CamelFolder *folder)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
CamelMessageInfo *info;
GPtrArray *infolist;
gint i, max, count = 0;
g_return_val_if_fail(mbox_folder->summary != NULL, -1);
max = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(mbox_folder->summary));
if (max == -1)
return -1;
infolist = mbox_get_summary(folder);
for (i = 0; i < infolist->len; i++) {
info = (CamelMessageInfo *) g_ptr_array_index(infolist, i);
if (!(info->flags & CAMEL_MESSAGE_SEEN))
count++;
}
return count;
}
/* FIXME: this may need some tweaking for performance? */
static void
mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
CamelStream *output_stream = NULL, *filter_stream = NULL;
CamelMimeFilter *filter_from = NULL;
CamelMessageInfo *newinfo;
struct stat st;
off_t seek = -1;
char *xev;
guint32 uid;
char *fromline = NULL;
if (stat(mbox_folder->folder_file_path, &st) != 0)
goto fail;
output_stream = camel_stream_fs_new_with_name(mbox_folder->folder_file_path, O_WRONLY|O_APPEND, 0600);
if (output_stream == NULL)
goto fail;
seek = st.st_size;
/* assign a new x-evolution header/uid */
camel_medium_remove_header(CAMEL_MEDIUM(message), "X-Evolution");
uid = camel_folder_summary_next_uid(CAMEL_FOLDER_SUMMARY(mbox_folder->summary));
/* important that the header matches exactly 00000000-0000 */
xev = g_strdup_printf("%08x-%04x", uid, info ? info->flags & 0xFFFF : 0);
camel_medium_add_header(CAMEL_MEDIUM(message), "X-Evolution", xev);
g_free(xev);
/* we must write this to the non-filtered stream ... */
fromline = camel_mbox_summary_build_from(CAMEL_MIME_PART(message)->headers);
if (camel_stream_printf(output_stream, seek==0?"%s":"\n%s", fromline) == -1)
goto fail;
/* and write the content to the filtering stream, that translated '\nFrom' into '\n>From' */
filter_stream = (CamelStream *) camel_stream_filter_new_with_stream(output_stream);
filter_from = (CamelMimeFilter *) camel_mime_filter_from_new();
camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from);
if (camel_data_wrapper_write_to_stream(CAMEL_DATA_WRAPPER(message), filter_stream) == -1)
goto fail;
if (camel_stream_close(filter_stream) == -1)
goto fail;
/* filter stream ref's the output stream itself, so we need to unref it too */
camel_object_unref(CAMEL_OBJECT(filter_from));
camel_object_unref(CAMEL_OBJECT(filter_stream));
camel_object_unref(CAMEL_OBJECT(output_stream));
g_free(fromline);
/* force a summary update - will only update from the new position, if it can */
if (camel_mbox_summary_update(mbox_folder->summary, seek==0?seek:seek+1, mbox_folder->changes) == 0) {
char uidstr[16];
sprintf(uidstr, "%u", uid);
newinfo = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mbox_folder->summary), uidstr);
if (info && newinfo) {
CamelFlag *flag = info->user_flags;
CamelTag *tag = info->user_tags;
while (flag) {
camel_flag_set(&(newinfo->user_flags), flag->name, TRUE);
flag = flag->next;
}
while (tag) {
camel_tag_set(&(newinfo->user_tags), tag->name, tag->value);
tag = tag->next;
}
}
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mbox_folder->changes);
camel_folder_change_info_clear(mbox_folder->changes);
}
return;
fail:
if (camel_exception_is_set(ex)) {
camel_exception_setv(ex, camel_exception_get_id(ex),
_("Cannot append message to mbox file: %s"), camel_exception_get_description(ex));
} else {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot append message to mbox file: %s"), g_strerror(errno));
}
if (filter_stream) {
/*camel_stream_close (filter_stream); */
camel_object_unref(CAMEL_OBJECT(filter_stream));
}
if (output_stream)
camel_object_unref(CAMEL_OBJECT(output_stream));
if (filter_from)
camel_object_unref(CAMEL_OBJECT(filter_from));
g_free(fromline);
/* make sure the file isn't munged by us */
if (seek != -1) {
int fd = open(mbox_folder->folder_file_path, O_WRONLY, 0600);
if (fd != -1) {
ftruncate(fd, st.st_size);
close(fd);
}
}
}
static GPtrArray *
mbox_get_uids(CamelFolder *folder)
{
GPtrArray *array;
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
int i, count;
count = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(mbox_folder->summary));
array = g_ptr_array_new();
g_ptr_array_set_size(array, count);
for (i = 0; i < count; i++) {
CamelMboxMessageInfo *info =
(CamelMboxMessageInfo *) camel_folder_summary_index(CAMEL_FOLDER_SUMMARY(mbox_folder->summary), i);
array->pdata[i] = g_strdup(info->info.uid);
}
return array;
}
static CamelMimeMessage *
mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
CamelStream *message_stream = NULL;
CamelMimeMessage *message = NULL;
CamelMboxMessageInfo *info;
CamelMimeParser *parser = NULL;
char *buffer;
int len;
/* get the message summary info */
info = (CamelMboxMessageInfo *) camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mbox_folder->summary), uid);
if (info == NULL) {
errno = ENOENT;
goto fail;
}
/* if this has no content, its an error in the library */
g_assert(info->info.content);
g_assert(info->frompos != -1);
/* where we read from */
message_stream = camel_stream_fs_new_with_name(mbox_folder->folder_file_path, O_RDONLY, 0);
if (message_stream == NULL)
goto fail;
/* we use a parser to verify the message is correct, and in the correct position */
parser = camel_mime_parser_new();
camel_mime_parser_init_with_stream(parser, message_stream);
camel_object_unref(CAMEL_OBJECT(message_stream));
camel_mime_parser_scan_from(parser, TRUE);
camel_mime_parser_seek(parser, info->frompos, SEEK_SET);
if (camel_mime_parser_step(parser, &buffer, &len) != HSCAN_FROM) {
g_warning("File appears truncated");
goto fail;
}
if (camel_mime_parser_tell_start_from(parser) != info->frompos) {
/* TODO: This should probably perform a re-sync/etc, and try again? */
g_warning("Summary doesn't match the folder contents! eek!\n"
" expecting offset %ld got %ld", (long int)info->frompos,
(long int)camel_mime_parser_tell_start_from(parser));
errno = EINVAL;
goto fail;
}
message = camel_mime_message_new();
if (camel_mime_part_construct_from_parser(CAMEL_MIME_PART(message), parser) == -1) {
g_warning("Construction failed");
goto fail;
}
camel_object_unref(CAMEL_OBJECT(parser));
return message;
fail:
camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s"), g_strerror(errno));
if (parser)
camel_object_unref(CAMEL_OBJECT(parser));
if (message)
camel_object_unref(CAMEL_OBJECT(message));
return NULL;
}
GPtrArray *
mbox_get_summary(CamelFolder *folder)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
return CAMEL_FOLDER_SUMMARY(mbox_folder->summary)->messages;
}
/* get a single message info, by uid */
static const CamelMessageInfo *
mbox_get_message_info(CamelFolder *folder, const char *uid)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
return camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mbox_folder->summary), uid);
}
static GPtrArray *
mbox_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
if (mbox_folder->search == NULL) {
mbox_folder->search = camel_folder_search_new();
}
camel_folder_search_set_folder(mbox_folder->search, folder);
if (mbox_folder->summary) {
/* FIXME: dont access summary array directly? */
camel_folder_search_set_summary(mbox_folder->search,
CAMEL_FOLDER_SUMMARY(mbox_folder->summary)->messages);
}
camel_folder_search_set_body_index(mbox_folder->search, mbox_folder->index);
return camel_folder_search_execute_expression(mbox_folder->search, expression, ex);
}
static void
mbox_search_free(CamelFolder *folder, GPtrArray * result)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
camel_folder_search_free_result(mbox_folder->search, result);
}
static guint32
mbox_get_message_flags(CamelFolder *folder, const char *uid)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, 0);
return info->flags;
}
static void
mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
info->flags = (info->flags & ~flags) | (set & flags) | CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}
static gboolean
mbox_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, FALSE);
return camel_flag_get(&info->user_flags, name);
}
static void
mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
camel_flag_set(&info->user_flags, name, value);
info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}
static const char *mbox_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, FALSE);
return camel_tag_get(&info->user_tags, name);
}
static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value)
{
CamelMessageInfo *info;
CamelMboxFolder *mf = CAMEL_MBOX_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
camel_tag_set(&info->user_tags, name, value);
info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}

View File

@ -1,83 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-folder.h : Abstract class for an email folder */
/*
*
* Author : Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright (C) 1999 Helix Code .
*
* 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_MBOX_FOLDER_H
#define CAMEL_MBOX_FOLDER_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus }*/
#include <camel/camel-folder.h>
#include <camel/camel-folder-search.h>
#include <libibex/ibex.h>
#include "camel-mbox-summary.h"
/* #include "camel-store.h" */
#define CAMEL_MBOX_FOLDER_TYPE (camel_mbox_folder_get_type ())
#define CAMEL_MBOX_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolder))
#define CAMEL_MBOX_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolderClass))
#define CAMEL_IS_MBOX_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_FOLDER_TYPE))
typedef struct {
CamelFolder parent_object;
gchar *folder_file_path; /* contains the messages */
gchar *summary_file_path; /* contains the messages summary */
gchar *folder_dir_path; /* contains the subfolders */
gchar *index_file_path; /* index of body contents */
ibex *index; /* index for this folder */
CamelMboxSummary *summary;
CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */
CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */
} CamelMboxFolder;
typedef struct {
CamelFolderClass parent_class;
/* Virtual methods */
} CamelMboxFolderClass;
/* public methods */
/* flags are taken from CAMEL_STORE_FOLDER_* flags */
CamelFolder *camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex);
/* Standard Camel function */
CamelType camel_mbox_folder_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_MBOX_FOLDER_H */

View File

@ -1,59 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-provider.c: mbox provider registration code */
/*
* Authors :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright (C) 2000 HelixCode (www.helixcode.com).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "config.h"
#include "camel-mbox-store.h"
#include "camel-provider.h"
#include "camel-session.h"
#include "camel-url.h"
static CamelProvider mbox_provider = {
"mbox",
N_("UNIX mbox-format mail files"),
N_("For reading mail delivered by the local system, and for "
"storing mail on local disk."),
"mail",
CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE,
CAMEL_URL_NEED_PATH,
{ 0, 0 },
NULL
};
void
camel_provider_module_init (CamelSession *session)
{
mbox_provider.object_types[CAMEL_PROVIDER_STORE] =
camel_mbox_store_get_type();
mbox_provider.service_cache = g_hash_table_new (camel_url_hash, camel_url_equal);
camel_session_register_provider (session, &mbox_provider);
}

View File

@ -1,287 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-store.c : class for an mbox store */
/*
*
* Copyright (C) 2000 Helix Code, Inc. <bertrand@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "camel-mbox-store.h"
#include "camel-mbox-folder.h"
#include "camel-exception.h"
#include "camel-url.h"
/* Returns the class for a CamelMboxStore */
#define CMBOXS_CLASS(so) CAMEL_MBOX_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
static char *get_name(CamelService *service, gboolean brief);
static CamelFolder *get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex);
static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
static char *get_folder_name(CamelStore *store, const char *folder_name, CamelException *ex);
static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top,
gboolean fast, gboolean recursive,
gboolean subscribed_only,
CamelException *ex);
static void
camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class)
{
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_mbox_store_class);
CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_mbox_store_class);
/* virtual method overload */
camel_service_class->get_name = get_name;
camel_store_class->get_folder = get_folder;
camel_store_class->delete_folder = delete_folder;
camel_store_class->rename_folder = rename_folder;
camel_store_class->get_folder_name = get_folder_name;
camel_store_class->get_folder_info = get_folder_info;
camel_store_class->free_folder_info = camel_store_free_folder_info_full;
}
static void
camel_mbox_store_init (gpointer object, gpointer klass)
{
CamelStore *store = CAMEL_STORE (object);
/* mbox names are filenames, so they are case-sensitive. */
store->folders = g_hash_table_new (g_str_hash, g_str_equal);
}
CamelType
camel_mbox_store_get_type (void)
{
static CamelType camel_mbox_store_type = CAMEL_INVALID_TYPE;
if (camel_mbox_store_type == CAMEL_INVALID_TYPE) {
camel_mbox_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelMboxStore",
sizeof (CamelMboxStore),
sizeof (CamelMboxStoreClass),
(CamelObjectClassInitFunc) camel_mbox_store_class_init,
NULL,
(CamelObjectInitFunc) camel_mbox_store_init,
NULL);
}
return camel_mbox_store_type;
}
const gchar *
camel_mbox_store_get_toplevel_dir (CamelMboxStore *store)
{
CamelURL *url = CAMEL_SERVICE (store)->url;
g_assert (url != NULL);
return url->path;
}
static CamelFolder *
get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex)
{
char *name;
struct stat st;
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
if (stat(name, &st) == -1) {
int fd;
if (errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not open file `%s':\n%s"),
name, g_strerror(errno));
g_free(name);
return NULL;
}
if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Folder `%s' does not exist."),
folder_name);
g_free(name);
return NULL;
}
fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0600);
if (fd == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not create file `%s':\n%s"),
name, g_strerror(errno));
g_free(name);
return NULL;
}
g_free(name);
close(fd);
} else if (!S_ISREG(st.st_mode)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("`%s' is not a regular file."),
name);
g_free(name);
return NULL;
} else
g_free(name);
return camel_mbox_folder_new(store, folder_name, flags, ex);
}
static void
delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
{
char *name, *name2;
struct stat st;
int status;
name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path, folder_name);
if (stat (name, &st) == -1) {
if (errno == ENOENT) {
/* file doesn't exist - it's kinda like deleting it ;-) */
g_free (name);
return;
}
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s':\n%s"),
folder_name, g_strerror (errno));
g_free (name);
return;
}
if (!S_ISREG (st.st_mode)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("`%s' is not a regular file."), name);
g_free (name);
return;
}
if (st.st_size != 0) {
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY,
_("Folder `%s' is not empty. Not deleted."),
folder_name);
g_free (name);
return;
}
/* Delete index and summary first, then the main file. */
name2 = g_strdup_printf ("%s.ibex", name);
status = unlink (name2);
g_free (name2);
if (status == 0 || errno == ENOENT) {
name2 = g_strdup_printf ("%s-ev-summary", name);
status = unlink (name2);
g_free (name2);
}
if (status == 0 || errno == ENOENT)
status = unlink (name);
g_free (name);
if (status == -1 && errno != ENOENT) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s':\n%s"),
folder_name, g_strerror (errno));
}
}
static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, CamelException *ex)
{
struct stat st;
char *old = g_strconcat(prefix, oldp, suffix, 0);
char *new = g_strconcat(prefix, newp, suffix, 0);
int ret = -1;
printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix);
/* FIXME: this has races ... */
if (!(stat(new, &st) == -1 && errno==ENOENT)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename folder %s to %s: destination exists"),
old, new);
} else if (rename(old, new) == 0 || errno==ENOENT) {
ret = 0;
} else if (stat(old, &st) == -1 && errno==ENOENT && stat(new, &st) == 0) {
/* for nfs, check if the rename worked anyway ... */
ret = 0;
}
g_free(old);
g_free(new);
return ret;
}
static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex)
{
char *path = CAMEL_SERVICE (store)->url->path;
/* try to rollback failures, has obvious races */
if (xrename(old, new, path, ".ibex", ex)) {
return;
}
if (xrename(old, new, path, "-ev-summary", ex)) {
xrename(new, old, path, ".ibex", ex);
return;
}
if (xrename(old, new, path, "", ex)) {
xrename(new, old, path, "-ev-summary", ex);
xrename(new, old, path, ".ibex", ex);
}
}
static char *
get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex)
{
/* For now, we don't allow hieararchy. FIXME. */
if (strchr (folder_name + 1, '/')) {
camel_exception_set (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Mbox folders may not be nested."));
return NULL;
}
return *folder_name == '/' ? g_strdup (folder_name) :
g_strdup_printf ("/%s", folder_name);
}
static char *
get_name (CamelService *service, gboolean brief)
{
if (brief)
return g_strdup (service->url->path);
else
return g_strdup_printf (_("Local mail file %s"), service->url->path);
}
static CamelFolderInfo *
get_folder_info (CamelStore *store, const char *top,
gboolean fast, gboolean recursive,
gboolean subscribed_only,
CamelException *ex)
{
/* FIXME: This is broken, but it corresponds to what was
* there before.
*/
return NULL;
}

View File

@ -1,68 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-store.h : class for an mbox store */
/*
*
* Copyright (C) 2000 Helix Code, Inc. <bertrand@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef CAMEL_MBOX_STORE_H
#define CAMEL_MBOX_STORE_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus }*/
#include "camel-store.h"
#define CAMEL_MBOX_STORE_TYPE (camel_mbox_store_get_type ())
#define CAMEL_MBOX_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_STORE_TYPE, CamelMboxStore))
#define CAMEL_MBOX_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_STORE_TYPE, CamelMboxStoreClass))
#define CAMEL_IS_MBOX_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_STORE_TYPE))
typedef struct {
CamelStore parent_object;
} CamelMboxStore;
typedef struct {
CamelStoreClass parent_class;
} CamelMboxStoreClass;
/* public methods */
/* Standard Camel function */
CamelType camel_mbox_store_get_type (void);
const gchar *camel_mbox_store_get_toplevel_dir (CamelMboxStore *store);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_MBOX_STORE_H */

View File

@ -1,894 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/*
* Copyright (C) 2000 Helix Code Inc.
*
* Authors: Michael Zucchi <notzed@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "camel-mbox-summary.h"
#include <camel/camel-mime-message.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define io(x)
#define d(x) x
#define CAMEL_MBOX_SUMMARY_VERSION (0x1000)
struct _CamelMboxSummaryPrivate {
};
#define _PRIVATE(o) (((CamelMboxSummary *)(o))->priv)
static int summary_header_load (CamelFolderSummary *, FILE *);
static int summary_header_save (CamelFolderSummary *, FILE *);
static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _header_raw *);
static CamelMessageInfo * message_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *);
static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *);
static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *);
/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/
static void camel_mbox_summary_class_init (CamelMboxSummaryClass *klass);
static void camel_mbox_summary_init (CamelMboxSummary *obj);
static void camel_mbox_summary_finalise (CamelObject *obj);
static CamelFolderSummaryClass *camel_mbox_summary_parent;
CamelType
camel_mbox_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_folder_summary_get_type(), "CamelMboxSummary",
sizeof (CamelMboxSummary),
sizeof (CamelMboxSummaryClass),
(CamelObjectClassInitFunc) camel_mbox_summary_class_init,
NULL,
(CamelObjectInitFunc) camel_mbox_summary_init,
(CamelObjectFinalizeFunc) camel_mbox_summary_finalise);
}
return type;
}
static void
camel_mbox_summary_class_init(CamelMboxSummaryClass *klass)
{
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass;
camel_mbox_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
sklass->summary_header_load = summary_header_load;
sklass->summary_header_save = summary_header_save;
sklass->message_info_new = message_info_new;
sklass->message_info_new_from_parser = message_info_new_from_parser;
sklass->message_info_load = message_info_load;
sklass->message_info_save = message_info_save;
/*sklass->message_info_free = message_info_free;*/
}
static void
camel_mbox_summary_init(CamelMboxSummary *obj)
{
struct _CamelMboxSummaryPrivate *p;
struct _CamelFolderSummary *s = (CamelFolderSummary *)obj;
p = _PRIVATE(obj) = g_malloc0(sizeof(*p));
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelMboxMessageInfo);
s->content_info_size = sizeof(CamelMboxMessageContentInfo);
/* and a unique file version */
s->version += CAMEL_MBOX_SUMMARY_VERSION;
}
static void
camel_mbox_summary_finalise(CamelObject *obj)
{
CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(obj);
g_free(mbs->folder_path);
}
/**
* camel_mbox_summary_new:
*
* Create a new CamelMboxSummary object.
*
* Return value: A new CamelMboxSummary widget.
**/
CamelMboxSummary *
camel_mbox_summary_new(const char *filename, const char *mbox_name, ibex *index)
{
CamelMboxSummary *new = CAMEL_MBOX_SUMMARY(camel_object_new(camel_mbox_summary_get_type()));
if (new) {
/* ?? */
camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), TRUE);
camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename);
new->folder_path = g_strdup(mbox_name);
new->index = index;
}
return new;
}
static int
summary_header_load(CamelFolderSummary *s, FILE *in)
{
CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1)
return -1;
return camel_folder_summary_decode_uint32(in, &mbs->folder_size);
}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
{
CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1)
return -1;
return camel_folder_summary_encode_uint32(out, mbs->folder_size);
}
static int
header_evolution_decode(const char *in, guint32 *uid, guint32 *flags)
{
char *header;
if (in && (header = header_token_decode(in))) {
if (strlen (header) == strlen ("00000000-0000")
&& sscanf (header, "%08x-%04x", uid, flags) == 2) {
g_free(header);
return *uid;
}
g_free(header);
}
return -1;
}
static char *
header_evolution_encode(guint32 uid, guint32 flags)
{
return g_strdup_printf("%08x-%04x", uid, flags & 0xffff);
}
static CamelMessageInfo *
message_info_new(CamelFolderSummary *s, struct _header_raw *h)
{
CamelMessageInfo *mi;
mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new(s, h);
if (mi) {
const char *xev;
guint32 uid, flags;
CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
xev = header_raw_find(&h, "X-Evolution", NULL);
if (xev && header_evolution_decode(xev, &uid, &flags) != -1) {
g_free(mi->uid);
mi->uid = g_strdup_printf("%u", uid);
if (camel_folder_summary_uid(s, mi->uid)) {
g_free(mi->uid);
mi->uid = camel_folder_summary_next_uid_string(s);
} else {
/* so we dont get clashes later on */
camel_folder_summary_set_uid(s, uid+1);
}
mi->flags = flags;
} else {
/* to indicate it has no xev header? */
mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
mi->uid = g_strdup_printf("%u", camel_folder_summary_next_uid(s));
}
mbi->frompos = -1;
}
return mi;
}
static CamelMessageInfo *
message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
{
CamelMessageInfo *mi;
CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new_from_parser(s, mp);
if (mi) {
CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
mbi->frompos = camel_mime_parser_tell_start_from(mp);
/* do we want to index this message as we add it, as well? */
if (mbs->index
&& (mbs->index_force
|| (mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0
|| !ibex_contains_name(mbs->index, mi->uid))) {
camel_folder_summary_set_index(s, mbs->index);
} else {
camel_folder_summary_set_index(s, NULL);
}
}
return mi;
}
static CamelMessageInfo *
message_info_load(CamelFolderSummary *s, FILE *in)
{
CamelMessageInfo *mi;
io(printf("loading mbox message info\n"));
mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_load(s, in);
if (mi) {
guint32 position;
CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
camel_folder_summary_decode_uint32(in, &position);
mbi->frompos = position;
}
return mi;
}
static int
message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi)
{
CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
io(printf("saving mbox message info\n"));
((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_save(s, out, mi);
return camel_folder_summary_encode_uint32(out, mbi->frompos);
}
static int
summary_rebuild(CamelMboxSummary *mbs, off_t offset)
{
CamelFolderSummary *s = CAMEL_FOLDER_SUMMARY(mbs);
CamelMimeParser *mp;
int fd;
int ok = 0;
fd = open(mbs->folder_path, O_RDONLY);
if (fd == -1) {
printf("%s failed to open: %s", mbs->folder_path, strerror(errno));
return -1;
}
mp = camel_mime_parser_new();
camel_mime_parser_init_with_fd(mp, fd);
camel_mime_parser_scan_from(mp, TRUE);
camel_mime_parser_seek(mp, offset, SEEK_SET);
if (offset > 0) {
if (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) {
if (camel_mime_parser_tell_start_from(mp) != offset) {
g_warning ("The next message didn't start where I expected\nbuilding summary from start");
camel_mime_parser_drop_step(mp);
offset = 0;
camel_mime_parser_seek(mp, offset, SEEK_SET);
camel_folder_summary_clear(CAMEL_FOLDER_SUMMARY(mbs));
} else {
camel_mime_parser_unstep(mp);
}
} else {
camel_object_unref(CAMEL_OBJECT(mp));
/* end of file - no content? */
return -1;
}
}
while (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) {
CamelMessageInfo *info;
info = camel_folder_summary_add_from_parser(CAMEL_FOLDER_SUMMARY(mbs), mp);
if (info == NULL) {
printf ("Could not build info from file?\n");
ok = -1;
break;
}
g_assert(camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM_END);
}
camel_object_unref(CAMEL_OBJECT (mp));
/* update the file size/mtime in the summary */
if (ok != -1) {
struct stat st;
if (stat(mbs->folder_path, &st) == 0) {
mbs->folder_size = st.st_size;
s->time = st.st_mtime;
}
}
return ok;
}
int
camel_mbox_summary_update(CamelMboxSummary *mbs, off_t offset, CamelFolderChangeInfo *changeinfo)
{
int ret, i, count;
CamelFolderSummary *s = (CamelFolderSummary *)mbs;
/* we use the diff function of the change_info to build the update list. */
for (i = 0; i < camel_folder_summary_count(s); i++) {
CamelMessageInfo *mi = camel_folder_summary_index(s, i);
camel_folder_change_info_add_source(changeinfo, mi->uid);
}
/* do the actual work */
mbs->index_force = FALSE;
ret = summary_rebuild(mbs, offset);
count = camel_folder_summary_count(s);
for (i = 0; i < count; i++) {
CamelMessageInfo *mi = camel_folder_summary_index(s, i);
camel_folder_change_info_add_update(changeinfo, mi->uid);
}
camel_folder_change_info_build_diff(changeinfo);
#if 0
#warning "Saving full summary and index after every summarisation is slow ..."
if (ret != -1) {
if (camel_folder_summary_save((CamelFolderSummary *)mbs) == -1)
g_warning("Could not save summary: %s", strerror(errno));
if (mbs->index)
ibex_save(mbs->index);
}
#endif
return ret;
}
int
camel_mbox_summary_load(CamelMboxSummary *mbs, int forceindex)
{
CamelFolderSummary *s = CAMEL_FOLDER_SUMMARY(mbs);
struct stat st;
int ret = 0;
off_t minstart;
mbs->index_force = forceindex;
/* is the summary out of date? */
if (stat(mbs->folder_path, &st) == -1) {
camel_folder_summary_clear(s);
printf("Cannot summarise folder: '%s': %s\n", mbs->folder_path, strerror(errno));
return -1;
}
if (forceindex || camel_folder_summary_load(s) == -1) {
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
} else {
minstart = st.st_size;
#if 0
/* find out the first unindexed message ... */
/* TODO: For this to work, it has to check that the message is
indexable, and contains content ... maybe it cannot be done
properly? */
for (i = 0; i < camel_folder_summary_count(s); i++) {
CamelMessageInfo *mi = camel_folder_summary_index(s, i);
if (mbs->index && !ibex_contains_name(mbs->index, mi->uid)) {
minstart = ((CamelMboxMessageInfo *) mi)->frompos;
printf("Found unindexed message: %s\n", mi->uid);
break;
}
}
#endif
/* is the summary uptodate? */
if (st.st_size == mbs->folder_size && st.st_mtime == s->time) {
if (minstart < st.st_size) {
/* FIXME: Only clear the messages and reindex from this point forward */
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
}
} else {
if (mbs->folder_size < st.st_size) {
if (minstart < mbs->folder_size) {
/* FIXME: only make it rebuild as necessary */
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
} else {
ret = summary_rebuild(mbs, mbs->folder_size);
/* If that fails, it might be because a message was changed
* rather than appended... so try again from the beginning.
*/
if (ret == -1) {
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
}
}
} else {
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
}
}
}
if (ret != -1) {
mbs->folder_size = st.st_size;
s->time = st.st_mtime;
if (camel_folder_summary_save(s) == -1)
g_warning("Could not save summary: %s", strerror(errno));
if (mbs->index)
ibex_save(mbs->index);
}
return ret;
}
static int
header_write(int fd, struct _header_raw *header, char *xevline)
{
struct iovec iv[4];
int outlen = 0, len;
iv[1].iov_base = ":";
iv[1].iov_len = 1;
iv[3].iov_base = "\n";
iv[3].iov_len = 1;
while (header) {
if (strcasecmp(header->name, "X-Evolution")) {
iv[0].iov_base = header->name;
iv[0].iov_len = strlen(header->name);
iv[2].iov_base = header->value;
iv[2].iov_len = strlen(header->value);
do {
len = writev(fd, iv, 4);
} while (len == -1 && errno == EINTR);
if (len == -1)
return -1;
outlen += len;
}
header = header->next;
}
iv[0].iov_base = "X-Evolution: ";
iv[0].iov_len = strlen(iv[0].iov_base);
iv[1].iov_base = xevline;
iv[1].iov_len = strlen(xevline);
iv[2].iov_base = "\n\n";
iv[2].iov_len = 2;
do {
len = writev(fd, iv, 3);
} while (len == -1 && errno == EINTR);
if (len == -1)
return -1;
outlen += 1;
d(printf("Wrote %d bytes of headers\n", outlen));
return outlen;
}
static int
copy_block(int fromfd, int tofd, off_t start, size_t bytes)
{
char buffer[4096];
int written = 0;
d(printf("writing %d bytes ... ", bytes));
if (lseek(fromfd, start, SEEK_SET) != start)
return -1;
while (bytes > 0) {
int toread, towrite;
toread = bytes;
if (bytes > 4096)
toread = 4096;
else
toread = bytes;
do {
towrite = read(fromfd, buffer, toread);
} while (towrite == -1 && errno == EINTR);
if (towrite == -1)
return -1;
/* check for 'end of file' */
if (towrite == 0) {
d(printf("end of file?\n"));
break;
}
do {
toread = write(tofd, buffer, towrite);
} while (toread == -1 && errno == EINTR);
if (toread == -1)
return -1;
written += toread;
bytes -= toread;
}
d(printf("written %d bytes\n", written));
return written;
}
static char *tz_months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static char *tz_days[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
/* tries to build a From line, based on message headers */
char *
camel_mbox_summary_build_from(struct _header_raw *header)
{
GString *out = g_string_new("From ");
char *ret;
const char *tmp;
time_t thetime;
int offset;
struct tm tm;
tmp = header_raw_find(&header, "Sender", NULL);
if (tmp == NULL)
tmp = header_raw_find(&header, "From", NULL);
if (tmp != NULL) {
struct _header_address *addr = header_address_decode(tmp);
tmp = NULL;
if (addr) {
if (addr->type == HEADER_ADDRESS_NAME) {
g_string_append(out, addr->v.addr);
tmp = "";
}
header_address_unref(addr);
}
}
if (tmp == NULL) {
g_string_append(out, "unknown@nodomain.now.au");
}
/* try use the received header to get the date */
tmp = header_raw_find(&header, "Received", NULL);
if (tmp) {
tmp = strrchr(tmp, ';');
if (tmp)
tmp++;
}
/* if there isn't one, try the Date field */
if (tmp == NULL)
tmp = header_raw_find(&header, "Date", NULL);
thetime = header_decode_date(tmp, &offset);
thetime += ((offset / 100) * (60 * 60)) + (offset % 100) * 60;
/* a pseudo, but still bogus attempt at thread safing the function */
/*memcpy(&tm, gmtime(&thetime), sizeof(tm));*/
gmtime_r(&thetime, &tm);
g_string_sprintfa(out, " %s %s %2d %02d:%02d:%02d %4d\n",
tz_days[tm.tm_wday],
tz_months[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900);
ret = out->str;
g_string_free(out, FALSE);
return ret;
}
int
camel_mbox_summary_sync(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
{
CamelMimeParser *mp = NULL;
int i, count;
CamelMboxMessageInfo *info;
CamelFolderSummary *s = CAMEL_FOLDER_SUMMARY(mbs);
int fd = -1, fdout = -1;
off_t offset = 0;
char *tmpname = NULL;
char *buffer, *xevnew = NULL;
const char *xev;
int len;
guint32 uid, flags;
int quick = TRUE, work = FALSE;
struct stat st;
char *fromline;
/* make sure we're in sync, after this point we at least have a complete list of id's */
count = camel_folder_summary_count (s);
if (count > 0) {
CamelMessageInfo *mi = camel_folder_summary_index(s, count - 1);
camel_mbox_summary_update(mbs, mi->content->endpos, changeinfo);
} else {
camel_mbox_summary_update(mbs, 0, changeinfo);
}
/* check if we have any work to do */
d(printf("Performing sync, %d messages in inbox\n", count));
for (i = 0; quick && i < count; i++) {
info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
if ((expunge && (info->info.flags & CAMEL_MESSAGE_DELETED)) ||
(info->info.flags & CAMEL_MESSAGE_FOLDER_NOXEV))
quick = FALSE;
else
work |= (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
}
d(printf("Options: %s %s %s\n", expunge ? "expunge" : "", quick ? "quick" : "", work ? "Work" : ""));
if (quick && !work)
return 0;
fd = open(mbs->folder_path, O_RDWR);
if (fd == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not open summary %s"), mbs->folder_path);
return -1;
}
mp = camel_mime_parser_new();
camel_mime_parser_scan_from(mp, TRUE);
camel_mime_parser_init_with_fd(mp, fd);
if (!quick) {
tmpname = alloca(strlen (mbs->folder_path) + 5);
sprintf(tmpname, "%s.tmp", mbs->folder_path);
d(printf("Writing tmp file to %s\n", tmpname));
retry_out:
fdout = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (fdout == -1) {
if (errno == EEXIST)
if (unlink(tmpname) != -1)
goto retry_out;
tmpname = NULL;
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot open temporary mailbox: %s"), strerror(errno));
goto error;
}
}
for (i = 0; i < count; i++) {
off_t frompos, bodypos, lastpos;
/* This has to be an int, not an off_t, because that's
* what camel_mime_parser_header returns... FIXME.
*/
int xevoffset;
info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
g_assert(info);
d(printf("Looking at message %s\n", info->info.uid));
if (expunge && info->info.flags & CAMEL_MESSAGE_DELETED) {
d(printf("Deleting %s\n", info->info.uid));
g_assert(!quick);
offset -= (info->info.content->endpos - info->frompos);
if (mbs->index)
ibex_unindex(mbs->index, info->info.uid);
/* remove it from teh change list */
camel_folder_change_info_remove_uid(changeinfo, info->info.uid);
camel_folder_summary_remove(s, (CamelMessageInfo *)info);
count--;
i--;
info = NULL;
} else if (info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) {
int xevok = FALSE;
d(printf("Updating header for %s flags = %08x\n", info->info.uid, info->info.flags));
/* find the next message, header parts */
camel_mime_parser_seek(mp, info->frompos, SEEK_SET);
if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM) {
g_warning("camel_mime_parser_step failed (1)");
goto error;
}
if (camel_mime_parser_tell_start_from (mp) != info->frompos) {
g_warning("Summary/mbox mismatch, aborting sync");
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Summary mismatch, aborting sync"));
goto error;
}
if (camel_mime_parser_step (mp, &buffer, &len) == HSCAN_FROM_END) {
g_warning("camel_mime_parser_step failed (2)");
goto error;
}
/* Check if the X-Evolution header is valid. */
xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset);
if (xev && header_evolution_decode (xev, &uid, &flags) != -1)
xevok = TRUE;
xevnew = header_evolution_encode(strtoul (info->info.uid, NULL, 10), info->info.flags & 0xffff);
if (quick) {
if (!xevok) {
g_warning("The summary told me I had an X-Evolution header, but i dont!");
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Summary mismatch, X-Evolution header missing"));
goto error;
}
buffer = g_strdup_printf("X-Evolution: %s", xevnew);
lastpos = lseek(fd, 0, SEEK_CUR);
lseek(fd, xevoffset, SEEK_SET);
do {
len = write(fd, buffer, strlen (buffer));
} while (len == -1 && errno == EINTR);
lseek(fd, lastpos, SEEK_SET);
g_free(buffer);
if (len == -1) {
goto error;
}
} else {
frompos = lseek(fdout, 0, SEEK_CUR);
fromline = camel_mbox_summary_build_from(camel_mime_parser_headers_raw (mp));
write(fdout, fromline, strlen(fromline));
g_free(fromline);
if (header_write(fdout, camel_mime_parser_headers_raw(mp), xevnew) == -1) {
d(printf("Error writing to tmp mailbox\n"));
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Error writing to temp mailbox: %s"),
strerror(errno));
goto error;
}
bodypos = lseek(fdout, 0, SEEK_CUR);
d(printf("pos = %d, endpos = %d, bodypos = %d\n",
(int) info->info.content->pos,
(int) info->info.content->endpos,
(int) info->info.content->bodypos));
if (copy_block(fd, fdout, info->info.content->bodypos,
info->info.content->endpos - info->info.content->bodypos) == -1) {
g_warning("Cannot copy data to output fd");
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot copy data to output file: %s"),
strerror (errno));
goto error;
}
info->frompos = frompos;
offset = bodypos - info->info.content->bodypos;
}
info->info.flags &= 0xffff;
g_free(xevnew);
xevnew = NULL;
camel_mime_parser_drop_step(mp);
camel_mime_parser_drop_step(mp);
} else {
if (!quick) {
if (copy_block(fd, fdout, info->frompos,
info->info.content->endpos - info->frompos) == -1) {
g_warning("Cannot copy data to output fd");
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot copy data to output file: %s"),
strerror(errno));
goto error;
}
/* update from pos here? */
info->frompos += offset;
} else {
d(printf("Nothing to do for this message\n"));
}
}
if (!quick && info != NULL && offset != 0) {
d(printf("offsetting content: %d\n", (int)offset));
camel_folder_summary_offset_content(info->info.content, offset);
d(printf("pos = %d, endpos = %d, bodypos = %d\n",
(int) info->info.content->pos,
(int) info->info.content->endpos,
(int) info->info.content->bodypos));
}
}
d(printf("Closing folders\n"));
if (close(fd) == -1) {
g_warning("Cannot close source folder: %s", strerror(errno));
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not close source folder %s: %s"),
mbs->folder_path, strerror(errno));
goto error;
}
if (!quick) {
if (close(fdout) == -1) {
g_warning("Cannot close tmp folder: %s", strerror(errno));
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not close temp folder: %s"),
strerror(errno));
goto error;
}
if (rename(tmpname, mbs->folder_path) == -1) {
g_warning("Cannot rename folder: %s", strerror(errno));
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename folder: %s"),
strerror(errno));
goto error;
}
tmpname = NULL;
if (mbs->index)
ibex_save(mbs->index);
}
if (stat(mbs->folder_path, &st) == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Unknown error: %s"),
strerror(errno));
goto error;
}
camel_folder_summary_touch(s);
s->time = st.st_mtime;
mbs->folder_size = st.st_size;
camel_folder_summary_save(s);
camel_object_unref(CAMEL_OBJECT(mp));
return 0;
error:
if (fd != -1)
close(fd);
if (fdout != -1)
close(fdout);
g_free(xevnew);
if (tmpname)
unlink(tmpname);
if (mp)
camel_object_unref(CAMEL_OBJECT(mp));
return -1;
}

View File

@ -1,81 +0,0 @@
/*
* Copyright (C) 2000 Helix Code Inc.
*
* Authors: Michael Zucchi <notzed@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef _CAMEL_MBOX_SUMMARY_H
#define _CAMEL_MBOX_SUMMARY_H
#include <camel/camel-folder-summary.h>
#include <camel/camel-folder.h>
#include <camel/camel-exception.h>
#include <libibex/ibex.h>
#define CAMEL_MBOX_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mbox_summary_get_type (), CamelMboxSummary)
#define CAMEL_MBOX_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mbox_summary_get_type (), CamelMboxSummaryClass)
#define CAMEL_IS_MBOX_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mbox_summary_get_type ())
typedef struct _CamelMboxSummary CamelMboxSummary;
typedef struct _CamelMboxSummaryClass CamelMboxSummaryClass;
/* extra summary flags */
enum {
CAMEL_MESSAGE_FOLDER_NOXEV = 1<<17,
};
typedef struct _CamelMboxMessageContentInfo {
CamelMessageContentInfo info;
} CamelMboxMessageContentInfo;
typedef struct _CamelMboxMessageInfo {
CamelMessageInfo info;
off_t frompos;
} CamelMboxMessageInfo;
struct _CamelMboxSummary {
CamelFolderSummary parent;
struct _CamelMboxSummaryPrivate *priv;
char *folder_path; /* name of matching folder */
size_t folder_size; /* size of the mbox file, last sync */
ibex *index;
int index_force; /* do we force index during creation? */
};
struct _CamelMboxSummaryClass {
CamelFolderSummaryClass parent_class;
};
guint camel_mbox_summary_get_type (void);
CamelMboxSummary *camel_mbox_summary_new (const char *filename, const char *mbox_name, ibex *index);
/* load/check the summary */
int camel_mbox_summary_load(CamelMboxSummary *mbs, int forceindex);
/* incremental update */
int camel_mbox_summary_update(CamelMboxSummary *mbs, off_t offset, CamelFolderChangeInfo *changeinfo);
/* perform a folder sync or expunge, if needed */
int camel_mbox_summary_sync (CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex);
/* generate a From line from headers */
char *camel_mbox_summary_build_from(struct _header_raw *header);
#endif /* ! _CAMEL_MBOX_SUMMARY_H */

View File

@ -1,7 +0,0 @@
.deps
Makefile
Makefile.in
.libs
.deps
*.lo
*.la

View File

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
libcamelmhincludedir = $(includedir)/camel
providerdir = $(pkglibdir)/camel-providers/$(VERSION)
provider_LTLIBRARIES = libcamelmh.la
provider_DATA = libcamelmh.urls
INCLUDES = -I.. \
-I$(srcdir)/.. \
-I$(top_srcdir)/camel \
-I$(top_srcdir)/intl \
-I$(top_srcdir)/libibex \
-I$(top_srcdir)/e-util \
-I$(top_srcdir) \
-I$(includedir) \
$(GTK_INCLUDEDIR) \
-DG_LOG_DOMAIN=\"camel-mh-provider\"
libcamelmh_la_SOURCES = \
camel-mh-folder.c \
camel-mh-provider.c \
camel-mh-store.c \
camel-mh-summary.c
libcamelmhinclude_HEADERS = \
camel-mh-folder.h \
camel-mh-store.h \
camel-mh-summary.h
libcamelmh_la_LDFLAGS = -version-info 0:0:0
libcamelmh_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
#libcamelmh_la_LIBADD = $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
EXTRA_DIST = libcamelmh.urls

View File

@ -1,534 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/* camel-mh-folder.c : Abstract class for an email folder */
/*
* Authors: Michael Zucchi <notzed@helixcode.com>
*
* Copyright (C) 1999, 2000 Helix Code Inc.
*
* 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 <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include "camel-mh-folder.h"
#include "camel-mh-store.h"
#include "string-utils.h"
#include "camel-stream-fs.h"
#include "camel-mh-summary.h"
#include "camel-data-wrapper.h"
#include "camel-mime-message.h"
#include "camel-stream-filter.h"
#include "camel-mime-filter-from.h"
#include "camel-exception.h"
#define d(x)
static CamelFolderClass *parent_class = NULL;
/* Returns the class for a CamelMhFolder */
#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CMHS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
static void mh_sync(CamelFolder * folder, gboolean expunge, CamelException * ex);
static gint mh_get_message_count(CamelFolder * folder);
static gint mh_get_unread_message_count(CamelFolder * folder);
static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, CamelException * ex);
static GPtrArray *mh_get_uids(CamelFolder * folder);
static GPtrArray *mh_get_summary(CamelFolder * folder);
static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex);
static void mh_expunge(CamelFolder * folder, CamelException * ex);
static const CamelMessageInfo *mh_get_message_info(CamelFolder * folder, const char *uid);
static GPtrArray *mh_search_by_expression(CamelFolder * folder, const char *expression, CamelException * ex);
static void mh_search_free(CamelFolder *folder, GPtrArray *result);
static guint32 mh_get_message_flags(CamelFolder * folder, const char *uid);
static void mh_set_message_flags(CamelFolder * folder, const char *uid, guint32 flags, guint32 set);
static gboolean mh_get_message_user_flag(CamelFolder * folder, const char *uid, const char *name);
static void mh_set_message_user_flag(CamelFolder * folder, const char *uid, const char *name, gboolean value);
static const char *mh_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name);
static void mh_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value);
static void mh_finalize(CamelObject * object);
static void camel_mh_folder_class_init(CamelObjectClass * camel_mh_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mh_folder_class);
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_folder_get_type()));
/* virtual method definition */
/* virtual method overload */
camel_folder_class->sync = mh_sync;
camel_folder_class->get_message_count = mh_get_message_count;
camel_folder_class->get_unread_message_count = mh_get_unread_message_count;
camel_folder_class->append_message = mh_append_message;
camel_folder_class->get_uids = mh_get_uids;
camel_folder_class->free_uids = camel_folder_free_deep;
camel_folder_class->get_summary = mh_get_summary;
camel_folder_class->free_summary = camel_folder_free_nop;
camel_folder_class->expunge = mh_expunge;
camel_folder_class->get_message = mh_get_message;
camel_folder_class->search_by_expression = mh_search_by_expression;
camel_folder_class->search_free = mh_search_free;
camel_folder_class->get_message_info = mh_get_message_info;
camel_folder_class->get_message_flags = mh_get_message_flags;
camel_folder_class->set_message_flags = mh_set_message_flags;
camel_folder_class->get_message_user_flag = mh_get_message_user_flag;
camel_folder_class->set_message_user_flag = mh_set_message_user_flag;
camel_folder_class->get_message_user_tag = mh_get_message_user_tag;
camel_folder_class->set_message_user_tag = mh_set_message_user_tag;
}
static void mh_init(gpointer object, gpointer klass)
{
CamelFolder *folder = object;
CamelMhFolder *mh_folder = object;
folder->has_summary_capability = TRUE;
folder->has_search_capability = TRUE;
folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT |
CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER;
mh_folder->summary = NULL;
mh_folder->search = NULL;
mh_folder->changes = camel_folder_change_info_new();
}
static void mh_finalize(CamelObject * object)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(object);
if (mh_folder->index)
ibex_close(mh_folder->index);
g_free(mh_folder->folder_file_path);
g_free(mh_folder->summary_file_path);
g_free(mh_folder->folder_dir_path);
g_free(mh_folder->index_file_path);
camel_folder_change_info_free(mh_folder->changes);
}
CamelType camel_mh_folder_get_type(void)
{
static CamelType camel_mh_folder_type = CAMEL_INVALID_TYPE;
if (camel_mh_folder_type == CAMEL_INVALID_TYPE) {
camel_mh_folder_type = camel_type_register(CAMEL_FOLDER_TYPE, "CamelMhFolder",
sizeof(CamelMhFolder),
sizeof(CamelMhFolderClass),
(CamelObjectClassInitFunc) camel_mh_folder_class_init,
NULL,
(CamelObjectInitFunc) mh_init,
(CamelObjectFinalizeFunc) mh_finalize);
}
return camel_mh_folder_type;
}
CamelFolder *
camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex)
{
CamelFolder *folder;
CamelMhFolder *mh_folder;
const char *root_dir_path, *name;
int forceindex;
struct stat st;
folder = CAMEL_FOLDER (camel_object_new(CAMEL_MH_FOLDER_TYPE));
mh_folder = (CamelMhFolder *)folder;
name = strrchr(full_name, '/');
if (name)
name++;
else
name = full_name;
camel_folder_construct (folder, parent_store, full_name, name);
root_dir_path = camel_mh_store_get_toplevel_dir(CAMEL_MH_STORE(folder->parent_store));
mh_folder->folder_file_path = g_strdup_printf("%s/%s", root_dir_path, full_name);
mh_folder->summary_file_path = g_strdup_printf("%s/%s/ev-summary", root_dir_path, full_name);
mh_folder->folder_dir_path = g_strdup_printf("%s/%s", root_dir_path, full_name);
mh_folder->index_file_path = g_strdup_printf("%s/%s/ev-index.ibex", root_dir_path, full_name);
/* if we have no index file, force it */
forceindex = stat(mh_folder->index_file_path, &st) == -1;
/* check if we need to setup an index */
if (flags & CAMEL_STORE_FOLDER_BODY_INDEX) {
mh_folder->index = ibex_open(mh_folder->index_file_path, O_CREAT | O_RDWR, 0600);
if (mh_folder->index == NULL) {
/* yes, this isn't fatal at all */
g_warning("Could not open/create index file: %s: indexing not performed", strerror(errno));
forceindex = FALSE;
}
} else {
/* if we do have an index file, remove it */
if (forceindex == FALSE) {
unlink(mh_folder->index_file_path);
}
forceindex = FALSE;
}
/* no summary (disk or memory), and we're proverbially screwed */
mh_folder->summary = camel_mh_summary_new(mh_folder->summary_file_path,
mh_folder->folder_file_path,
mh_folder->index);
if (camel_mh_summary_load(mh_folder->summary, forceindex) == -1) {
camel_exception_set(ex, CAMEL_EXCEPTION_FOLDER_INVALID, /* FIXME: right error code */
_("Could not load or create summary"));
camel_object_unref (CAMEL_OBJECT (folder));
return NULL;
}
return folder;
}
static void mh_sync(CamelFolder * folder, gboolean expunge, CamelException * ex)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
if (expunge)
mh_expunge(folder, ex);
else {
camel_mh_summary_sync(mh_folder->summary, FALSE, mh_folder->changes, ex);
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mh_folder->changes);
camel_folder_change_info_clear(mh_folder->changes);
}
/* save index */
if (mh_folder->index)
ibex_save(mh_folder->index);
if (mh_folder->summary)
camel_folder_summary_save(CAMEL_FOLDER_SUMMARY(mh_folder->summary));
}
static void mh_expunge(CamelFolder * folder, CamelException * ex)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
camel_mh_summary_sync(mh_folder->summary, TRUE, mh_folder->changes, ex);
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mh_folder->changes);
camel_folder_change_info_clear(mh_folder->changes);
}
static gint mh_get_message_count(CamelFolder * folder)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
g_return_val_if_fail(mh_folder->summary != NULL, -1);
return camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(mh_folder->summary));
}
static gint mh_get_unread_message_count(CamelFolder * folder)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
CamelMessageInfo *info;
GPtrArray *infolist;
gint i, count = 0;
g_return_val_if_fail(mh_folder->summary != NULL, -1);
infolist = mh_get_summary(folder);
for (i = 0; i < infolist->len; i++) {
info = (CamelMessageInfo *) g_ptr_array_index(infolist, i);
if (!(info->flags & CAMEL_MESSAGE_SEEN))
count++;
}
return count;
}
static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, CamelException * ex)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
CamelStream *output_stream = NULL;
char *name = NULL;
char *uid = NULL;
CamelMessageInfo *newinfo;
/* FIXME: probably needs additional locking */
/* keep trying uid's until we find one thats ok */
do {
g_free(uid);
g_free(name);
uid = camel_folder_summary_next_uid_string((CamelFolderSummary *)mh_folder->summary);
name = g_strdup_printf("%s/%s", mh_folder->folder_file_path, uid);
output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT|O_EXCL, 0600);
} while (output_stream == NULL && errno == EEXIST);
if (output_stream == NULL)
goto fail;
/* write the message */
if (camel_data_wrapper_write_to_stream(CAMEL_DATA_WRAPPER(message), output_stream) == -1)
goto fail;
if (camel_stream_close(output_stream) == -1)
goto fail;
/* index/summarise the message. Yes this re-reads it, its just simpler */
camel_mh_summary_add(mh_folder->summary, uid, TRUE);
if (info
&& (newinfo = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mh_folder->summary), uid))) {
CamelFlag *flag = info->user_flags;
CamelTag *tag = info->user_tags;
newinfo->flags = info->flags;
while (flag) {
camel_flag_set(&newinfo->user_flags, flag->name, TRUE);
flag = flag->next;
}
while (tag) {
camel_tag_set(&newinfo->user_tags, tag->name, tag->value);
tag = tag->next;
}
}
camel_folder_change_info_add_uid(mh_folder->changes, uid);
camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", mh_folder->changes);
camel_folder_change_info_clear(mh_folder->changes);
g_free(name);
g_free(uid);
return;
fail:
if (camel_exception_is_set(ex)) {
camel_exception_setv(ex, camel_exception_get_id(ex),
_("Cannot append message to mh folder: %s"), camel_exception_get_description(ex));
} else {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot append message to mh folder: %s"), g_strerror(errno));
}
if (output_stream)
camel_object_unref(CAMEL_OBJECT(output_stream));
if (name) {
unlink(name);
g_free(name);
}
g_free(uid);
}
static GPtrArray *mh_get_uids(CamelFolder * folder)
{
GPtrArray *array;
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
int i, count;
count = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(mh_folder->summary));
array = g_ptr_array_new();
g_ptr_array_set_size(array, count);
for (i = 0; i < count; i++) {
CamelMessageInfo *info =
camel_folder_summary_index(CAMEL_FOLDER_SUMMARY(mh_folder->summary), i);
array->pdata[i] = g_strdup(info->uid);
}
return array;
}
static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
CamelStream *message_stream = NULL;
CamelMimeMessage *message = NULL;
CamelMessageInfo *info;
char *name;
name = g_strdup_printf("%s/%s", mh_folder->folder_file_path, uid);
/* get the message summary info */
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mh_folder->summary), uid);
if (info == NULL) {
errno = ENOENT;
goto fail;
}
message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0);
/* where we read from */
if (message_stream == NULL)
goto fail;
message = camel_mime_message_new();
if (camel_data_wrapper_construct_from_stream(CAMEL_DATA_WRAPPER(message), message_stream) == -1) {
g_warning("Construction failed");
errno = EINVAL;
goto fail;
}
camel_object_unref(CAMEL_OBJECT(message_stream));
g_free(name);
return message;
fail:
camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"),
name, g_strerror(errno));
if (message_stream)
camel_object_unref(CAMEL_OBJECT(message_stream));
if (message)
camel_object_unref(CAMEL_OBJECT(message));
g_free(name);
return NULL;
}
GPtrArray *mh_get_summary(CamelFolder * folder)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
return CAMEL_FOLDER_SUMMARY(mh_folder->summary)->messages;
}
/* get a single message info, by uid */
static const CamelMessageInfo *mh_get_message_info(CamelFolder * folder, const char *uid)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
return camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mh_folder->summary), uid);
}
static GPtrArray *mh_search_by_expression(CamelFolder * folder, const char *expression, CamelException * ex)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
if (mh_folder->search == NULL) {
mh_folder->search = camel_folder_search_new();
}
camel_folder_search_set_folder(mh_folder->search, folder);
if (mh_folder->summary) {
/* FIXME: dont access summary array directly? */
camel_folder_search_set_summary(mh_folder->search,
CAMEL_FOLDER_SUMMARY(mh_folder->summary)->messages);
}
camel_folder_search_set_body_index(mh_folder->search, mh_folder->index);
return camel_folder_search_execute_expression(mh_folder->search, expression, ex);
}
static void mh_search_free(CamelFolder *folder, GPtrArray *result)
{
CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder);
camel_folder_search_free_result(mh_folder->search, result);
}
static guint32 mh_get_message_flags(CamelFolder * folder, const char *uid)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, 0);
return info->flags;
}
static void mh_set_message_flags(CamelFolder * folder, const char *uid, guint32 flags, guint32 set)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
info->flags = (info->flags & ~flags) | (set & flags) | CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event (CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}
static gboolean mh_get_message_user_flag(CamelFolder * folder, const char *uid, const char *name)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, FALSE);
return camel_flag_get(&info->user_flags, name);
}
static void mh_set_message_user_flag(CamelFolder * folder, const char *uid, const char *name, gboolean value)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
camel_flag_set(&info->user_flags, name, value);
info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event (CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}
static const char *mh_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_val_if_fail(info != NULL, FALSE);
return camel_tag_get(&info->user_tags, name);
}
static void mh_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value)
{
CamelMessageInfo *info;
CamelMhFolder *mf = CAMEL_MH_FOLDER(folder);
info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid);
g_return_if_fail(info != NULL);
camel_tag_set(&info->user_tags, name, value);
info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary));
camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid);
}

View File

@ -1,74 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mh-folder.h : MH folder. */
/*
*
* Authors:
* Michael Zucchi <notzed@helixcode.com>
*
* Copyright (C) 1999 Helix Code Inc.
*
* 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_MH_FOLDER_H
#define CAMEL_MH_FOLDER_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus } */
#include <camel/camel-folder.h>
#include <camel/camel-folder-search.h>
#include <libibex/ibex.h>
#include "camel-mh-summary.h"
#define CAMEL_MH_FOLDER_TYPE (camel_mh_folder_get_type ())
#define CAMEL_MH_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_FOLDER_TYPE, CamelMhFolder))
#define CAMEL_MH_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_FOLDER_TYPE, CamelMhFolderClass))
#define CAMEL_IS_MH_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_FOLDER_TYPE))
typedef struct {
CamelFolder parent_object;
gchar *folder_file_path; /* contains the messages */
gchar *summary_file_path; /* contains the messages summary */
gchar *folder_dir_path; /* contains the subfolders */
gchar *index_file_path; /* index of body contents */
ibex *index; /* index for this folder */
CamelMhSummary *summary;
CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */
CamelFolderChangeInfo *changes; /* mass changes to the folder */
} CamelMhFolder;
typedef struct {
CamelFolderClass parent_class;
/* Virtual methods */
} CamelMhFolderClass;
/* public methods */
CamelFolder *camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex);
/* Standard Camel function */
CamelType camel_mh_folder_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_MH_FOLDER_H */

View File

@ -1,56 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-provider.c: mbox provider registration code */
/*
* Authors :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright (C) 2000 HelixCode (www.helixcode.com).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "config.h"
#include "camel-mh-store.h"
#include "camel-provider.h"
#include "camel-session.h"
#include "camel-url.h"
static CamelProvider mh_provider = {
"mh",
N_("UNIX MH-format mail directories"),
N_("For storing local mail in MH-like mail directories"),
"mail",
CAMEL_PROVIDER_IS_STORAGE,
CAMEL_URL_NEED_PATH,
{0, 0},
NULL
};
void camel_provider_module_init(CamelSession * session)
{
mh_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mh_store_get_type();
mh_provider.service_cache = g_hash_table_new(camel_url_hash, camel_url_equal);
camel_session_register_provider(session, &mh_provider);
}

View File

@ -1,228 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-store.c : class for an mbox store */
/*
*
* Copyright (C) 2000 Helix Code, Inc.
*
* Authors: Michael Zucchi <notzed@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "camel-mh-store.h"
#include "camel-mh-folder.h"
#include "camel-exception.h"
#include "camel-url.h"
/* Returns the class for a CamelMhStore */
#define CMHS_CLASS(so) CAMEL_MH_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
static char *get_name(CamelService * service, gboolean brief);
static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex);
static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex);
static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
static char *get_folder_name(CamelStore * store, const char *folder_name, CamelException * ex);
static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top,
gboolean fast, gboolean recursive,
gboolean subscribed_only,
CamelException *ex);
static void camel_mh_store_class_init(CamelObjectClass * camel_mh_store_class)
{
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mh_store_class);
CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_mh_store_class);
/* virtual method overload */
camel_service_class->get_name = get_name;
camel_store_class->get_folder = get_folder;
camel_store_class->delete_folder = delete_folder;
camel_store_class->rename_folder = rename_folder;
camel_store_class->get_folder_name = get_folder_name;
camel_store_class->get_folder_info = get_folder_info;
camel_store_class->free_folder_info = camel_store_free_folder_info_full;
}
static void camel_mh_store_init(CamelObject * object)
{
CamelStore *store = CAMEL_STORE(object);
/* mh names are filenames, so they are case-sensitive. */
store->folders = g_hash_table_new(g_str_hash, g_str_equal);
}
CamelType camel_mh_store_get_type(void)
{
static CamelType camel_mh_store_type = CAMEL_INVALID_TYPE;
if (camel_mh_store_type == CAMEL_INVALID_TYPE) {
camel_mh_store_type = camel_type_register(CAMEL_STORE_TYPE, "CamelMhStore",
sizeof(CamelMhStore),
sizeof(CamelMhStoreClass),
(CamelObjectClassInitFunc) camel_mh_store_class_init,
NULL,
(CamelObjectInitFunc) camel_mh_store_init,
NULL);
}
return camel_mh_store_type;
}
const gchar *camel_mh_store_get_toplevel_dir(CamelMhStore * store)
{
CamelURL *url = CAMEL_SERVICE(store)->url;
g_assert(url != NULL);
return url->path;
}
static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex)
{
char *name;
struct stat st;
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
if (stat(name, &st) == -1) {
if (errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not open folder `%s':\n%s"),
folder_name, g_strerror(errno));
g_free (name);
return NULL;
}
if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Folder `%s' does not exist."), folder_name);
g_free (name);
return NULL;
}
printf("creating ...\n");
if (mkdir(name, 0700) != 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not create folder `%s':\n%s"),
folder_name, g_strerror(errno));
g_free (name);
return NULL;
}
printf("created ok?\n");
} else if (!S_ISDIR(st.st_mode)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("`%s' is not a directory."), name);
g_free (name);
return NULL;
}
g_free(name);
return camel_mh_folder_new(store, folder_name, flags, ex);
}
static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex)
{
char *name;
struct stat st;
char *str;
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
if (stat(name, &st) == -1) {
if (errno != ENOENT)
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s': %s"),
folder_name, strerror(errno));
} else {
/* this will 'fail' if there are still messages in the directory -
but only the metadata is lost */
str = g_strdup_printf("%s/ev-summary", name);
unlink(str);
g_free(str);
str = g_strdup_printf("%s/ev-index.ibex", name);
unlink(str);
g_free(str);
if (rmdir(name) == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s': %s"),
folder_name, strerror(errno));
}
}
g_free(name);
}
static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
{
char *old, *new;
struct stat st;
old = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, old_name);
new = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, new_name);
if (stat(new, &st) == -1 && errno == ENOENT) {
if (stat(old, &st) == 0 && S_ISDIR(st.st_mode)) {
if (rename(old, new) != 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename folder `%s': %s"), old_name, strerror(errno));
}
} else {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename folder `%s': %s"), old_name, strerror(errno));
}
} else {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename folder `%s': %s exists"), old_name, new_name);
}
}
static char *get_folder_name(CamelStore * store, const char *folder_name, CamelException * ex)
{
/* For now, we don't allow hieararchy. FIXME. */
if (strchr(folder_name + 1, '/')) {
camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, _("MH folders may not be nested."));
return NULL;
}
return *folder_name == '/' ? g_strdup(folder_name) : g_strdup_printf("/%s", folder_name);
}
static char *get_name(CamelService * service, gboolean brief)
{
if (brief)
return g_strdup(service->url->path);
else
return g_strdup_printf(_("Local mail directory %s"), service->url->path);
}
static CamelFolderInfo *
get_folder_info (CamelStore *store, const char *top,
gboolean fast, gboolean recursive,
gboolean subscribed_only,
CamelException *ex)
{
/* FIXME: This is broken, but it corresponds to what was
* there before.
*/
return NULL;
}

View File

@ -1,59 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mh-store.h : class for an mh store */
/*
*
* Copyright (C) 2000 Helix Code, Inc.
*
* Authors: Michael Zucchi <notzed@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef CAMEL_MH_STORE_H
#define CAMEL_MH_STORE_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus } */
#include "camel-store.h"
#define CAMEL_MH_STORE_TYPE (camel_mh_store_get_type ())
#define CAMEL_MH_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_STORE_TYPE, CamelMhStore))
#define CAMEL_MH_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_STORE_TYPE, CamelMhStoreClass))
#define CAMEL_IS_MH_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_STORE_TYPE))
typedef struct {
CamelStore parent_object;
} CamelMhStore;
typedef struct {
CamelStoreClass parent_class;
} CamelMhStoreClass;
/* public methods */
/* Standard Camel function */
CamelType camel_mh_store_get_type(void);
const gchar *camel_mh_store_get_toplevel_dir(CamelMhStore * store);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_MH_STORE_H */

View File

@ -1,279 +0,0 @@
/*
* Copyright (C) 2000 Helix Code Inc.
*
* Authors: Not Zed <notzed@lostzed.mmc.com.au>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "camel-mh-summary.h"
#include <camel/camel-mime-message.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#define d(x)
#define CAMEL_MH_SUMMARY_VERSION (0x2000)
static CamelMessageInfo *message_info_new(CamelFolderSummary *, struct _header_raw *);
static void camel_mh_summary_class_init (CamelMhSummaryClass *class);
static void camel_mh_summary_init (CamelMhSummary *gspaper);
static void camel_mh_summary_finalise (CamelObject *obj);
#define _PRIVATE(x) (((CamelMhSummary *)(x))->priv)
struct _CamelMhSummaryPrivate {
char *current_uid;
};
static CamelFolderSummaryClass *parent_class;
CamelType
camel_mh_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_folder_summary_get_type (), "CamelMhSummary",
sizeof(CamelMhSummary),
sizeof(CamelMhSummaryClass),
(CamelObjectClassInitFunc)camel_mh_summary_class_init,
NULL,
(CamelObjectInitFunc)camel_mh_summary_init,
(CamelObjectFinalizeFunc)camel_mh_summary_finalise);
}
return type;
}
static void
camel_mh_summary_class_init (CamelMhSummaryClass *class)
{
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class;
parent_class = CAMEL_FOLDER_SUMMARY_CLASS (camel_type_get_global_classfuncs(camel_folder_summary_get_type ()));
/* override methods */
sklass->message_info_new = message_info_new;
}
static void
camel_mh_summary_init (CamelMhSummary *o)
{
struct _CamelFolderSummary *s = (CamelFolderSummary *) o;
o->priv = g_malloc0(sizeof(*o->priv));
/* set unique file version */
s->version += CAMEL_MH_SUMMARY_VERSION;
}
static void
camel_mh_summary_finalise(CamelObject *obj)
{
CamelMhSummary *o = (CamelMhSummary *)obj;
g_free(o->mh_path);
g_free(o->priv);
}
/**
* camel_mh_summary_new:
*
* Create a new CamelMhSummary object.
*
* Return value: A new #CamelMhSummary object.
**/
CamelMhSummary *camel_mh_summary_new (const char *filename, const char *mhdir, ibex *index)
{
CamelMhSummary *o = (CamelMhSummary *)camel_object_new(camel_mh_summary_get_type ());
camel_folder_summary_set_build_content((CamelFolderSummary *)o, TRUE);
camel_folder_summary_set_filename((CamelFolderSummary *)o, filename);
o->mh_path = g_strdup(mhdir);
o->index = index;
return o;
}
static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header_raw *h)
{
CamelMessageInfo *mi;
CamelMhSummary *mhs = (CamelMhSummary *)s;
mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new(s, h);
if (mi) {
/* it only ever indexes 1 message at a time */
mi->uid = g_strdup(mhs->priv->current_uid);
}
return mi;
}
int camel_mh_summary_load(CamelMhSummary * mhs, int forceindex)
{
CamelFolderSummary *s = CAMEL_FOLDER_SUMMARY(mhs);
d(printf("loading summary ...\n"));
if (forceindex || camel_folder_summary_load(s) == -1) {
camel_folder_summary_clear(s);
}
return camel_mh_summary_check(mhs, forceindex);
}
int camel_mh_summary_add(CamelMhSummary * mhs, const char *name, int forceindex)
{
char *filename = g_strdup_printf("%s/%s", mhs->mh_path, name);
int fd;
CamelMimeParser *mp;
d(printf("summarising: %s\n", name));
fd = open(filename, O_RDONLY);
if (fd == -1) {
g_warning("Cannot summarise/index: %s: %s", filename, strerror(errno));
g_free(filename);
return -1;
}
mp = camel_mime_parser_new();
camel_mime_parser_scan_from(mp, FALSE);
camel_mime_parser_init_with_fd(mp, fd);
if (mhs->index && (forceindex || !ibex_contains_name(mhs->index, (char *)name))) {
d(printf("forcing indexing of message content\n"));
camel_folder_summary_set_index((CamelFolderSummary *)mhs, mhs->index);
} else {
camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL);
}
mhs->priv->current_uid = (char *)name;
camel_folder_summary_add_from_parser((CamelFolderSummary *)mhs, mp);
camel_object_unref((CamelObject *)mp);
mhs->priv->current_uid = NULL;
camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL);
g_free(filename);
return 0;
}
static void
remove_summary(char *key, CamelMessageInfo *info, CamelMhSummary *mhs)
{
d(printf("removing message %s from summary\n", key));
if (mhs->index)
ibex_unindex(mhs->index, info->uid);
camel_folder_summary_remove((CamelFolderSummary *)mhs, info);
}
int camel_mh_summary_check(CamelMhSummary * mhs, int forceindex)
{
DIR *dir;
struct dirent *d;
char *p, c;
CamelMessageInfo *info;
GHashTable *left;
int i, count;
d(printf("checking summary ...\n"));
/* scan the directory, check for mail files not in the index, or index entries that
no longer exist */
dir = opendir(mhs->mh_path);
if (dir == NULL)
return -1;
/* keeps track of all uid's that have not been processed */
left = g_hash_table_new(g_str_hash, g_str_equal);
count = camel_folder_summary_count((CamelFolderSummary *)mhs);
for (i=0;i<count;i++) {
info = camel_folder_summary_index((CamelFolderSummary *)mhs, i);
if (info) {
g_hash_table_insert(left, info->uid, info);
}
}
while ( (d = readdir(dir)) ) {
/* FIXME: also run stat to check for regular file */
p = d->d_name;
while ( (c = *p++) ) {
if (!isdigit(c))
break;
}
if (c==0) {
info = camel_folder_summary_uid((CamelFolderSummary *)mhs, d->d_name);
if (info == NULL || (mhs->index && (!ibex_contains_name(mhs->index, d->d_name)))) {
/* need to add this file to the summary */
if (info != NULL) {
g_hash_table_remove(left, info->uid);
camel_folder_summary_remove((CamelFolderSummary *)mhs, info);
}
camel_mh_summary_add(mhs, d->d_name, forceindex);
} else {
g_hash_table_remove(left, info->uid);
}
}
}
closedir(dir);
g_hash_table_foreach(left, (GHFunc)remove_summary, mhs);
g_hash_table_destroy(left);
/* force a save of the index, just to make sure */
/* note this could be expensive so possibly shouldn't be here
as such */
if (mhs->index) {
ibex_save(mhs->index);
}
return 0;
}
/* sync the summary with the ondisk files.
It doesnt store the state in the file, the summary only, == MUCH faster */
int camel_mh_summary_sync(CamelMhSummary * mhs, int expunge, CamelFolderChangeInfo *changes, CamelException *ex)
{
int count, i;
CamelMessageInfo *info;
char *name;
printf("summary_sync(expunge=%s)\n", expunge?"true":"false");
if (mhs->index) {
ibex_save(mhs->index);
}
if (!expunge)
return 0;
count = camel_folder_summary_count((CamelFolderSummary *)mhs);
for (i=count-1;i>=0;i--) {
info = camel_folder_summary_index((CamelFolderSummary *)mhs, i);
if (info && info->flags & CAMEL_MESSAGE_DELETED) {
name = g_strdup_printf("%s/%s", mhs->mh_path, info->uid);
d(printf("deleting %s\n", name));
if (unlink(name) == 0 || errno==ENOENT) {
camel_folder_change_info_remove_uid(changes, info->uid);
camel_folder_summary_remove((CamelFolderSummary *)mhs, info);
}
}
}
return 0;
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2000 Helix Code Inc.
*
* Authors: Not Zed <notzed@lostzed.mmc.com.au>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _CAMEL_MH_SUMMARY_H
#define _CAMEL_MH_SUMMARY_H
#include <camel/camel-folder-summary.h>
#include <camel/camel-folder.h>
#include <camel/camel-exception.h>
#include <libibex/ibex.h>
#define CAMEL_MH_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mh_summary_get_type (), CamelMhSummary)
#define CAMEL_MH_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mh_summary_get_type (), CamelMhSummaryClass)
#define CAMEL_IS_MH_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mh_summary_get_type ())
typedef struct _CamelMhSummary CamelMhSummary;
typedef struct _CamelMhSummaryClass CamelMhSummaryClass;
struct _CamelMhSummary {
CamelFolderSummary parent;
struct _CamelMhSummaryPrivate *priv;
char *mh_path;
ibex *index;
};
struct _CamelMhSummaryClass {
CamelFolderSummaryClass parent_class;
/* virtual methods */
/* signals */
};
CamelType camel_mh_summary_get_type (void);
CamelMhSummary *camel_mh_summary_new (const char *filename, const char *mhdir, ibex *index);
/* methods */
int camel_mh_summary_load(CamelMhSummary * mhs, int forceindex);
int camel_mh_summary_check(CamelMhSummary * mhs, int forceindex);
int camel_mh_summary_add(CamelMhSummary * mhs, const char *name, int forceindex);
int camel_mh_summary_sync(CamelMhSummary * mhs, int expunge, CamelFolderChangeInfo *changes, CamelException *ex);
#endif /* ! _CAMEL_MH_SUMMARY_H */