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:
committed by
Chris Lahey
parent
02ee28bf77
commit
dbad1c19f8
@ -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.
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
@ -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 =
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/** *** **/
|
||||
|
||||
@ -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 */
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
.libs
|
||||
.deps
|
||||
*.lo
|
||||
*.la
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
.libs
|
||||
.deps
|
||||
*.lo
|
||||
*.la
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user