diff options
Diffstat (limited to 'camel/providers/local')
35 files changed, 0 insertions, 8672 deletions
diff --git a/camel/providers/local/.cvsignore b/camel/providers/local/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/local/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/local/Makefile.am b/camel/providers/local/Makefile.am deleted file mode 100644 index f0ad0c7f6c..0000000000 --- a/camel/providers/local/Makefile.am +++ /dev/null @@ -1,63 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamellocalincludedir = $(includedir)/camel - -camel_provider_LTLIBRARIES = libcamellocal.la -camel_provider_DATA = libcamellocal.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) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-local-provider\" - -libcamellocal_la_SOURCES = \ - camel-local-folder.c \ - camel-local-store.c \ - camel-local-summary.c \ - camel-local-provider.c \ - camel-mh-folder.c \ - camel-mh-store.c \ - camel-mh-summary.c \ - camel-mbox-folder.c \ - camel-mbox-store.c \ - camel-mbox-summary.c \ - camel-maildir-folder.c \ - camel-maildir-store.c \ - camel-maildir-summary.c \ - camel-spool-folder.c \ - camel-spool-store.c \ - camel-spool-summary.c - -libcamellocalinclude_HEADERS = \ - camel-local-folder.h \ - camel-local-store.h \ - camel-local-summary.h \ - camel-mh-folder.h \ - camel-mh-store.h \ - camel-mh-summary.h \ - camel-mbox-folder.h \ - camel-mbox-store.h \ - camel-mbox-summary.h \ - camel-maildir-folder.h \ - camel-maildir-store.h \ - camel-maildir-summary.h \ - camel-spool-folder.h \ - camel-spool-store.h \ - camel-spool-summary.h - -noinst_HEADERS = \ - camel-local-private.h - -libcamellocal_la_LDFLAGS = -version-info 0:0:0 - -libcamellocal_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(top_builddir)/libibex/libibex.la - -EXTRA_DIST = libcamellocal.urls diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c deleted file mode 100644 index d84041025c..0000000000 --- a/camel/providers/local/camel-local-folder.c +++ /dev/null @@ -1,435 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2000 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <limits.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#ifndef _POSIX_PATH_MAX -#include <posix1_lim.h> -#endif - -#include "camel-local-folder.h" -#include "camel-local-store.h" -#include "string-utils.h" -#include "camel-stream-fs.h" -#include "camel-local-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" - -#include "camel-local-private.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#ifndef PATH_MAX -#define PATH_MAX _POSIX_PATH_MAX -#endif - -static CamelFolderClass *parent_class = NULL; - -/* Returns the class for a CamelLocalFolder */ -#define CLOCALF_CLASS(so) CAMEL_LOCAL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CLOCALS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void local_unlock(CamelLocalFolder *lf); - -static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); -static void local_expunge(CamelFolder *folder, CamelException *ex); - -static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void local_search_free(CamelFolder *folder, GPtrArray * result); - -static void local_rename(CamelFolder *folder, const char *newname); - -static void local_finalize(CamelObject * object); - -static void -camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_local_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 = local_sync; - camel_folder_class->expunge = local_expunge; - - camel_folder_class->search_by_expression = local_search_by_expression; - camel_folder_class->search_by_uids = local_search_by_uids; - camel_folder_class->search_free = local_search_free; - - camel_folder_class->rename = local_rename; - - camel_local_folder_class->lock = local_lock; - camel_local_folder_class->unlock = local_unlock; -} - -static void -local_init(gpointer object, gpointer klass) -{ - CamelFolder *folder = object; - CamelLocalFolder *local_folder = object; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER; - - folder->summary = NULL; - local_folder->search = NULL; - - local_folder->priv = g_malloc0(sizeof(*local_folder->priv)); -#ifdef ENABLE_THREADS - local_folder->priv->search_lock = g_mutex_new(); -#endif -} - -static void -local_finalize(CamelObject * object) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(object); - CamelFolder *folder = (CamelFolder *)object; - - if (folder->summary) { - camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, local_folder->changes, NULL); - camel_object_unref((CamelObject *)folder->summary); - folder->summary = NULL; - } - - if (local_folder->search) { - camel_object_unref((CamelObject *)local_folder->search); - } - - /* must free index after summary, since it isn't refcounted */ - if (local_folder->index) - ibex_close(local_folder->index); - - while (local_folder->locked> 0) - camel_local_folder_unlock(local_folder); - - g_free(local_folder->base_path); - g_free(local_folder->folder_path); - g_free(local_folder->summary_path); - g_free(local_folder->index_path); - - camel_folder_change_info_free(local_folder->changes); - -#ifdef ENABLE_THREADS - g_mutex_free(local_folder->priv->search_lock); -#endif - g_free(local_folder->priv); -} - -CamelType camel_local_folder_get_type(void) -{ - static CamelType camel_local_folder_type = CAMEL_INVALID_TYPE; - - if (camel_local_folder_type == CAMEL_INVALID_TYPE) { - camel_local_folder_type = camel_type_register(CAMEL_FOLDER_TYPE, "CamelLocalFolder", - sizeof(CamelLocalFolder), - sizeof(CamelLocalFolderClass), - (CamelObjectClassInitFunc) camel_local_folder_class_init, - NULL, - (CamelObjectInitFunc) local_init, - (CamelObjectFinalizeFunc) local_finalize); - } - - return camel_local_folder_type; -} - -CamelLocalFolder * -camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelFolder *folder; - const char *root_dir_path, *name; - char folder_path[PATH_MAX]; - struct stat st; - int forceindex; - - folder = (CamelFolder *)lf; - - name = strrchr(full_name, '/'); - if (name) - name++; - else - name = full_name; - - camel_folder_construct(folder, parent_store, full_name, name); - - root_dir_path = camel_local_store_get_toplevel_dir(CAMEL_LOCAL_STORE(folder->parent_store)); - - lf->base_path = g_strdup(root_dir_path); - lf->folder_path = g_strdup_printf("%s/%s", root_dir_path, full_name); - lf->summary_path = g_strdup_printf("%s/%s.ev-summary", root_dir_path, full_name); - lf->index_path = g_strdup_printf("%s/%s.ibex", root_dir_path, full_name); - - /* follow any symlinks to the mailbox */ - if (lstat (lf->folder_path, &st) != -1 && S_ISLNK (st.st_mode) && - realpath (lf->folder_path, folder_path) != NULL) { - g_free (lf->folder_path); - lf->folder_path = g_strdup (folder_path); - } - - lf->changes = camel_folder_change_info_new(); - - /* if we have no index file, force it */ - forceindex = stat(lf->index_path, &st) == -1; - if (flags & CAMEL_STORE_FOLDER_BODY_INDEX) { - lf->index = ibex_open(lf->index_path, O_CREAT | O_RDWR, 0600); - if (lf->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; - /* record that we dont have an index afterall */ - flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - } - } else { - /* if we do have an index file, remove it */ - if (forceindex == FALSE) { - unlink(lf->index_path); - } - forceindex = FALSE; - } - - lf->flags = flags; - - folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf->summary_path, lf->folder_path, lf->index); - if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, ex) == -1) { - camel_exception_clear(ex); - } - - if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (full_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf("%s:%s#%s", ((CamelService *)parent_store)->url->protocol, ((CamelService *)parent_store)->url->path, full_name); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_folder_info_build_path(fi, '/'); - - camel_object_trigger_event(CAMEL_OBJECT (parent_store), "folder_created", fi); - camel_folder_info_free(fi); - - return lf; -} - -/* lock the folder, may be called repeatedly (with matching unlock calls), - with type the same or less than the first call */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - if (lf->locked > 0) { - /* lets be anal here - its important the code knows what its doing */ - g_assert(lf->locktype == type || lf->locktype == CAMEL_LOCK_WRITE); - } else { - if (CLOCALF_CLASS(lf)->lock(lf, type, ex) == -1) - return -1; - lf->locktype = type; - } - - lf->locked++; - - return 0; -} - -/* unlock folder */ -int camel_local_folder_unlock(CamelLocalFolder *lf) -{ - g_assert(lf->locked>0); - lf->locked--; - if (lf->locked == 0) - CLOCALF_CLASS(lf)->unlock(lf); - - return 0; -} - -static int -local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - return 0; -} - -static void -local_unlock(CamelLocalFolder *lf) -{ - /* nothing */ -} - -static void -local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelLocalFolder *lf = CAMEL_LOCAL_FOLDER(folder); - - d(printf("local sync, expunge=%s\n", expunge?"true":"false")); - - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - /* if sync fails, we'll pass it up on exit through ex */ - camel_local_summary_sync((CamelLocalSummary *)folder->summary, expunge, lf->changes, ex); - camel_local_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -local_expunge(CamelFolder *folder, CamelException *ex) -{ - d(printf("expunge\n")); - - /* Just do a sync with expunge, serves the same purpose */ - /* call the callback directly, to avoid locking problems */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex); -} - -static void -local_rename(CamelFolder *folder, const char *newname) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - d(printf("renaming local folder paths to '%s'\n", newname)); - - /* Sync? */ - - g_free(lf->folder_path); - g_free(lf->summary_path); - g_free(lf->index_path); - lf->folder_path = g_strdup_printf("%s/%s", lf->base_path, newname); - lf->summary_path = g_strdup_printf("%s/%s.ev-summary", lf->base_path, newname); - lf->index_path = g_strdup_printf("%s/%s.ibex", lf->base_path, newname); - - /* FIXME: Poke some internals, sigh */ - camel_folder_summary_set_filename(folder->summary, lf->summary_path); - g_free(((CamelLocalSummary *)folder->summary)->folder_path); - ((CamelLocalSummary *)folder->summary)->folder_path = g_strdup(lf->folder_path); - - parent_class->rename(folder, newname); -} - -static GPtrArray * -local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *summary, *matches; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - summary = camel_folder_get_summary(folder); - camel_folder_search_set_summary(local_folder->search, summary); - - matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - camel_folder_free_summary(folder, summary); - - return matches; -} - -static GPtrArray * -local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *summary, *matches; - int i; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - summary = g_ptr_array_new(); - for (i=0;i<uids->len;i++) { - CamelMessageInfo *info; - - info = camel_folder_get_message_info(folder, uids->pdata[i]); - if (info) - g_ptr_array_add(summary, info); - } - - if (summary->len == 0) - return summary; - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - camel_folder_search_set_summary(local_folder->search, summary); - - matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - for (i=0;i<summary->len;i++) - camel_folder_free_message_info(folder, summary->pdata[i]); - g_ptr_array_free(summary, TRUE); - - return matches; -} - -static void -local_search_free(CamelFolder *folder, GPtrArray * result) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - - /* we need to lock this free because of the way search_free_result works */ - /* FIXME: put the lock inside search_free_result */ - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result(local_folder->search, result); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); -} diff --git a/camel/providers/local/camel-local-folder.h b/camel/providers/local/camel-local-folder.h deleted file mode 100644 index 3eb4b02c32..0000000000 --- a/camel/providers/local/camel-local-folder.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian (www.ximian.com/). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_LOCAL_FOLDER_H -#define CAMEL_LOCAL_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-local-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_LOCAL_FOLDER_TYPE (camel_local_folder_get_type ()) -#define CAMEL_LOCAL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolder)) -#define CAMEL_LOCAL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolderClass)) -#define CAMEL_IS_LOCAL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_FOLDER_TYPE)) - -typedef struct { - CamelFolder parent_object; - struct _CamelLocalFolderPrivate *priv; - - guint32 flags; /* open mode flags */ - - int locked; /* lock counter */ - CamelLockType locktype; /* what type of lock we have */ - - char *base_path; /* base path of the local folder */ - char *folder_path; /* the path to the folder itself */ - char *summary_path; /* where the summary lives */ - char *index_path; /* where the index file lives */ - - ibex *index; /* index for this folder */ - CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */ - CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */ -} CamelLocalFolder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - - /* summary factory, only used at init */ - CamelLocalSummary *(*create_summary)(const char *path, const char *folder, ibex *index); - - /* Lock the folder for my operations */ - int (*lock)(CamelLocalFolder *, CamelLockType type, CamelException *ex); - - /* Unlock the folder for my operations */ - void (*unlock)(CamelLocalFolder *); -} CamelLocalFolderClass; - - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelLocalFolder *camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, - const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_local_folder_get_type(void); - -/* Lock the folder for internal use. May be called repeatedly */ -/* UNIMPLEMENTED */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -int camel_local_folder_unlock(CamelLocalFolder *lf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_FOLDER_H */ diff --git a/camel/providers/local/camel-local-private.h b/camel/providers/local/camel-local-private.h deleted file mode 100644 index 4dfe9f635c..0000000000 --- a/camel/providers/local/camel-local-private.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-local-private.h: Private info for local provider. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_PRIVATE_H -#define CAMEL_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#include "config.h" - -#ifdef ENABLE_THREADS -#include <pthread.h> -#endif - -struct _CamelLocalFolderPrivate { -#ifdef ENABLE_THREADS - GMutex *search_lock; /* for locking the search object */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_LOCAL_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelLocalFolder *)f)->priv->l)) -#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelLocalFolder *)f)->priv->l)) -#else -#define CAMEL_LOCAL_FOLDER_LOCK(f, l) -#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) -#endif - -struct _CamelSpoolFolderPrivate { -#ifdef ENABLE_THREADS - GMutex *search_lock; /* for locking the search object */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_SPOOL_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelSpoolFolder *)f)->priv->l)) -#define CAMEL_SPOOL_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelSpoolFolder *)f)->priv->l)) -#else -#define CAMEL_SPOOL_FOLDER_LOCK(f, l) -#define CAMEL_SPOOL_FOLDER_UNLOCK(f, l) -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_H */ - diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c deleted file mode 100644 index f4a4301022..0000000000 --- a/camel/providers/local/camel-local-provider.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian (www.ximian.com). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> - -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" - -#include "camel-mh-store.h" -#include "camel-mbox-store.h" -#include "camel-maildir-store.h" -#include "camel-spool-store.h" - -#define d(x) - -static CamelProvider mh_provider = { - "mh", - N_("MH-format mail directories"), - N_("For storing local mail in MH-like mail directories."), - "mail", - CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, - /* ... */ -}; - -static CamelProvider mbox_provider = { - "mbox", - N_("Local delivery"), - N_("For retrieving local mail from standard mbox formated spools."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, - /* ... */ -}; - -static CamelProviderConfEntry local_conf_entries[] = { - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in INBOX"), "0" }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider maildir_provider = { - "maildir", - N_("Maildir-format mail directories"), - N_("For storing local mail in maildir directories."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | - CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, - local_conf_entries, - /* ... */ -}; - -static CamelProvider spool_provider = { - "spool", - N_("Standard Unix mbox spools"), - N_("For reading and storing local mail in standard mbox spool files."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, - local_conf_entries, - /* ... */ -}; - -/* build a canonical 'path' */ -static char * -make_can_path(char *p, char *o) -{ - char c, last, *start = o; - - d(printf("canonical '%s' = ", p)); - - last = 0; - while ((c = *p++)) { - if (c!='/' - || (c=='/' && last != '/')) - *o++ = c; - last = c; - } - if (o>start && o[-1] == '/') - o[-1] = 0; - else - *o = 0; - - d(printf("'%s'\n", start)); - - return start; -} - -/* 'helper' function for it */ -#define get_can_path(p) ((p==NULL)?NULL:(make_can_path((p), alloca(strlen(p)+1)))) - -static guint -local_url_hash (const void *v) -{ - const CamelURL *u = v; - guint hash = 0; - -#define ADD_HASH(s) if (s) hash ^= g_str_hash (s); - - ADD_HASH (u->protocol); - ADD_HASH (u->user); - ADD_HASH (u->authmech); - ADD_HASH (u->host); - if (u->path) - hash ^= g_str_hash(get_can_path(u->path)); - ADD_HASH (u->path); - ADD_HASH (u->query); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -local_url_equal(const void *v, const void *v2) -{ - const CamelURL *u1 = v, *u2 = v2; - char *p1, *p2; - - p1 = get_can_path(u1->path); - p2 = get_can_path(u2->path); - return check_equal(p1, p2) - && check_equal(u1->protocol, u2->protocol) - && check_equal(u1->user, u2->user) - && check_equal(u1->authmech, u2->authmech) - && check_equal(u1->host, u2->host) - && check_equal(u1->query, u2->query) - && u1->port == u2->port; -} - -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(local_url_hash, local_url_equal); - mh_provider.url_hash = local_url_hash; - mh_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &mh_provider); - - mbox_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mbox_store_get_type(); - mbox_provider.service_cache = g_hash_table_new(local_url_hash, local_url_equal); - mbox_provider.url_hash = local_url_hash; - mbox_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &mbox_provider); - - maildir_provider.object_types[CAMEL_PROVIDER_STORE] = camel_maildir_store_get_type(); - maildir_provider.service_cache = g_hash_table_new(local_url_hash, local_url_equal); - maildir_provider.url_hash = local_url_hash; - maildir_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &maildir_provider); - - spool_provider.object_types[CAMEL_PROVIDER_STORE] = camel_spool_store_get_type(); - spool_provider.service_cache = g_hash_table_new(local_url_hash, local_url_equal); - spool_provider.url_hash = local_url_hash; - spool_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &spool_provider); -} diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c deleted file mode 100644 index daa70979dc..0000000000 --- a/camel/providers/local/camel-local-store.c +++ /dev/null @@ -1,404 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> - -#include <glib.h> - -#include "camel-private.h" - -#include "camel-local-store.h" -#include "camel-exception.h" -#include "camel-url.h" - -#include "camel-local-folder.h" - -#define d(x) - -/* Returns the class for a CamelLocalStore */ -#define CLOCALS_CLASS(so) CAMEL_LOCAL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, 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, const char *new, CamelException *ex); -static CamelFolderInfo *create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_local_store_class_init (CamelLocalStoreClass *camel_local_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_local_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_local_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -static void -camel_local_store_finalize (CamelLocalStore *local_store) -{ - if (local_store->toplevel_dir) - g_free (local_store->toplevel_dir); -} - -CamelType -camel_local_store_get_type (void) -{ - static CamelType camel_local_store_type = CAMEL_INVALID_TYPE; - - if (camel_local_store_type == CAMEL_INVALID_TYPE) { - camel_local_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelLocalStore", - sizeof (CamelLocalStore), - sizeof (CamelLocalStoreClass), - (CamelObjectClassInitFunc) camel_local_store_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_local_store_finalize); - } - - return camel_local_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelLocalStore *local_store = CAMEL_LOCAL_STORE (service); - int len; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - len = strlen (service->url->path); - if (service->url->path[len - 1] != '/') - local_store->toplevel_dir = g_strdup_printf ("%s/", service->url->path); - else - local_store->toplevel_dir = g_strdup (service->url->path); -} - -const char * -camel_local_store_get_toplevel_dir (CamelLocalStore *store) -{ - return store->toplevel_dir; -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - struct stat st; - char *path = ((CamelLocalStore *)store)->toplevel_dir; - char *sub, *slash; - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - if (stat(path, &st) == 0) { - if (!S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not a regular directory"), path); - } - return NULL; - } - - if (errno != ENOENT - || (flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), path, strerror(errno)); - return NULL; - } - - /* need to create the dir heirarchy */ - sub = alloca(strlen(path)+1); - strcpy(sub, path); - slash = sub; - do { - slash = strchr(slash+1, '/'); - if (slash) - *slash = 0; - if (stat(sub, &st) == -1) { - if (errno != ENOENT - || mkdir(sub, 0700) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), path, strerror(errno)); - return NULL; - } - } - if (slash) - *slash = '/'; - } while (slash); - - return NULL; -} - -static CamelFolder * -get_inbox(CamelStore *store, CamelException *ex) -{ - camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Local stores do not have an inbox")); - return NULL; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - char *dir = ((CamelLocalStore*)service)->toplevel_dir; - - if (brief) - return g_strdup (dir); - else - return g_strdup_printf (_("Local mail file %s"), dir); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - /* FIXME: This is broken, but it corresponds to what was - * there before. - */ - - d(printf("-- LOCAL STRE -- get folder info: %s\n", top)); - - return NULL; -} - -static CamelFolderInfo * -create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - char *path = ((CamelLocalStore *)store)->toplevel_dir; - char *name; - CamelFolder *folder; - CamelFolderInfo *info = NULL; - struct stat st; - - /* This is a pretty hacky version of create folder, but should basically work */ - - /* FIXME: The strings here are funny because of string freeze */ - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - name = g_strdup_printf("%s/%s/%s", path, parent_name, folder_name); - - if (stat(name, &st) == 0 || errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), name, strerror(errno)); - g_free(name); - return NULL; - } - - g_free(name); - - name = g_strdup_printf("%s/%s", parent_name, folder_name); - - folder = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex); - if (folder) { - camel_object_unref((CamelObject *)folder); - info = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info(store, name, 0, ex); - - /* get_folder(CREATE) will emit a folder_created event for us */ - /*if (info) - camel_object_trigger_event((CamelObject *)store, "folder_created", info);*/ - } - - g_free(name); - - return info; -} - -static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, int missingok, CamelException *ex) -{ - struct stat st; - char *old = g_strconcat(prefix, oldp, suffix, 0); - char *new = g_strconcat(prefix, newp, suffix, 0); - int ret = -1; - int err = 0; - - d(printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix)); - - if (stat(old, &st) == -1) { - if (missingok && errno == ENOENT) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (S_ISDIR(st.st_mode)) { /* use rename for dirs */ - if (rename(old, new) == 0 - || stat(new, &st) == 0) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (link(old, new) == 0 /* and link for files */ - || (stat(new, &st) == 0 && st.st_nlink == 2)) { - if (unlink(old) == 0) { - ret = 0; - } else { - err = errno; - unlink(new); - ret = -1; - } - } else { - err = errno; - ret = -1; - } - - if (ret == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder %s to %s: %s"), - old, new, strerror(err)); - } - - g_free(old); - g_free(new); - return ret; -} - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - char *path = CAMEL_LOCAL_STORE (store)->toplevel_dir; - CamelLocalFolder *folder; - char *newibex = g_strdup_printf("%s%s.ibex", path, new); - char *oldibex = g_strdup_printf("%s%s.ibex", path, old); - - /* try to rollback failures, has obvious races */ - - d(printf("local rename folder '%s' '%s'\n", old, new)); - - CAMEL_STORE_LOCK(store, cache_lock); - folder = g_hash_table_lookup(store->folders, old); - if (folder) { - if (folder->index && ibex_move(folder->index, newibex) == -1) - goto ibex_failed; - } else { - if (xrename(old, new, path, ".ibex", TRUE, ex)) - goto ibex_failed; - } - - if (xrename(old, new, path, ".ev-summary", TRUE, ex)) - goto summary_failed; - - if (xrename(old, new, path, "", FALSE, ex)) - goto base_failed; - - CAMEL_STORE_UNLOCK(store, cache_lock); - - g_free(newibex); - g_free(oldibex); - - return; - -base_failed: - xrename(new, old, path, ".ev-summary", TRUE, ex); - -summary_failed: - if (folder) { - if (folder->index) - ibex_move(folder->index, oldibex); - } else - xrename(new, old, path, ".ibex", TRUE, ex); - -ibex_failed: - CAMEL_STORE_UNLOCK(store, cache_lock); - g_free(newibex); - g_free(oldibex); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - char *name; - char *str; - - /* remove metadata only */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - str = g_strdup_printf("%s.ev-summary", name); - if (unlink(str) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder summary file `%s': %s"), - str, strerror(errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - str = g_strdup_printf("%s.ibex", name); - if (unlink(str) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder index file `%s': %s"), - str, strerror(errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - g_free(name); - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (g_basename (folder_name)); - fi->url = g_strdup_printf ("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - fi->unread_message_count = -1; - camel_folder_info_build_path(fi, '/'); - - camel_object_trigger_event (CAMEL_OBJECT (store), - "folder_deleted", fi); - - camel_folder_info_free (fi); -} diff --git a/camel/providers/local/camel-local-store.h b/camel/providers/local/camel-local-store.h deleted file mode 100644 index 21d854c562..0000000000 --- a/camel/providers/local/camel-local-store.h +++ /dev/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 Ximian, Inc. <bertrand@helixcode.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_LOCAL_STORE_H -#define CAMEL_LOCAL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-store.h" - -#define CAMEL_LOCAL_STORE_TYPE (camel_local_store_get_type ()) -#define CAMEL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_STORE_TYPE, CamelLocalStore)) -#define CAMEL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_STORE_TYPE, CamelLocalStoreClass)) -#define CAMEL_IS_LOCAL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - char *toplevel_dir; - -} CamelLocalStore; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelLocalStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_local_store_get_type (void); - -const gchar *camel_local_store_get_toplevel_dir (CamelLocalStore *store); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_STORE_H */ - - diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c deleted file mode 100644 index 508c7e0831..0000000000 --- a/camel/providers/local/camel-local-summary.c +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-local-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-stream-null.h" - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_LOCAL_SUMMARY_VERSION (0x200) - -struct _CamelLocalSummaryPrivate { -}; - -#define _PRIVATE(o) (((CamelLocalSummary *)(o))->priv) - -static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _header_raw *); - -static int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); -static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); - -static int local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static void camel_local_summary_class_init (CamelLocalSummaryClass *klass); -static void camel_local_summary_init (CamelLocalSummary *obj); -static void camel_local_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_local_summary_parent; - -CamelType -camel_local_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelLocalSummary", - sizeof (CamelLocalSummary), - sizeof (CamelLocalSummaryClass), - (CamelObjectClassInitFunc) camel_local_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_local_summary_init, - (CamelObjectFinalizeFunc) camel_local_summary_finalise); - } - - return type; -} - -static void -camel_local_summary_class_init(CamelLocalSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass; - - camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - sklass->message_info_new = message_info_new; - - klass->load = local_summary_load; - klass->check = local_summary_check; - klass->sync = local_summary_sync; - klass->add = local_summary_add; - - klass->encode_x_evolution = local_summary_encode_x_evolution; - klass->decode_x_evolution = local_summary_decode_x_evolution; -} - -static void -camel_local_summary_init(CamelLocalSummary *obj) -{ - struct _CamelLocalSummaryPrivate *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(CamelMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_LOCAL_SUMMARY_VERSION; -} - -static void -camel_local_summary_finalise(CamelObject *obj) -{ - CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(obj); - - g_free(mbs->folder_path); -} - -void -camel_local_summary_construct(CamelLocalSummary *new, const char *filename, const char *local_name, ibex *index) -{ - camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE); - camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename); - new->folder_path = g_strdup(local_name); - new->index = index; -} - -static int -local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - return camel_folder_summary_load((CamelFolderSummary *)cls); -} - -/* load/check the summary */ -int -camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - d(printf("Loading summary ...\n")); - - if (forceindex - || stat(s->summary_path, &st) == -1 - || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) { - w(g_warning("Could not load summary: flags may be reset")); - camel_folder_summary_clear((CamelFolderSummary *)cls); - return -1; - } - - return 0; -} - -char * -camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->encode_x_evolution(cls, info); -} - -int -camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info); -} - -/*#define DOSTATS*/ -#ifdef DOSTATS -struct _stat_info { - int mitotal; - int micount; - int citotal; - int cicount; - int msgid; - int msgcount; -}; - -static void -do_stat_ci(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageContentInfo *ci) -{ - info->cicount++; - info->citotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4 memchunks are 1/4 byte overhead per mi */; - if (ci->id) - info->citotal += strlen(ci->id) + 4; - if (ci->description) - info->citotal += strlen(ci->description) + 4; - if (ci->encoding) - info->citotal += strlen(ci->encoding) + 4; - if (ci->type) { - struct _header_content_type *ct = ci->type; - struct _header_param *param; - - info->citotal += sizeof(*ct) + 4; - if (ct->type) - info->citotal += strlen(ct->type) + 4; - if (ct->subtype) - info->citotal += strlen(ct->subtype) + 4; - param = ct->params; - while (param) { - info->citotal += sizeof(*param) + 4; - if (param->name) - info->citotal += strlen(param->name)+4; - if (param->value) - info->citotal += strlen(param->value)+4; - param = param->next; - } - } - ci = ci->childs; - while (ci) { - do_stat_ci(cls, info, ci); - ci = ci->next; - } -} - -static void -do_stat_mi(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageInfo *mi) -{ - info->micount++; - info->mitotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4*/; - - if (mi->subject) - info->mitotal += strlen(mi->subject) + 4; - if (mi->to) - info->mitotal += strlen(mi->to) + 4; - if (mi->from) - info->mitotal += strlen(mi->from) + 4; - if (mi->cc) - info->mitotal += strlen(mi->cc) + 4; - if (mi->uid) - info->mitotal += strlen(mi->uid) + 4; - - if (mi->references) { - info->mitotal += (mi->references->size-1) * sizeof(CamelSummaryMessageID) + sizeof(CamelSummaryReferences) + 4; - info->msgid += (mi->references->size) * sizeof(CamelSummaryMessageID); - info->msgcount += mi->references->size; - } - - /* dont have any user flags yet */ - - if (mi->content) { - do_stat_ci(cls, info, mi->content); - } -} - -#endif - -int -camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret; - - ret = ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->check(cls, changeinfo, ex); - -#ifdef DOSTATS - if (ret != -1) { - int i; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct _stat_info stats = { 0 }; - - for (i=0;i<camel_folder_summary_count(s);i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - do_stat_mi(cls, &stats, info); - camel_folder_summary_info_free(s, info); - } - - printf("\nMemory used by summary:\n\n"); - printf("Total of %d messages\n", camel_folder_summary_count(s)); - printf("Total: %d bytes (ave %f)\n", stats.citotal + stats.mitotal, - (double)(stats.citotal+stats.mitotal)/(double)camel_folder_summary_count(s)); - printf("Message Info: %d (ave %f)\n", stats.mitotal, (double)stats.mitotal/(double)stats.micount); - printf("Content Info; %d (ave %f) count %d\n", stats.citotal, (double)stats.citotal/(double)stats.cicount, stats.cicount); - printf("message id's: %d (ave %f) count %d\n", stats.msgid, (double)stats.msgid/(double)stats.msgcount, stats.msgcount); - } -#endif - return ret; -} - -int -camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->sync(cls, expunge, changeinfo, ex); -} - -CamelMessageInfo * -camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->add(cls, msg, info, ci, ex); -} - -/** - * camel_local_summary_write_headers: - * @fd: - * @header: - * @xevline: - * - * Write a bunch of headers to the file @fd. IF xevline is non NULL, then - * an X-Evolution header line is created at the end of all of the headers. - * The headers written are termianted with a blank line. - * - * Return value: -1 on error, otherwise the number of bytes written. - **/ -int -camel_local_summary_write_headers(int fd, struct _header_raw *header, char *xevline) -{ - int outlen = 0, len; - int newfd; - FILE *out; - - /* dum de dum, maybe the whole sync function should just use stdio for output */ - newfd = dup(fd); - if (newfd == -1) - return -1; - - out = fdopen(newfd, "w"); - if (out == NULL) { - close(newfd); - errno = EINVAL; - return -1; - } - - while (header) { - if (strcmp(header->name, "X-Evolution")) { - len = fprintf(out, "%s:%s\n", header->name, header->value); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - header = header->next; - } - - if (xevline) { - len = fprintf(out, "X-Evolution: %s\n\n", xevline); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (fclose(out) == -1) - return -1; - - return outlen; -} - -static int -local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - /* FIXME: sync index here ? */ - return 0; -} - -static int -local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret = 0; - - ret = camel_folder_summary_save((CamelFolderSummary *)cls); - if (ret == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not save summary: %s: %s"), cls->folder_path, strerror(errno)); - g_warning("Could not save summary for %s: %s", cls->folder_path, strerror(errno)); - } - - if (cls->index && ibex_save(cls->index) == -1) - g_warning("Could not sync index for %s: %s", cls->folder_path, strerror(errno)); - - return ret; -} - -static CamelMessageInfo * -local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelMessageInfo *mi; - char *xev; - - d(printf("Adding message to summary\n")); - - mi = camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg); - if (mi) { - d(printf("Added, uid = %s\n", mi->uid)); - if (info) { - CamelTag *tag = info->user_tags; - CamelFlag *flag = info->user_flags; - - while (flag) { - camel_flag_set(&mi->user_flags, flag->name, TRUE); - flag = flag->next; - } - - while (tag) { - camel_tag_set(&mi->user_tags, tag->name, tag->value); - tag = tag->next; - } - - mi->flags = mi->flags | (info->flags & 0xffff); - if (info->size) - mi->size = info->size; - } - - /* we need to calculate the size ourselves */ - if (mi->size == 0) { - CamelStreamNull *sn = (CamelStreamNull *)camel_stream_null_new(); - - camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn); - mi->size = sn->written; - camel_object_unref((CamelObject *)sn); - } - - mi->flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED); - xev = camel_local_summary_encode_x_evolution(cls, mi); - camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev); - g_free(xev); - camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi)); - } else { - d(printf("Failed!\n")); - camel_exception_set(ex, 1, _("Unable to add message to summary: unknown reason")); - } - return mi; -} - -static char * -local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi) -{ - GString *out = g_string_new(""); - struct _header_param *params = NULL; - GString *val = g_string_new(""); - CamelFlag *flag = mi->user_flags; - CamelTag *tag = mi->user_tags; - char *ret; - const char *p, *uidstr; - guint32 uid; - - /* FIXME: work out what to do with uid's that aren't stored here? */ - /* FIXME: perhaps make that a mbox folder only issue?? */ - p = uidstr = camel_message_info_uid(mi); - while (*p && isdigit(*p)) - p++; - if (*p == 0 && sscanf(uidstr, "%u", &uid) == 1) { - g_string_sprintf(out, "%08x-%04x", uid, mi->flags & 0xffff); - } else { - g_string_sprintf(out, "%s-%04x", uidstr, mi->flags & 0xffff); - } - - if (flag || tag) { - val = g_string_new(""); - - if (flag) { - while (flag) { - g_string_append(val, flag->name); - if (flag->next) - g_string_append_c(val, ','); - flag = flag->next; - } - header_set_param(¶ms, "flags", val->str); - g_string_truncate(val, 0); - } - if (tag) { - while (tag) { - g_string_append(val, tag->name); - g_string_append_c(val, '='); - g_string_append(val, tag->value); - if (tag->next) - g_string_append_c(val, ','); - tag = tag->next; - } - header_set_param(¶ms, "tags", val->str); - } - g_string_free(val, TRUE); - header_param_list_format_append(out, params); - header_param_list_free(params); - } - ret = out->str; - g_string_free(out, FALSE); - return ret; -} - -static int -local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi) -{ - struct _header_param *params, *scan; - guint32 uid, flags; - char *header; - int i; - - /* check for uid/flags */ - header = header_token_decode(xev); - if (header && strlen(header) == strlen("00000000-0000") - && sscanf(header, "%08x-%04x", &uid, &flags) == 2) { - char uidstr[20]; - if (mi) { - sprintf(uidstr, "%u", uid); - camel_message_info_set_uid(mi, g_strdup(uidstr)); - mi->flags = flags; - } - } else { - g_free(header); - return -1; - } - g_free(header); - - if (mi == NULL) - return 0; - - /* check for additional data */ - header = strchr(xev, ';'); - if (header) { - params = header_param_list_decode(header+1); - scan = params; - while (scan) { - if (!strcasecmp(scan->name, "flags")) { - char **flagv = g_strsplit(scan->value, ",", 1000); - - for (i=0;flagv[i];i++) { - camel_flag_set(&mi->user_flags, flagv[i], TRUE); - } - g_strfreev(flagv); - } else if (!strcasecmp(scan->name, "tags")) { - char **tagv = g_strsplit(scan->value, ",", 10000); - char *val; - - for (i=0;tagv[i];i++) { - val = strchr(tagv[i], '='); - if (val) { - *val++ = 0; - camel_tag_set(&mi->user_tags, tagv[i], val); - val[-1]='='; - } - } - g_strfreev(tagv); - } - scan = scan->next; - } - header_param_list_free(params); - } - return 0; -} - -static CamelMessageInfo * -message_info_new(CamelFolderSummary *s, struct _header_raw *h) -{ - CamelMessageInfo *mi; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - - mi = ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new(s, h); - if (mi) { - const char *xev; - int doindex = FALSE; - - xev = header_raw_find(&h, "X-Evolution", NULL); - if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) { - /* to indicate it has no xev header */ - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - - /* shortcut, no need to look it up in the index library */ - doindex = TRUE; - } - - if (cls->index - && (doindex - || cls->index_force - || !ibex_contains_name(cls->index, (char *)camel_message_info_uid(mi)))) { - d(printf("Am indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, cls->index); - } else { - d(printf("Not indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, NULL); - } - } - - return mi; -} diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h deleted file mode 100644 index e9c570deb1..0000000000 --- a/camel/providers/local/camel-local-summary.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_LOCAL_SUMMARY_H -#define _CAMEL_LOCAL_SUMMARY_H - -#include <camel/camel-folder-summary.h> -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <libibex/ibex.h> - -#define CAMEL_LOCAL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_local_summary_get_type (), CamelLocalSummary) -#define CAMEL_LOCAL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_local_summary_get_type (), CamelLocalSummaryClass) -#define CAMEL_IS_LOCAL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_local_summary_get_type ()) - -typedef struct _CamelLocalSummary CamelLocalSummary; -typedef struct _CamelLocalSummaryClass CamelLocalSummaryClass; - -/* extra summary flags */ -enum { - CAMEL_MESSAGE_FOLDER_NOXEV = 1<<17, - CAMEL_MESSAGE_FOLDER_XEVCHANGE = 1<<18, -}; - -struct _CamelLocalSummary { - CamelFolderSummary parent; - - struct _CamelLocalSummaryPrivate *priv; - - char *folder_path; /* name of matching folder */ - - ibex *index; - int index_force; /* do we force index during creation? */ -}; - -struct _CamelLocalSummaryClass { - CamelFolderSummaryClass parent_class; - - int (*load)(CamelLocalSummary *cls, int forceindex, CamelException *ex); - int (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - int (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - - char *(*encode_x_evolution)(CamelLocalSummary *cls, const CamelMessageInfo *info); - int (*decode_x_evolution)(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info); -}; - -guint camel_local_summary_get_type (void); -void camel_local_summary_construct (CamelLocalSummary *new, const char *filename, const char *local_name, ibex *index); - -/* load/check the summary */ -int camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* generate an X-Evolution header line */ -char *camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *info); -int camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header */ -int camel_local_summary_write_headers(int fd, struct _header_raw *header, char *xevline); - -#endif /* ! _CAMEL_LOCAL_SUMMARY_H */ - diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c deleted file mode 100644 index 5336cb39c3..0000000000 --- a/camel/providers/local/camel-maildir-folder.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2000 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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-maildir-folder.h" -#include "camel-maildir-store.h" -#include "string-utils.h" -#include "camel-stream-fs.h" -#include "camel-maildir-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-exception.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirFolder */ -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *maildir_create_summary(const char *path, const char *folder, ibex *index); - -static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, CamelException * ex); -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -static void maildir_finalize(CamelObject * object); - -static void camel_maildir_folder_class_init(CamelObjectClass * camel_maildir_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_maildir_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_maildir_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = maildir_append_message; - camel_folder_class->get_message = maildir_get_message; - - lclass->create_summary = maildir_create_summary; -} - -static void maildir_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMaildirFolder *maildir_folder = object;*/ -} - -static void maildir_finalize(CamelObject * object) -{ - /*CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER(object);*/ -} - -CamelType camel_maildir_folder_get_type(void) -{ - static CamelType camel_maildir_folder_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_folder_type == CAMEL_INVALID_TYPE) { - camel_maildir_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMaildirFolder", - sizeof(CamelMaildirFolder), - sizeof(CamelMaildirFolderClass), - (CamelObjectClassInitFunc) camel_maildir_folder_class_init, - NULL, - (CamelObjectInitFunc) maildir_init, - (CamelObjectFinalizeFunc) maildir_finalize); - } - - return camel_maildir_folder_type; -} - -CamelFolder * -camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating maildir folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MAILDIR_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, ".") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -static CamelLocalSummary *maildir_create_summary(const char *path, const char *folder, ibex *index) -{ - return (CamelLocalSummary *)camel_maildir_summary_new(path, folder, index); -} - -static void -maildir_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex) -{ - CamelMaildirFolder *maildir_folder = (CamelMaildirFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - CamelMaildirMessageInfo *mdi; - char *name, *dest = NULL; - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - mdi = (CamelMaildirMessageInfo *)mi; - - d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename)); - - /* write it out to tmp, use the uid we got from the summary */ - name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name (name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* now move from tmp to cur (bypass new, does it matter?) */ - dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); - if (rename (name, dest) == 1) - goto fail_write; - - g_free (dest); - g_free (name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)maildir_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)maildir_folder)->changes); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Maildir append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to maildir folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); - g_free (dest); -} - -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - CamelMaildirMessageInfo *mdi; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); - return NULL; - } - - mdi = (CamelMaildirMessageInfo *)info; - - /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess */ - name = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); - - camel_folder_summary_info_free(folder->summary, info); - - if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), - name, g_strerror(errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv(ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), - name, _("Invalid message contents")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-maildir-folder.h b/camel/providers/local/camel-maildir-folder.h deleted file mode 100644 index c495d9b14d..0000000000 --- a/camel/providers/local/camel-maildir-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 "camel-local-folder.h" - -#define CAMEL_MAILDIR_FOLDER_TYPE (camel_maildir_folder_get_type ()) -#define CAMEL_MAILDIR_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolder)) -#define CAMEL_MAILDIR_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolderClass)) -#define CAMEL_IS_MAILDIR_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - -} CamelMaildirFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMaildirFolderClass; - -/* public methods */ -CamelFolder *camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_maildir_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_FOLDER_H */ diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c deleted file mode 100644 index e26ab6b23e..0000000000 --- a/camel/providers/local/camel-maildir-store.c +++ /dev/null @@ -1,412 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> - -#include <dirent.h> - -#include "camel-maildir-store.h" -#include "camel-maildir-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" - -#define d(x) - -static CamelLocalStoreClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirStore */ -#define CMAILDIRS_CLASS(so) CAMEL_MAILDIR_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex); - -static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class); - /*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_maildir_store_class);*/ - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->delete_folder = delete_folder; - - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; -} - -CamelType camel_maildir_store_get_type(void) -{ - static CamelType camel_maildir_store_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_store_type == CAMEL_INVALID_TYPE) { - camel_maildir_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMaildirStore", - sizeof(CamelMaildirStore), - sizeof(CamelMaildirStoreClass), - (CamelObjectClassInitFunc) camel_maildir_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_maildir_store_type; -} - -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - CamelFolder *folder = NULL; - - (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); - if (camel_exception_is_set(ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", 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, strerror(errno)); - } else if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), folder_name); - } else { - if (mkdir(name, 0700) != 0 - || mkdir(tmp, 0700) != 0 - || mkdir(cur, 0700) != 0 - || mkdir(new, 0700) != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s':\n%s"), - folder_name, strerror(errno)); - rmdir(tmp); - rmdir(cur); - rmdir(new); - rmdir(name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - } - } else if (!S_ISDIR(st.st_mode) - || stat(tmp, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(cur, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(new, &st) != 0 || !S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a maildir directory."), name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); - - return folder; -} - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - return get_folder (store, ".", 0, ex); -} - -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(name, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(tmp, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(cur, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(new, &st) == -1 || !S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, errno?strerror(errno):_("not a maildir directory")); - } else { - int err = 0; - - /* remove subdirs first - will fail if not empty */ - if (rmdir(cur) == -1 || rmdir(new) == -1) { - err = errno; - } else { - DIR *dir; - struct dirent *d; - - /* for tmp (only), its contents is irrelevant */ - dir = opendir(tmp); - if (dir) { - while ( (d=readdir(dir)) ) { - char *name = d->d_name, *file; - - if (!strcmp(name, ".") || !strcmp(name, "..")) - continue; - file = g_strdup_printf("%s/%s", tmp, name); - unlink(file); - g_free(file); - } - closedir(dir); - } - if (rmdir(tmp) == -1 || rmdir(name) == -1) - err = errno; - } - - if (err != 0) { - /* easier just to mkdir all (and let them fail), than remember what we got to */ - mkdir(name, 0700); - mkdir(cur, 0700); - mkdir(new, 0700); - mkdir(tmp, 0700); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, strerror(err)); - } else { - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); - } - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); -} - -static CamelFolderInfo *camel_folder_info_new(const char *url, const char *full, const char *name, int unread) -{ - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - fi->url = g_strdup(url); - fi->full_name = g_strdup(full); - fi->name = g_strdup(name); - fi->unread_message_count = unread; - camel_folder_info_build_path(fi, '/'); - - d(printf("Adding maildir info: '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* returns number of records found at or below this level */ -static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *name, *uri, *tmp, *cur, *new; - const char *base; - CamelFolderInfo *fi = NULL; - struct stat st; - CamelFolder *folder; - int unread; - - /* look for folders matching the right structure, recursively */ - name = g_strdup_printf("%s/%s", root, path); - - d(printf("checking dir '%s' part '%s' for maildir content\n", root, path)); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode) - && stat(cur, &st) == 0 && S_ISDIR(st.st_mode) - && stat(new, &st) == 0 && S_ISDIR(st.st_mode)) { - uri = g_strdup_printf("maildir:%s#%s", root, path); - } else - uri = g_strdup_printf("maildir:%s;noselect=yes#%s", root, path); - - base = strrchr(path, '/'); - if (base) - base++; - else - base = path; - - /* if we have this folder open, get the real unread count */ - unread = -1; - - CAMEL_STORE_LOCK(store, cache_lock); - folder = g_hash_table_lookup(store->folders, path); - if (folder) - unread = camel_folder_get_unread_message_count(folder); - CAMEL_STORE_UNLOCK(store, cache_lock); - - /* if we dont have a folder, then scan the directory and get the unread - count from there, which is reasonably cheap (on decent filesystem) */ - /* Well we could get this from the summary, but this is more accurate */ - if (folder == NULL - && (flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) { - unread = 0; - dir = opendir(new); - if (dir) { - /* we assume that all files here are unread ones */ - while ( (d = readdir(dir)) ) { - if (d->d_name[0] != '.') - unread++; - } - closedir(dir); - } - dir = opendir(cur); - if (dir) { - /* any files with flags but not the 'S' (seen) flag are unread */ - while ( (d = readdir(dir)) ) { - char *p = strstr(d->d_name, ":2,"); - - if (p && strchr(p, 'S') == NULL) - unread++; - } - closedir(dir); - } - } - - fi = camel_folder_info_new(uri, path, base, unread); - - d(printf("found! uri = %s\n", fi->url)); - d(printf(" full_name = %s\n name = '%s'\n", fi->full_name, fi->name)); - - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - g_free(uri); - - g_free(tmp); - g_free(cur); - g_free(new); - - unread = 0; - - /* always look further if asked */ - if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) { - dir = opendir(name); - if (dir == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - root, strerror(errno)); - g_free(name); - return -1; - } - - while ( (d = readdir(dir)) ) { - if (strcmp(d->d_name, "tmp") == 0 - || strcmp(d->d_name, "cur") == 0 - || strcmp(d->d_name, "new") == 0 - || strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - tmp = g_strdup_printf("%s/%s", name, d->d_name); - if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_malloc(sizeof(*inew)); - - *inew = in; - g_hash_table_insert(visited, inew, inew); - new = g_strdup_printf("%s/%s", path, d->d_name); - if (scan_dir(store, visited, root, new, flags, fi, &fi->child, ex) == -1) { - g_free(tmp); - g_free(new); - closedir(dir); - return -1; - } - g_free(new); - } - } - g_free(tmp); - } - closedir(dir); - } - - g_free(name); - - return 0; -} - -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelLocalStore *local_store = (CamelLocalStore *)store; - GHashTable *visited; - - visited = g_hash_table_new(inode_hash, inode_equal); - - if (scan_dir(store, visited, ((CamelService *)local_store)->url->path, top?top:".", flags, NULL, &fi, ex) == -1 && fi != NULL) { - camel_store_free_folder_info_full(store, fi); - fi = NULL; - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - - return fi; -} diff --git a/camel/providers/local/camel-maildir-store.h b/camel/providers/local/camel-maildir-store.h deleted file mode 100644 index f7725bc189..0000000000 --- a/camel/providers/local/camel-maildir-store.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 "camel-local-store.h" - -#define CAMEL_MAILDIR_STORE_TYPE (camel_maildir_store_get_type ()) -#define CAMEL_MAILDIR_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStore)) -#define CAMEL_MAILDIR_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStoreClass)) -#define CAMEL_IS_MAILDIR_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_STORE_TYPE)) - -typedef struct { - CamelLocalStore parent_object; - -} CamelMaildirStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMaildirStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_maildir_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_STORE_H */ diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c deleted file mode 100644 index 1cfcf50a88..0000000000 --- a/camel/providers/local/camel-maildir-summary.c +++ /dev/null @@ -1,753 +0,0 @@ -/* - * Copyright (C) 2000 Ximian 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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> - -#include "camel-maildir-summary.h" -#include <camel/camel-mime-message.h> - -#include "camel-private.h" -#include "e-util/e-memory.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000) - -static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); -static CamelMessageInfo *message_info_new(CamelFolderSummary *, struct _header_raw *); -static void message_info_free(CamelFolderSummary *, CamelMessageInfo *mi); - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s); -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); - -static void camel_maildir_summary_class_init (CamelMaildirSummaryClass *class); -static void camel_maildir_summary_init (CamelMaildirSummary *gspaper); -static void camel_maildir_summary_finalise (CamelObject *obj); - -#define _PRIVATE(x) (((CamelMaildirSummary *)(x))->priv) - -struct _CamelMaildirSummaryPrivate { - char *current_file; - char *hostname; - - GHashTable *load_map; -}; - -static CamelLocalSummaryClass *parent_class; - -CamelType -camel_maildir_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type (), "CamelMaildirSummary", - sizeof(CamelMaildirSummary), - sizeof(CamelMaildirSummaryClass), - (CamelObjectClassInitFunc)camel_maildir_summary_class_init, - NULL, - (CamelObjectInitFunc)camel_maildir_summary_init, - (CamelObjectFinalizeFunc)camel_maildir_summary_finalise); - } - - return type; -} - -static void -camel_maildir_summary_class_init (CamelMaildirSummaryClass *class) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->message_info_load = message_info_load; - sklass->message_info_new = message_info_new; - sklass->message_info_free = message_info_free; - sklass->next_uid_string = maildir_summary_next_uid_string; - - lklass->load = maildir_summary_load; - lklass->check = maildir_summary_check; - lklass->sync = maildir_summary_sync; - lklass->add = maildir_summary_add; - lklass->encode_x_evolution = maildir_summary_encode_x_evolution; - lklass->decode_x_evolution = maildir_summary_decode_x_evolution; -} - -static void -camel_maildir_summary_init (CamelMaildirSummary *o) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *) o; - char hostname[256]; - - o->priv = g_malloc0(sizeof(*o->priv)); - /* set unique file version */ - s->version += CAMEL_MAILDIR_SUMMARY_VERSION; - - s->message_info_size = sizeof(CamelMaildirMessageInfo); - s->content_info_size = sizeof(CamelMaildirMessageContentInfo); - -#if defined (DOEPOOLV) || defined (DOESTRV) - s->message_info_strings = CAMEL_MAILDIR_INFO_LAST; -#endif - - if (gethostname(hostname, 256) == 0) { - o->priv->hostname = g_strdup(hostname); - } else { - o->priv->hostname = g_strdup("localhost"); - } -} - -static void -camel_maildir_summary_finalise(CamelObject *obj) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)obj; - - g_free(o->priv->hostname); - g_free(o->priv); -} - -/** - * camel_maildir_summary_new: - * - * Create a new CamelMaildirSummary object. - * - * Return value: A new #CamelMaildirSummary object. - **/ -CamelMaildirSummary *camel_maildir_summary_new (const char *filename, const char *maildirdir, ibex *index) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)camel_object_new(camel_maildir_summary_get_type ()); - - camel_local_summary_construct((CamelLocalSummary *)o, filename, maildirdir, index); - return o; -} - -/* the 'standard' maildir flags. should be defined in sorted order. */ -static struct { - char flag; - guint32 flagbit; -} flagbits[] = { - { 'F', CAMEL_MESSAGE_FLAGGED }, - { 'R', CAMEL_MESSAGE_ANSWERED }, - { 'S', CAMEL_MESSAGE_SEEN }, - { 'T', CAMEL_MESSAGE_DELETED }, -}; - -/* convert the uid + flags into a unique:info maildir format */ -char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info) -{ - char *p, *buf; - int i; - const char *uid; - - uid = camel_message_info_uid(info); - buf = alloca(strlen(uid) + strlen(":2,") + (sizeof(flagbits)/sizeof(flagbits[0])) + 1); - p = buf + sprintf(buf, "%s:2,", uid); - for (i=0;i<sizeof(flagbits)/sizeof(flagbits[0]);i++) { - if (info->flags & flagbits[i].flagbit) - *p++ = flagbits[i].flag; - } - *p = 0; - - return g_strdup(buf); -} - -/* returns 0 if the info matches (or there was none), otherwise we changed it */ -int camel_maildir_summary_name_to_info(CamelMessageInfo *info, const char *name) -{ - char *p, c; - guint32 set = 0; /* what we set */ - /*guint32 all = 0;*/ /* all flags */ - int i; - - p = strstr(name, ":2,"); - if (p) { - p+=3; - while ((c = *p++)) { - /* we could assume that the flags are in order, but its just as easy not to require */ - for (i=0;i<sizeof(flagbits)/sizeof(flagbits[0]);i++) { - if (flagbits[i].flag == c && (info->flags & flagbits[i].flagbit) == 0) { - set |= flagbits[i].flagbit; - } - /*all |= flagbits[i].flagbit;*/ - } - } - - /* changed? */ - /*if ((info->flags & all) != set) {*/ - if ((info->flags & set) != set) { - /* ok, they did change, only add the new flags ('merge flags'?) */ - /*info->flags &= all; if we wanted to set only the new flags, which we probably dont */ - info->flags |= set; - return 1; - } - } - - return 0; -} - -/* for maildir, x-evolution isn't used, so dont try and get anything out of it */ -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi) -{ - return -1; -} - -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi) -{ - return NULL; -} - -/* FIXME: - both 'new' and 'add' will try and set the filename, this is not ideal ... -*/ -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMessageInfo *mi; - - mi = ((CamelLocalSummaryClass *) parent_class)->add(cls, msg, info, changes, ex); - if (mi) { - if (info) { - camel_maildir_info_set_filename(mi, camel_maildir_summary_info_to_name(mi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return mi; -} - -static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header_raw *h) -{ - CamelMessageInfo *mi; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - CamelMaildirMessageInfo *mdi; - const char *uid; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new(s, h); - /* assign the uid and new filename */ - if (mi) { - mdi = (CamelMaildirMessageInfo *)mi; - - uid = camel_message_info_uid(mi); - if (uid==NULL || uid[0] == 0) - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - - /* with maildir we know the real received date, from the filename */ - mi->date_received = strtoul(camel_message_info_uid(mi), NULL, 10); - - if (mds->priv->current_file) { -#if 0 - char *p1, *p2, *p3; - unsigned long uid; -#endif - /* if setting from a file, grab the flags from it */ - camel_maildir_info_set_filename(mi, g_strdup(mds->priv->current_file)); - camel_maildir_summary_name_to_info(mi, mds->priv->current_file); - -#if 0 - /* Actually, I dont think all this effort is worth it at all ... */ - - /* also, see if we can extract the next-id from tne name, and safe-if-fy ourselves against collisions */ - /* we check for something.something_number.something */ - p1 = strchr(mdi->filename, '.'); - if (p1) { - p2 = strchr(p1+1, '.'); - p3 = strchr(p1+1, '_'); - if (p2 && p3 && p3<p2) { - uid = strtoul(p3+1, &p1, 10); - if (p1 == p2 && uid>0) - camel_folder_summary_set_uid(s, uid); - } - } -#endif - } else { - /* if creating a file, set its name from the flags we have */ - camel_maildir_info_set_filename(mdi, camel_maildir_summary_info_to_name(mi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return mi; -} - - -static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) -{ -#if !defined (DOEPOOLV) && !defined (DOESTRV) - CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *)mi; - - g_free(mdi->filename); -#endif - ((CamelFolderSummaryClass *) parent_class)->message_info_free(s, mi); -} - - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - d(printf("next uid string called?\n")); - - /* if we have a current file, then use that to get the uid */ - if (mds->priv->current_file) { - char *cln; - - cln = strchr(mds->priv->current_file, ':'); - if (cln) - return g_strndup(mds->priv->current_file, cln-mds->priv->current_file); - else - return g_strdup(mds->priv->current_file); - } else { - /* the first would probably work, but just to be safe, check for collisions */ -#if 0 - return g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), camel_folder_summary_next_uid(s), mds->priv->hostname); -#else - CamelLocalSummary *cls = (CamelLocalSummary *)s; - char *name = NULL, *uid = NULL; - struct stat st; - int retry = 0; - guint32 nextuid = camel_folder_summary_next_uid(s); - - /* we use time.pid_count.hostname */ - do { - if (retry > 0) { - g_free(name); - g_free(uid); - sleep(2); - } - uid = g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), nextuid, mds->priv->hostname); - name = g_strdup_printf("%s/tmp/%s", cls->folder_path, uid); - retry++; - } while (stat(name, &st) == 0 && retry<3); - - /* I dont know what we're supposed to do if it fails to find a unique name?? */ - - g_free(name); - return uid; -#endif - } -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_load(s, in); - if (mi) { - char *name; - - if (mds->priv->load_map - && (name = g_hash_table_lookup(mds->priv->load_map, camel_message_info_uid(mi)))) { - d(printf("Setting filename of %s to %s\n", camel_message_info_uid(mi), name)); - camel_maildir_info_set_filename(mi, g_strdup(name)); - camel_maildir_summary_name_to_info(mi, name); - } - } - - return mi; -} - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - char *cur; - DIR *dir; - struct dirent *d; - CamelMaildirSummary *mds = (CamelMaildirSummary *)cls; - char *uid; - EMemPool *pool; - int ret; - - cur = g_strdup_printf("%s/cur", cls->folder_path); - - d(printf("pre-loading uid <> filename map\n")); - - dir = opendir(cur); - if (dir == NULL) { - camel_exception_setv(ex, 1, _("Cannot open maildir directory path: %s: %s"), cls->folder_path, strerror(errno)); - g_free(cur); - return -1; - } - - mds->priv->load_map = g_hash_table_new(g_str_hash, g_str_equal); - pool = e_mempool_new(1024, 512, E_MEMPOOL_ALIGN_BYTE); - - while ( (d = readdir(dir)) ) { - if (d->d_name[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) { - int len = uid-d->d_name; - uid = e_mempool_alloc(pool, len+1); - memcpy(uid, d->d_name, len); - uid[len] = 0; - g_hash_table_insert(mds->priv->load_map, uid, e_mempool_strdup(pool, d->d_name)); - } else { - uid = e_mempool_strdup(pool, d->d_name); - g_hash_table_insert(mds->priv->load_map, uid, uid); - } - } - closedir(dir); - g_free(cur); - - ret = ((CamelLocalSummaryClass *) parent_class)->load(cls, forceindex, ex); - - g_hash_table_destroy(mds->priv->load_map); - mds->priv->load_map = NULL; - e_mempool_destroy(pool); - - return ret; -} - -static int camel_maildir_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMaildirSummary *maildirs = (CamelMaildirSummary *)cls; - char *filename = g_strdup_printf("%s/cur/%s", cls->folder_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 (cls->index && (forceindex || !ibex_contains_name(cls->index, (char *)name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, cls->index); - } else { - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - } - maildirs->priv->current_file = (char *)name; - camel_folder_summary_add_from_parser((CamelFolderSummary *)maildirs, mp); - camel_object_unref((CamelObject *)mp); - maildirs->priv->current_file = NULL; - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - g_free(filename); - return 0; -} - -static void -remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) -{ - d(printf("removing message %s from summary\n", key)); - if (cls->index) - ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); -} - -static int -sort_receive_cmp(const void *ap, const void *bp) -{ - const CamelMessageInfo - *a = *((CamelMessageInfo **)ap), - *b = *((CamelMessageInfo **)bp); - - if (a->date_received < b->date_received) - return -1; - else if (a->date_received > b->date_received) - return 1; - - return 0; -} - -static int -maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - GHashTable *left; - int i, count; - int forceindex; - char *new, *cur; - char *uid; - - new = g_strdup_printf("%s/new", cls->folder_path); - cur = g_strdup_printf("%s/cur", cls->folder_path); - - /* FIXME: Handle changeinfo */ - - 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(cur); - if (dir == NULL) { - camel_exception_setv(ex, 1, _("Cannot open maildir directory path: %s: %s"), cls->folder_path, strerror(errno)); - g_free(cur); - g_free(new); - 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 *)cls); - forceindex = count == 0; - for (i=0;i<count;i++) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - if (info) { - g_hash_table_insert(left, (char *)camel_message_info_uid(info), info); - } - } - - while ( (d = readdir(dir)) ) { - /* FIXME: also run stat to check for regular file */ - p = d->d_name; - if (p[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) - uid = g_strndup(d->d_name, uid-d->d_name); - else - uid = g_strdup(d->d_name); - - info = camel_folder_summary_uid((CamelFolderSummary *)cls, uid); - if (info == NULL || (cls->index && (!ibex_contains_name(cls->index, uid)))) { - /* need to add this file to the summary */ - if (info != NULL) { - CamelMessageInfo *old = g_hash_table_lookup(left, camel_message_info_uid(info)); - if (old) { - g_hash_table_remove(left, uid); - camel_folder_summary_info_free((CamelFolderSummary *)cls, old); - } - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - camel_maildir_summary_add(cls, d->d_name, forceindex); - } else { - const char *filename; - CamelMessageInfo *old; - - old = g_hash_table_lookup(left, camel_message_info_uid(info)); - if (old) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, old); - g_hash_table_remove(left, camel_message_info_uid(info)); - } - - mdi = (CamelMaildirMessageInfo *)info; - filename = camel_maildir_info_filename(mdi); - /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ - if (filename == NULL || strcmp(filename, d->d_name) != 0) { -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name, FALSE); -# else - g_free(mdi->filename); - mdi->filename = g_strdup(d->d_name); -# endif -#endif - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - g_free(uid); - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, cls); - g_hash_table_destroy(left); - - /* now, scan new for new messages, and copy them to cur, and so forth */ - dir = opendir(new); - if (dir != NULL) { - while ( (d = readdir(dir)) ) { - char *name, *newname, *destname, *destfilename; - char *src, *dest; - - name = d->d_name; - if (name[0] == '.') - continue; - - /* already in summary? shouldn't happen, but just incase ... */ - if ((info = camel_folder_summary_uid((CamelFolderSummary *)cls, name))) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - newname = destname = camel_folder_summary_next_uid_string(s); - } else { - newname = NULL; - destname = name; - } - - /* copy this to the destination folder, use 'standard' semantics for maildir info field */ - src = g_strdup_printf("%s/%s", new, name); - destfilename = g_strdup_printf("%s:2,", destname); - dest = g_strdup_printf("%s/%s", cur, destfilename); - - /* FIXME: This should probably use link/unlink */ - - if (rename(src, dest) == 0) { - camel_maildir_summary_add(cls, destfilename, forceindex); - if (changes) { - camel_folder_change_info_add_uid(changes, destname); - camel_folder_change_info_recent_uid(changes, destname); - } - } else { - /* else? we should probably care about failures, but wont */ - g_warning("Failed to move new maildir message %s to cur %s", src, dest); - } - - /* c strings are painful to work with ... */ - g_free(destfilename); - g_free(newname); - g_free(src); - g_free(dest); - } - } - closedir(dir); - - g_free(new); - g_free(cur); - - /* sort the summary based on receive time, since the directory order is not useful */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - return 0; -} - -/* sync the summary with the ondisk files. */ -static int -maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; -#ifdef DOESTRV - CamelFolderSummary *s = (CamelFolderSummary *)cls; -#endif - char *name; - struct stat st; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - mdi = (CamelMaildirMessageInfo *)info; - if (info && (info->flags & CAMEL_MESSAGE_DELETED) && expunge) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); - - camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - } - g_free(name); - } else if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - char *newname = camel_maildir_summary_info_to_name(info); - char *dest; - - /* do we care about additional metainfo stored inside the message? */ - /* probably should all go in the filename? */ - - /* have our flags/ i.e. name changed? */ - if (strcmp(newname, camel_maildir_info_filename(mdi))) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - dest = g_strdup_printf("%s/cur/%s", cls->folder_path, newname); - rename(name, dest); - if (stat(dest, &st) == -1) { - /* we'll assume it didn't work, but dont change anything else */ - g_free(newname); - } else { - /* TODO: If this is made mt-safe, then this code could be a problem, since - the estrv is being modified. - Sigh, this may mean the maildir name has to be cached another way */ -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref_free(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname, TRUE); -# else - g_free(mdi->filename); - mdi->filename = newname; -# endif -#endif - } - g_free(name); - g_free(dest); - } else { - g_free(newname); - } - - /* strip FOLDER_MESSAGE_FLAGED, etc */ - info->flags &= 0xffff; - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} - diff --git a/camel/providers/local/camel-maildir-summary.h b/camel/providers/local/camel-maildir-summary.h deleted file mode 100644 index 5362795ab2..0000000000 --- a/camel/providers/local/camel-maildir-summary.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2000 Ximian 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_SUMMARY_H -#define _CAMEL_MAILDIR_SUMMARY_H - -#include "camel-local-summary.h" -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <libibex/ibex.h> - -#define CAMEL_MAILDIR_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_maildir_summary_get_type (), CamelMaildirSummary) -#define CAMEL_MAILDIR_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_maildir_summary_get_type (), CamelMaildirSummaryClass) -#define CAMEL_IS_MAILDIR_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_maildir_summary_get_type ()) - -typedef struct _CamelMaildirSummary CamelMaildirSummary; -typedef struct _CamelMaildirSummaryClass CamelMaildirSummaryClass; - -typedef struct _CamelMaildirMessageContentInfo { - CamelMessageContentInfo info; -} CamelMaildirMessageContentInfo; - -#if defined (DOEPOOLV) || defined (DOESTRV) -enum { - CAMEL_MAILDIR_INFO_FILENAME = CAMEL_MESSAGE_INFO_LAST, - CAMEL_MAILDIR_INFO_LAST, -}; -#endif - -typedef struct _CamelMaildirMessageInfo { - CamelMessageInfo info; - -#if !defined (DOEPOOLV) && !defined (DOESTRV) - char *filename; /* maildir has this annoying status shit on the end of the filename, use this to get the real message id */ -#endif -} CamelMaildirMessageInfo; - -struct _CamelMaildirSummary { - CamelLocalSummary parent; - struct _CamelMaildirSummaryPrivate *priv; -}; - -struct _CamelMaildirSummaryClass { - CamelLocalSummaryClass parent_class; - - /* virtual methods */ - - /* signals */ -}; - -CamelType camel_maildir_summary_get_type (void); -CamelMaildirSummary *camel_maildir_summary_new (const char *filename, const char *maildirdir, ibex *index); - -/* convert some info->flags to/from the messageinfo */ -char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info); -int camel_maildir_summary_name_to_info(CamelMessageInfo *info, const char *name); - -#if defined (DOEPOOLV) || defined (DOESTRV) -#define camel_maildir_info_filename(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME) -#define camel_maildir_info_set_filename(x, s) camel_message_info_set_string((CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME, s) -#else -#define camel_maildir_info_filename(x) (((CamelMaildirMessageInfo *)x)->filename) -#define camel_maildir_info_set_filename(x, s) (g_free(((CamelMaildirMessageInfo *)x)->filename),((CamelMaildirMessageInfo *)x)->filename = s) -#endif - -#endif /* ! _CAMEL_MAILDIR_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c deleted file mode 100644 index c2b98c9aa3..0000000000 --- a/camel/providers/local/camel-mbox-folder.c +++ /dev/null @@ -1,449 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2000 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *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 int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void mbox_unlock(CamelLocalFolder *lf); - -static void mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); -static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); - -static void mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex); -static CamelMimeMessage *mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); -static CamelLocalSummary *mbox_create_summary(const char *path, const char *folder, ibex *index); - -static void mbox_finalise(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); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mbox_folder_class; - - parent_class = (CamelLocalFolderClass *)camel_type_get_global_classfuncs(camel_local_folder_get_type()); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mbox_append_message; - camel_folder_class->get_message = mbox_get_message; - - camel_folder_class->set_message_user_flag = mbox_set_message_user_flag; - camel_folder_class->set_message_user_tag = mbox_set_message_user_tag; - - lclass->create_summary = mbox_create_summary; - lclass->lock = mbox_lock; - lclass->unlock = mbox_unlock; -} - -static void -mbox_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object;*/ - CamelMboxFolder *mbox_folder = object; - - mbox_folder->lockfd = -1; -} - -static void -mbox_finalise(CamelObject * object) -{ - CamelMboxFolder *mbox_folder = (CamelMboxFolder *)object; - - g_assert(mbox_folder->lockfd == -1); -} - -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_LOCAL_FOLDER_TYPE, "CamelMboxFolder", - sizeof(CamelMboxFolder), - sizeof(CamelMboxFolderClass), - (CamelObjectClassInitFunc) camel_mbox_folder_class_init, - NULL, - (CamelObjectInitFunc) mbox_init, - (CamelObjectFinalizeFunc) mbox_finalise); - } - - return camel_mbox_folder_type; -} - -CamelFolder * -camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating mbox folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_MBOX_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -static CamelLocalSummary *mbox_create_summary(const char *path, const char *folder, ibex *index) -{ - return (CamelLocalSummary *)camel_mbox_summary_new(path, folder, index); -} - -static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - /* make sure we have matching unlocks for locks, camel-local-folder class should enforce this */ - g_assert(mf->lockfd == -1); - - mf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (mf->lockfd == -1) { - camel_exception_setv(ex, 1, _("Cannot create folder lock on %s: %s"), lf->folder_path, strerror(errno)); - return -1; - } - - if (camel_lock_folder(lf->folder_path, mf->lockfd, type, ex) == -1) { - close(mf->lockfd); - mf->lockfd = -1; - return -1; - } - - return 0; -} - -static void mbox_unlock(CamelLocalFolder *lf) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - g_assert(mf->lockfd != -1); - camel_unlock_folder(lf->folder_path, mf->lockfd); - close(mf->lockfd); - mf->lockfd = -1; -} - -static void -mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream = NULL, *filter_stream = NULL; - CamelMimeFilter *filter_from = NULL; - CamelMboxSummary *mbs = (CamelMboxSummary *)folder->summary; - CamelMessageInfo *mi; - char *fromline = NULL; - int fd, retval; - struct stat st; -#if 0 - char *xev; -#endif - /* If we can't lock, dont do anything */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - d(printf("Appending message\n")); - - /* first, check the summary is correct (updates folder_size too) */ - retval = camel_local_summary_check ((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval == -1) - goto fail; - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (mi == NULL) - goto fail; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY|O_APPEND, 0600); - if (output_stream == NULL) { - camel_exception_setv(ex, 1, _("Cannot open mailbox: %s: %s\n"), lf->folder_path, strerror(errno)); - goto fail; - } - - /* and we need to set the frompos/XEV explicitly */ - ((CamelMboxMessageInfo *)mi)->frompos = mbs->folder_size?mbs->folder_size+1:0; -#if 0 - xev = camel_local_summary_encode_x_evolution((CamelLocalSummary *)folder->summary, mi); - if (xev) { - /* the x-ev header should match the 'current' flags, no problem, so store as much */ - camel_medium_set_header((CamelMedium *)message, "X-Evolution", xev); - mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED; - g_free(xev); - } -#endif - - /* we must write this to the non-filtered stream ... prepend a \n if not at the start of the file */ - fromline = camel_mbox_summary_build_from(((CamelMimePart *)message)->headers); - if (camel_stream_printf(output_stream, mbs->folder_size==0?"%s":"\n%s", fromline) == -1) - goto fail_write; - - /* 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((CamelDataWrapper *)message, filter_stream) == -1) - goto fail_write; - - if (camel_stream_close(filter_stream) == -1) - goto fail_write; - - /* unlock as soon as we can */ - camel_local_folder_unlock(lf); - - /* filter stream ref's the output stream itself, so we need to unref it too */ - camel_object_unref((CamelObject *)filter_from); - camel_object_unref((CamelObject *)filter_stream); - camel_object_unref((CamelObject *)output_stream); - g_free(fromline); - - /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ - /* the stat really shouldn't fail, we just wrote to it */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return; - -fail_write: - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Mail append cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mbox file: %s: %s"), - lf->folder_path, g_strerror (errno)); - - if (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); - - /* reset the file to original size */ - fd = open(lf->folder_path, O_WRONLY, 0600); - if (fd != -1) { - ftruncate(fd, mbs->folder_size); - close(fd); - } - - /* remove the summary info so we are not out-of-sync with the mbox */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (mbs), camel_message_info_uid (mi)); - - /* and tell the summary its uptodate */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - -fail: - /* make sure we unlock the folder - before we start triggering events into appland */ - camel_local_folder_unlock(lf); - - /* cascade the changes through, anyway, if there are any outstanding */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static CamelMimeMessage * -mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelMimeMessage *message; - CamelMboxMessageInfo *info; - CamelMimeParser *parser; - int fd, retval; - int retried = FALSE; - - d(printf("Getting message %s\n", uid)); - - /* lock the folder first, burn if we can't */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_READ, ex) == -1) - return NULL; - -retry: - /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid(folder->summary, uid); - - if (info == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), uid, _("No such message")); - camel_local_folder_unlock(lf); - return NULL; - } - - /* no frompos, its an error in the library (and we can't do anything with it */ - g_assert(info->frompos != -1); - - /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache - the whole message in memory if the stream is non-seekable (which it is when built from a parser - with no stream). This means we dont have to lock the mbox for the life of the message, but only - while it is being created. */ - - fd = open(lf->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - strerror(errno)); - camel_local_folder_unlock(lf); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - return NULL; - } - - /* 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_fd(parser, fd); - camel_mime_parser_scan_from(parser, TRUE); - - camel_mime_parser_seek(parser, info->frompos, SEEK_SET); - if (camel_mime_parser_step(parser, NULL, NULL) != HSCAN_FROM - || camel_mime_parser_tell_start_from(parser) != info->frompos) { - - g_warning("Summary doesn't match the folder contents! eek!\n" - " expecting offset %ld got %ld, state = %d", (long int)info->frompos, - (long int)camel_mime_parser_tell_start_from(parser), - camel_mime_parser_state(parser)); - - camel_object_unref((CamelObject *)parser); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - - if (!retried) { - retried = TRUE; - retval = camel_local_summary_check ((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval != -1) - goto retry; - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("The folder appears to be irrecoverably corrupted.")); - - camel_local_folder_unlock(lf); - return NULL; - } - - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - - message = camel_mime_message_new(); - if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) { - camel_exception_setv(ex, errno==EINTR?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("Message construction failed: Corrupt mailbox?")); - camel_object_unref((CamelObject *)parser); - camel_object_unref((CamelObject *)message); - camel_local_folder_unlock(lf); - return NULL; - } - - camel_medium_remove_header((CamelMedium *)message, "X-Evolution"); - - /* and unlock now we're finished with it */ - camel_local_folder_unlock(lf); - - camel_object_unref((CamelObject *)parser); - - /* use the opportunity to notify of changes (particularly if we had a rebuild) */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return message; -} - -static void -mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - g_return_if_fail(info != NULL); - - if (camel_flag_set(&info->user_flags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} - -static void -mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - g_return_if_fail(info != NULL); - - if (camel_tag_set(&info->user_tags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} diff --git a/camel/providers/local/camel-mbox-folder.h b/camel/providers/local/camel-mbox-folder.h deleted file mode 100644 index aa0b67201f..0000000000 --- a/camel/providers/local/camel-mbox-folder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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-local-folder.h" -#include "camel-mbox-summary.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 { - CamelLocalFolder parent_object; - - int lockfd; /* for when we have a lock on the folder */ -} CamelMboxFolder; - -typedef struct { - CamelLocalFolderClass 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 */ diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c deleted file mode 100644 index f401632b8d..0000000000 --- a/camel/providers/local/camel-mbox-store.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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" - -static CamelLocalStoreClass *parent_class = NULL; - -/* 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 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 -camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_mbox_store_class); - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload */ - camel_store_class->get_folder = get_folder; - camel_store_class->delete_folder = delete_folder; -} - -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_LOCAL_STORE_TYPE, "CamelMboxStore", - sizeof (CamelMboxStore), - sizeof (CamelMboxStoreClass), - (CamelObjectClassInitFunc) camel_mbox_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mbox_store_type; -} - -static CamelFolder * -get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - char *name; - struct stat st; - - (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); - if (camel_exception_is_set(ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, 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; - struct stat st; - - name = g_strdup_printf ("%s%s", CAMEL_LOCAL_STORE (store)->toplevel_dir, folder_name); - if (stat (name, &st) == -1) { - 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; - } - - if (unlink(name) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - name, g_strerror (errno)); - g_free(name); - return; - } - - g_free(name); - - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); -} diff --git a/camel/providers/local/camel-mbox-store.h b/camel/providers/local/camel-mbox-store.h deleted file mode 100644 index 5b6fbdd926..0000000000 --- a/camel/providers/local/camel-mbox-store.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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-local-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 { - CamelLocalStore parent_object; - -} CamelMboxStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMboxStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mbox_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MBOX_STORE_H */ - - diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c deleted file mode 100644 index 697e806e53..0000000000 --- a/camel/providers/local/camel-mbox-summary.c +++ /dev/null @@ -1,884 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-mbox-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" - -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-mbox-summary.h" -#include "camel/camel-file-utils.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(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 int mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -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 CamelLocalSummaryClass *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_local_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; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass; - - camel_mbox_summary_parent = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_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;*/ - - lklass->check = mbox_summary_check; - lklass->sync = mbox_summary_sync; -} - -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);*/ -} - -/** - * 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 = (CamelMboxSummary *)camel_object_new(camel_mbox_summary_get_type()); - - camel_local_summary_construct((CamelLocalSummary *)new, filename, mbox_name, 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_file_util_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_file_util_encode_uint32(out, mbs->folder_size); -} - -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) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - mbi->frompos = -1; - } - - return mi; -} - -static CamelMessageInfo * -message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) -{ - CamelMessageInfo *mi; - - 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); - } - - 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) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1) - goto error; - } - - return mi; -error: - camel_folder_summary_info_free(s, mi); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) -{ - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - io(printf("saving mbox message info\n")); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_save(s, out, mi) == -1 - || camel_file_util_encode_off_t(out, mbi->frompos) == -1) - return -1; - - return 0; -} - -static int -summary_rebuild(CamelMboxSummary *mbs, off_t offset, CamelException *ex) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)mbs; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp; - int fd; - int ok = 0; - struct stat st; - off_t size = 0; - - /* FIXME: If there is a failure, it shouldn't clear the summary and restart, - it should try and merge the summary info's. This is a bit tricky. */ - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - d(printf("%s failed to open: %s\n", cls->folder_path, strerror(errno))); - camel_exception_setv(ex, 1, _("Could not open folder: %s: %s"), - cls->folder_path, strerror(errno)); - camel_operation_end(NULL); - return -1; - } - - if (fstat(fd, &st) == 0) - size = st.st_size; - - 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, building summary from start"); - camel_mime_parser_drop_step(mp); - offset = 0; - camel_mime_parser_seek(mp, offset, SEEK_SET); - camel_folder_summary_clear(s); - } else { - camel_mime_parser_unstep(mp); - } - } else { - d(printf("mime parser state ran out? state is %d\n", camel_mime_parser_state(mp))); - camel_object_unref(CAMEL_OBJECT(mp)); - /* end of file - no content? no error either */ - camel_operation_end(NULL); - return 0; - } - } - - while (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) { - CamelMessageInfo *info; - off_t pc = camel_mime_parser_tell_start_from (mp) + 1; - - camel_operation_progress (NULL, (int) (((float) pc / size) * 100)); - - info = camel_folder_summary_add_from_parser(s, mp); - if (info == NULL) { - camel_exception_setv(ex, 1, _("Fatal mail parser error near position %ld in folder %s"), - camel_mime_parser_tell(mp), cls->folder_path); - 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) { - if (stat(cls->folder_path, &st) == 0) { - camel_folder_summary_touch(s); - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - } - } - - camel_operation_end(NULL); - - return ok; -} - -/* like summary_rebuild, but also do changeinfo stuff (if supplied) */ -static int -summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret, i, count; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - - d(printf("Calling summary update, from pos %d\n", (int)offset)); - - if (changeinfo) { - /* 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, camel_message_info_uid(mi)); - camel_folder_summary_info_free(s, mi); - } - } - - /* do the actual work */ - cls->index_force = FALSE; - ret = summary_rebuild(mbs, offset, ex); - - if (changeinfo) { - 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, camel_message_info_uid(mi)); - camel_folder_summary_info_free(s, mi); - } - camel_folder_change_info_build_diff(changeinfo); - } - - return ret; -} - -static int -mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct stat st; - int ret = 0; - - d(printf("Checking summary\n")); - - /* check if the summary is up-to-date */ - if (stat(cls->folder_path, &st) == -1) { - camel_folder_summary_clear(s); - camel_exception_setv(ex, 1, _("Cannot check folder: %s: %s"), cls->folder_path, strerror(errno)); - return -1; - } - - if (st.st_size == 0) { - /* empty? No need to scan at all */ - d(printf("Empty mbox, clearing summary\n")); - camel_folder_summary_clear(s); - ret = 0; - } else if (s->messages->len == 0) { - /* if we are empty, then we rebuilt from scratch */ - d(printf("Empty summary, rebuilding from start\n")); - ret = summary_update(cls, 0, changes, ex); - } else { - /* is the summary uptodate? */ - if (st.st_size != mbs->folder_size || st.st_mtime != s->time) { - if (mbs->folder_size < st.st_size) { - /* this will automatically rescan from 0 if there is a problem */ - d(printf("folder grew, attempting to rebuild from %d\n", mbs->folder_size)); - ret = summary_update(cls, mbs->folder_size, changes, ex); - } else { - d(printf("folder shrank! rebuilding from start\n")); - camel_folder_summary_clear(s); - ret = summary_update(cls, 0, changes, ex); - } - } - } - - /* FIXME: move upstream? */ - - if (ret != -1) { - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - camel_folder_summary_touch(s); - } - } - - return ret; -} - -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; -} - -/* perform a full sync */ -static int -mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - int fd = -1, fdout = -1; - char *tmpname = NULL; - char *buffer, *xevnew = NULL; - int len; - const char *fromline; - int lastdel = FALSE; - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, strerror(errno)); - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - tmpname = alloca(strlen (cls->folder_path) + 5); - sprintf(tmpname, "%s.tmp", cls->folder_path); - d(printf("Writing tmp file to %s\n", tmpname)); - fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fdout == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), strerror(errno)); - goto error; - } - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int pc = (i + 1) * 100 / count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Looking at message %s\n", camel_message_info_uid(info))); - - /* only need to seek past deleted messages, otherwise we should be at the right spot/state already */ - if (lastdel) { - d(printf("seeking to %d\n", (int)info->frompos)); - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - } - - if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - lastdel = FALSE; - if (expunge && info->info.flags & CAMEL_MESSAGE_DELETED) { - const char *uid = camel_message_info_uid(info); - - d(printf("Deleting %s\n", uid)); - - if (cls->index) - ibex_unindex(cls->index, (char *)uid); - - /* remove it from the change list */ - camel_folder_change_info_remove_uid(changeinfo, uid); - camel_folder_summary_remove(s, (CamelMessageInfo *)info); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - count--; - i--; - info = NULL; - lastdel = TRUE; - } else { - /* otherwise, the message is staying, copy its From_ line across */ - if (i>0) { - write(fdout, "\n", 1); - } - info->frompos = lseek(fdout, 0, SEEK_CUR); - fromline = camel_mime_parser_from_line(mp); - write(fdout, fromline, strlen(fromline)); - } - - if (info && info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) { - d(printf("Updating header for %s flags = %08x\n", camel_message_info_uid(info), info->info.flags)); - - if (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xevnew = camel_local_summary_encode_x_evolution(cls, (CamelMessageInfo *)info); - if (camel_local_summary_write_headers(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; - } - info->info.flags &= 0xffff; - g_free(xevnew); - xevnew = NULL; - camel_mime_parser_drop_step(mp); - } - - camel_mime_parser_drop_step(mp); - if (info) { - d(printf("looking for message content to copy across from %d\n", (int)camel_mime_parser_tell(mp))); - while (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_PRE_FROM) { - /*d(printf("copying mbox contents to tmp: '%.*s'\n", len, buffer));*/ - if (write(fdout, buffer, len) != len) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Writing to tmp mailbox failed: %s: %s"), - cls->folder_path, strerror(errno)); - goto error; - } - } - d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp), - (int)camel_mime_parser_tell_start_from(mp))); - camel_mime_parser_unstep(mp); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - } - } - - 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"), - cls->folder_path, strerror(errno)); - fd = -1; - goto error; - } - - 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)); - fdout = -1; - goto error; - } - - /* this should probably either use unlink/link/unlink, or recopy over - the original mailbox, for various locking reasons/etc */ - if (rename(tmpname, cls->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; - - camel_object_unref((CamelObject *)mp); - camel_operation_end(NULL); - - 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((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -/* perform a quick sync - only system flags have changed */ -static int -mbox_summary_sync_quick(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - int fd = -1; - char *xevnew, *xevtmp; - const char *xev; - int len; - off_t lastpos; - - d(printf("Performing quick summary sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, strerror(errno)); - - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int xevoffset; - int pc = (i+1)*100/count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags)); - - if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - continue; - } - - d(printf("Updating message %s\n", camel_message_info_uid(info))); - - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - - if (camel_mime_parser_step(mp, 0, 0) != HSCAN_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_step(mp, 0, 0) == HSCAN_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - if (xev == NULL || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1) { - g_warning("We're supposed to have a valid x-ev header, but we dont"); - goto error; - } - xevnew = camel_local_summary_encode_x_evolution(cls, (CamelMessageInfo *)info); - /* SIGH: encode_param_list is about the only function which folds headers by itself. - This should be fixed somehow differently (either parser doesn't fold headers, - or param_list doesn't, or something */ - xevtmp = header_unfold(xevnew); - /* the raw header contains a leading ' ', so (dis)count that too */ - if (strlen(xev)-1 != strlen(xevtmp)) { - g_free(xevnew); - g_free(xevtmp); - g_warning("Hmm, the xev headers shouldn't have changed size, but they did"); - goto error; - } - g_free(xevtmp); - - /* we write out the xevnew string, assuming its been folded identically to the original too! */ - - lastpos = lseek(fd, 0, SEEK_CUR); - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - lseek(fd, lastpos, SEEK_SET); - g_free(xevnew); - - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - - info->info.flags &= 0xffff; - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - } - - 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"), - cls->folder_path, strerror(errno)); - fd = -1; - goto error; - } - - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -static int -mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - struct stat st; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - int i, count; - int quick = TRUE, work=FALSE; - int ret; - - /* first, sync ourselves up, just to make sure */ - if (camel_local_summary_check(cls, changeinfo, ex) == -1) - return -1; - - count = camel_folder_summary_count(s); - if (count == 0) - return 0; - - /* check what work we have to do, if any */ - for (i=0;quick && i<count; i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - g_assert(info); - if ((expunge && (info->flags & CAMEL_MESSAGE_DELETED)) || - (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE))) - quick = FALSE; - else - work |= (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; - camel_folder_summary_info_free(s, info); - } - - /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */ - ret = -1; - if (quick) { - if (work) { - ret = mbox_summary_sync_quick(cls, expunge, changeinfo, ex); - if (ret == -1) { - g_warning("failed a quick-sync, trying a full sync"); - camel_exception_clear(ex); - } - } else { - ret = 0; - } - } - - if (ret == -1) - ret = mbox_summary_sync_full(cls, expunge, changeinfo, ex); - if (ret == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unknown error: %s"), strerror(errno)); - return -1; - } - - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - s->time = st.st_mtime; - mbs->folder_size = st.st_size; - camel_folder_summary_touch(s); - } - - return ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->sync(cls, expunge, changeinfo, ex); -} diff --git a/camel/providers/local/camel-mbox-summary.h b/camel/providers/local/camel-mbox-summary.h deleted file mode 100644 index 82d200c854..0000000000 --- a/camel/providers/local/camel-mbox-summary.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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-local-summary.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; - -typedef struct _CamelMboxMessageContentInfo { - CamelMessageContentInfo info; -} CamelMboxMessageContentInfo; - -typedef struct _CamelMboxMessageInfo { - CamelMessageInfo info; - - off_t frompos; -} CamelMboxMessageInfo; - -struct _CamelMboxSummary { - CamelLocalSummary parent; - - struct _CamelMboxSummaryPrivate *priv; - - size_t folder_size; /* size of the mbox file, last sync */ -}; - -struct _CamelMboxSummaryClass { - CamelLocalSummaryClass parent_class; -}; - -guint camel_mbox_summary_get_type (void); -CamelMboxSummary *camel_mbox_summary_new (const char *filename, const char *mbox_name, ibex *index); - -/* generate a From line from headers */ -char *camel_mbox_summary_build_from(struct _header_raw *header); - -#endif /* ! _CAMEL_MBOX_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c deleted file mode 100644 index 6795ab3fbf..0000000000 --- a/camel/providers/local/camel-mh-folder.c +++ /dev/null @@ -1,227 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2000 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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-exception.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *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 CamelLocalSummary *mh_create_summary(const char *path, const char *folder, ibex *index); - -static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, CamelException * ex); -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -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); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mh_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mh_append_message; - camel_folder_class->get_message = mh_get_message; - - lclass->create_summary = mh_create_summary; -} - -static void mh_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMhFolder *mh_folder = object;*/ -} - -static void mh_finalize(CamelObject * object) -{ - /*CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(object);*/ -} - -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_LOCAL_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; - - d(printf("Creating mh folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MH_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -static CamelLocalSummary *mh_create_summary(const char *path, const char *folder, ibex *index) -{ - return (CamelLocalSummary *)camel_mh_summary_new(path, folder, index); -} - -static void -mh_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex) -{ - CamelMhFolder *mh_folder = (CamelMhFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - char *name; - - /* FIXME: probably needs additional locking (although mh doesn't appear do do it) */ - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - /* write it out, use the uid we got from the summary */ - name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* close this? */ - camel_object_unref (CAMEL_OBJECT (output_stream)); - - g_free(name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)mh_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)mh_folder)->changes); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("MH append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mh folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); -} - -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); - return NULL; - } - - /* we only need it to check the message exists */ - camel_folder_summary_info_free(folder->summary, info); - - name = g_strdup_printf("%s/%s", lf->folder_path, uid); - if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), - name, g_strerror(errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), - name, _("Invalid message contents")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-mh-folder.h b/camel/providers/local/camel-mh-folder.h deleted file mode 100644 index 125f8c8ac5..0000000000 --- a/camel/providers/local/camel-mh-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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-local-folder.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 { - CamelLocalFolder parent_object; - -} CamelMhFolder; - -typedef struct { - CamelLocalFolderClass 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 */ diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c deleted file mode 100644 index 8b8c2e5f0e..0000000000 --- a/camel/providers/local/camel-mh-store.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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" - -static CamelLocalStoreClass *parent_class = NULL; - -/* 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 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 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);*/ - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_store_class->get_folder = get_folder; - camel_store_class->delete_folder = delete_folder; -} - -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_LOCAL_STORE_TYPE, "CamelMhStore", - sizeof(CamelMhStore), - sizeof(CamelMhStoreClass), - (CamelObjectClassInitFunc) camel_mh_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mh_store_type; -} - -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name; - struct stat st; - - (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); - if (camel_exception_is_set(ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, 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; - } - 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; - } - } 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; - - /* remove folder directory - will fail if not empty */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - if (rmdir(name) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, strerror(errno)); - g_free(name); - return; - } - g_free(name); - - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); -} diff --git a/camel/providers/local/camel-mh-store.h b/camel/providers/local/camel-mh-store.h deleted file mode 100644 index b69bddb7c2..0000000000 --- a/camel/providers/local/camel-mh-store.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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-local-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 { - CamelLocalStore parent_object; - -} CamelMhStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMhStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mh_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MH_STORE_H */ diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c deleted file mode 100644 index 06c5715d0d..0000000000 --- a/camel/providers/local/camel-mh-summary.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2000 Ximian 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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> - -#include "camel-mh-summary.h" -#include <camel/camel-mime-message.h> - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MH_SUMMARY_VERSION (0x2000) - -static int mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -/*static int mh_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);*/ - -static char *mh_summary_next_uid_string(CamelFolderSummary *s); - -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 CamelLocalSummaryClass *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_local_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; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->next_uid_string = mh_summary_next_uid_string; - - lklass->check = mh_summary_check; - lklass->sync = mh_summary_sync; - /*lklass->add = mh_summary_add;*/ -} - -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->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_local_summary_construct((CamelLocalSummary *)o, filename, mhdir, index); - return o; -} - -static char *mh_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMhSummary *mhs = (CamelMhSummary *)s; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - int fd = -1; - guint32 uid; - char *name; - - /* if we are working to add an existing file, then use current_uid */ - if (mhs->priv->current_uid) - return g_strdup(mhs->priv->current_uid); - - /* else scan for one - and create it too, to make sure */ - do { - close(fd); - uid = camel_folder_summary_next_uid(s); - name = g_strdup_printf("%s/%u", cls->folder_path, uid); - /* O_EXCL isn't guaranteed, sigh. Oh well, bad luck, mh has problems anyway */ - fd = open(name, O_WRONLY|O_CREAT|O_EXCL, 0600); - g_free(name); - } while (fd == -1 && errno == EEXIST); - - close(fd); - - return g_strdup_printf("%u", uid); -} - -static int camel_mh_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMhSummary *mhs = (CamelMhSummary *)cls; - char *filename = g_strdup_printf("%s/%s", cls->folder_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 (cls->index && (forceindex || !ibex_contains_name(cls->index, (char *)name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)mhs, cls->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, CamelLocalSummary *cls) -{ - d(printf("removing message %s from summary\n", key)); - if (cls->index) - ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); -} - -static int -mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p, c; - CamelMessageInfo *info; - GHashTable *left; - int i, count; - int forceindex; - - /* FIXME: Handle changeinfo */ - - 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(cls->folder_path); - if (dir == NULL) { - camel_exception_setv(ex, 1, _("Cannot open MH directory path: %s: %s"), cls->folder_path, strerror(errno)); - 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 *)cls); - forceindex = count == 0; - for (i=0;i<count;i++) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - if (info) { - g_hash_table_insert(left, (char *)camel_message_info_uid(info), 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 *)cls, d->d_name); - if (info == NULL || (cls->index && (!ibex_contains_name(cls->index, d->d_name)))) { - /* need to add this file to the summary */ - if (info != NULL) { - g_hash_table_remove(left, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - camel_mh_summary_add(cls, d->d_name, forceindex); - } else { - const char *uid = camel_message_info_uid(info); - CamelMessageInfo *old = g_hash_table_lookup(left, uid); - - if (old) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, old); - g_hash_table_remove(left, uid); - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - } - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, cls); - g_hash_table_destroy(left); - - return 0; -} - -static int -mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelException *ex) -{ - CamelMimeParser *mp; - const char *xev, *buffer; - int xevoffset; - int fd, outfd, len, outlen, ret=0; - char *name, *tmpname, *xevnew; - - name = g_strdup_printf("%s/%s", cls->folder_path, camel_message_info_uid(info)); - fd = open(name, O_RDWR); - if (fd == -1) - return -1; - - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(mp, fd); - if (camel_mime_parser_step(mp, 0, 0) != HSCAN_EOF) { - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - d(printf("xev = '%s'\n", xev)); - xevnew = camel_local_summary_encode_x_evolution(cls, info); - if (xev == NULL - || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1 - || strlen(xev)-1 != strlen(xevnew)) { - - d(printf("camel local summary_decode_xev = %d\n", camel_local_summary_decode_x_evolution(cls, xev, NULL))); - - /* need to write a new copy/unlink old */ - tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), camel_message_info_uid(info)); - d(printf("old xev was %d %s new xev is %d %s\n", strlen(xev), xev, strlen(xevnew), xevnew)); - d(printf("creating new message %s\n", tmpname)); - outfd = open(tmpname, O_CREAT|O_WRONLY|O_TRUNC, 0600); - if (outfd != -1) { - outlen = 0; - len = camel_local_summary_write_headers(outfd, camel_mime_parser_headers_raw(mp), xevnew); - if (len != -1) { - while (outlen != -1 && (len = camel_mime_parser_read(mp, &buffer, 10240)) > 0) { - d(printf("camel mime parser read, read %d bytes: %.*s\n", len, len, buffer)); - do { - outlen = write(outfd, buffer, len); - } while (outlen == -1 && errno == EINTR); - } - } - - d(printf("len = %d outlen = %d, renaming/finishing\n", len, outlen)); - if (close(outfd) == -1 - || len == -1 - || outlen == -1 - || rename(tmpname, name) == -1) { - unlink(tmpname); - ret = -1; - } - } else { - g_warning("sync can't create tmp file: %s", strerror(errno)); - } - g_free(tmpname); - } else { - d(printf("stamping in updated X-EV at %d\n", (int)xevoffset)); - /* else, we can just update the flags field */ - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - if (len == -1) - ret = -1; - } - - g_free(xevnew); - } - - camel_object_unref((CamelObject *)mp); - g_free(name); - return ret; -} - -/* sync the summary file with the ondisk files */ -static int -mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelMessageInfo *info; - char *name; - const char *uid; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - /* we could probably get away without this ... but why not use it, esp if we're going to - be doing any significant io already */ - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - g_assert(info); - if (expunge && (info->flags & CAMEL_MESSAGE_DELETED)) { - uid = camel_message_info_uid(info); - name = g_strdup_printf("%s/%s", cls->folder_path, uid); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - ibex_unindex(cls->index, (char *)uid); - - camel_folder_change_info_remove_uid(changes, uid); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - } - g_free(name); - } else if (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED)) { - if (mh_summary_sync_message(cls, info, ex) != -1) { - info->flags &= 0xffff; - } else { - g_warning("Problem occured when trying to expunge, ignored"); - } - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} diff --git a/camel/providers/local/camel-mh-summary.h b/camel/providers/local/camel-mh-summary.h deleted file mode 100644 index b24efbbfbf..0000000000 --- a/camel/providers/local/camel-mh-summary.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2000 Ximian 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_SUMMARY_H -#define _CAMEL_MH_SUMMARY_H - -#include "camel-local-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 { - CamelLocalSummary parent; - struct _CamelMhSummaryPrivate *priv; -}; - -struct _CamelMhSummaryClass { - CamelLocalSummaryClass 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); - -#endif /* ! _CAMEL_MH_SUMMARY_H */ - diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c deleted file mode 100644 index d63e760df4..0000000000 --- a/camel/providers/local/camel-spool-folder.c +++ /dev/null @@ -1,695 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#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-spool-folder.h" -#include "camel-spool-store.h" -#include "string-utils.h" -#include "camel-stream-fs.h" -#include "camel-spool-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" - -#include "camel-lock-client.h" - -#include "camel-local-private.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelFolderClass *parent_class = NULL; - -/* Returns the class for a CamelSpoolFolder */ -#define CSPOOLF_CLASS(so) CAMEL_SPOOL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CSPOOLS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int spool_lock(CamelSpoolFolder *lf, CamelLockType type, CamelException *ex); -static void spool_unlock(CamelSpoolFolder *lf); - -static void spool_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); -static void spool_expunge(CamelFolder *folder, CamelException *ex); - -static GPtrArray *spool_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void spool_search_free(CamelFolder *folder, GPtrArray * result); - -static void spool_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex); -static CamelMimeMessage *spool_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); -static void spool_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); -static void spool_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); - -static void spool_finalize(CamelObject * object); - -static void -camel_spool_folder_class_init(CamelSpoolFolderClass * camel_spool_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_spool_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 = spool_sync; - camel_folder_class->expunge = spool_expunge; - - camel_folder_class->search_by_expression = spool_search_by_expression; - camel_folder_class->search_by_uids = spool_search_by_uids; - camel_folder_class->search_free = spool_search_free; - - /* virtual method overload */ - camel_folder_class->append_message = spool_append_message; - camel_folder_class->get_message = spool_get_message; - - camel_folder_class->set_message_user_flag = spool_set_message_user_flag; - camel_folder_class->set_message_user_tag = spool_set_message_user_tag; - - camel_spool_folder_class->lock = spool_lock; - camel_spool_folder_class->unlock = spool_unlock; -} - -static void -spool_init(gpointer object, gpointer klass) -{ - CamelFolder *folder = object; - CamelSpoolFolder *spool_folder = object; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER; - - folder->summary = NULL; - spool_folder->search = NULL; - - spool_folder->priv = g_malloc0(sizeof(*spool_folder->priv)); -#ifdef ENABLE_THREADS - spool_folder->priv->search_lock = g_mutex_new(); -#endif -} - -static void -spool_finalize(CamelObject * object) -{ - CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(object); - CamelFolder *folder = (CamelFolder *)object; - - if (folder->summary) { - camel_spool_summary_sync((CamelSpoolSummary *)folder->summary, FALSE, spool_folder->changes, NULL); - camel_object_unref((CamelObject *)folder->summary); - folder->summary = NULL; - } - - if (spool_folder->search) { - camel_object_unref((CamelObject *)spool_folder->search); - } - - while (spool_folder->locked> 0) - camel_spool_folder_unlock(spool_folder); - - g_free(spool_folder->base_path); - g_free(spool_folder->folder_path); - - camel_folder_change_info_free(spool_folder->changes); - -#ifdef ENABLE_THREADS - g_mutex_free(spool_folder->priv->search_lock); -#endif - g_free(spool_folder->priv); -} - -CamelType camel_spool_folder_get_type(void) -{ - static CamelType camel_spool_folder_type = CAMEL_INVALID_TYPE; - - if (camel_spool_folder_type == CAMEL_INVALID_TYPE) { - camel_spool_folder_type = camel_type_register(CAMEL_FOLDER_TYPE, "CamelSpoolFolder", - sizeof(CamelSpoolFolder), - sizeof(CamelSpoolFolderClass), - (CamelObjectClassInitFunc) camel_spool_folder_class_init, - NULL, - (CamelObjectInitFunc) spool_init, - (CamelObjectFinalizeFunc) spool_finalize); - } - - return camel_spool_folder_type; -} - -CamelSpoolFolder * -camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelFolder *folder; - const char *root_dir_path, *name; - - folder = (CamelFolder *)lf; - - name = strrchr(full_name, '/'); - if (name) - name++; - else - name = full_name; - - camel_folder_construct(folder, parent_store, full_name, name); - - root_dir_path = camel_spool_store_get_toplevel_dir(CAMEL_SPOOL_STORE(folder->parent_store)); - - lf->base_path = g_strdup(root_dir_path); - lf->folder_path = g_strdup(root_dir_path); - - lf->changes = camel_folder_change_info_new(); - lf->flags = flags; - - folder->summary = (CamelFolderSummary *)camel_spool_summary_new(lf->folder_path); - if (camel_spool_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) { - camel_object_unref((CamelObject *)lf); - return NULL; - } - - camel_spool_summary_check((CamelSpoolSummary *)folder->summary, lf->changes, ex); - camel_spool_folder_unlock(lf); - - fi = g_malloc0(sizeof(*fi)); - fi->full_name = g_strdup(full_name); - fi->name = g_strdup(name); - fi->url = g_strdup_printf("spool:%s#%s", ((CamelService *)parent_store)->url->path, fi->name); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_folder_info_build_path(fi, '/'); - - camel_object_trigger_event(CAMEL_OBJECT(parent_store), "folder_created", fi); - camel_folder_info_free (fi); - - return lf; -} - -CamelFolder * -camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating spool folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_SPOOL_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, "INBOX") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - folder = (CamelFolder *)camel_spool_folder_construct((CamelSpoolFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -/* lock the folder, may be called repeatedly (with matching unlock calls), - with type the same or less than the first call */ -int camel_spool_folder_lock(CamelSpoolFolder *lf, CamelLockType type, CamelException *ex) -{ - if (lf->locked > 0) { - /* lets be anal here - its important the code knows what its doing */ - g_assert(lf->locktype == type || lf->locktype == CAMEL_LOCK_WRITE); - } else { - if (CSPOOLF_CLASS(lf)->lock(lf, type, ex) == -1) - return -1; - lf->locktype = type; - } - - lf->locked++; - - return 0; -} - -/* unlock folder */ -int camel_spool_folder_unlock(CamelSpoolFolder *lf) -{ - g_assert(lf->locked>0); - lf->locked--; - if (lf->locked == 0) - CSPOOLF_CLASS(lf)->unlock(lf); - - return 0; -} - -static int -spool_lock(CamelSpoolFolder *lf, CamelLockType type, CamelException *ex) -{ - int retry = 0; - - lf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (lf->lockfd == -1) { - camel_exception_setv(ex, 1, _("Cannot create folder lock on %s: %s"), lf->folder_path, strerror(errno)); - return -1; - } - - while (retry < CAMEL_LOCK_RETRY) { - if (retry > 0) - sleep(CAMEL_LOCK_DELAY); - - camel_exception_clear(ex); - - if (camel_lock_fcntl(lf->lockfd, type, ex) == 0) { - if (camel_lock_flock(lf->lockfd, type, ex) == 0) { - if ((lf->lockid = camel_lock_helper_lock(lf->folder_path, ex)) != -1) - return 0; - camel_unlock_flock(lf->lockfd); - } - camel_unlock_fcntl(lf->lockfd); - } - retry++; - } - - return -1; -} - -static void -spool_unlock(CamelSpoolFolder *lf) -{ - camel_lock_helper_unlock(lf->lockid); - lf->lockid = -1; - camel_unlock_flock(lf->lockid); - camel_unlock_fcntl(lf->lockid); - - close(lf->lockfd); - lf->lockfd = -1; -} - -static void -spool_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelSpoolFolder *lf = CAMEL_SPOOL_FOLDER(folder); - - d(printf("spool sync, expunge=%s\n", expunge?"true":"false")); - - if (camel_spool_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - /* if sync fails, we'll pass it up on exit through ex */ - camel_spool_summary_sync((CamelSpoolSummary *)folder->summary, expunge, lf->changes, ex); - camel_spool_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -spool_expunge(CamelFolder *folder, CamelException *ex) -{ - d(printf("expunge\n")); - - /* Just do a sync with expunge, serves the same purpose */ - /* call the callback directly, to avoid locking problems */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex); -} - -static GPtrArray * -spool_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(folder); - GPtrArray *summary, *matches; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - CAMEL_SPOOL_FOLDER_LOCK(folder, search_lock); - - if (spool_folder->search == NULL) - spool_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(spool_folder->search, folder); - summary = camel_folder_get_summary(folder); - camel_folder_search_set_summary(spool_folder->search, summary); - - matches = camel_folder_search_execute_expression(spool_folder->search, expression, ex); - - CAMEL_SPOOL_FOLDER_UNLOCK(folder, search_lock); - - camel_folder_free_summary(folder, summary); - - return matches; -} - -static GPtrArray * -spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(folder); - GPtrArray *summary, *matches; - int i; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - summary = g_ptr_array_new(); - for (i=0;i<uids->len;i++) { - CamelMessageInfo *info; - - info = camel_folder_get_message_info(folder, uids->pdata[i]); - if (info) - g_ptr_array_add(summary, info); - } - - if (summary->len == 0) - return summary; - - CAMEL_SPOOL_FOLDER_LOCK(folder, search_lock); - - if (spool_folder->search == NULL) - spool_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(spool_folder->search, folder); - camel_folder_search_set_summary(spool_folder->search, summary); - - matches = camel_folder_search_execute_expression(spool_folder->search, expression, ex); - - CAMEL_SPOOL_FOLDER_UNLOCK(folder, search_lock); - - for (i=0;i<summary->len;i++) - camel_folder_free_message_info(folder, summary->pdata[i]); - g_ptr_array_free(summary, TRUE); - - return matches; -} - -static void -spool_search_free(CamelFolder *folder, GPtrArray * result) -{ - CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(folder); - - /* we need to lock this free because of the way search_free_result works */ - /* FIXME: put the lock inside search_free_result */ - CAMEL_SPOOL_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result(spool_folder->search, result); - - CAMEL_SPOOL_FOLDER_UNLOCK(folder, search_lock); -} - -static void -spool_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex) -{ - CamelSpoolFolder *lf = (CamelSpoolFolder *)folder; - CamelStream *output_stream = NULL, *filter_stream = NULL; - CamelMimeFilter *filter_from = NULL; - CamelSpoolSummary *mbs = (CamelSpoolSummary *)folder->summary; - CamelMessageInfo *mi; - char *fromline = NULL; - int fd; - struct stat st; -#if 0 - char *xev; -#endif - /* If we can't lock, dont do anything */ - if (camel_spool_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - d(printf("Appending message\n")); - - /* first, check the summary is correct (updates folder_size too) */ - camel_spool_summary_check((CamelSpoolSummary *)folder->summary, lf->changes, ex); - if (camel_exception_is_set(ex)) - goto fail; - - /* add it to the summary/assign the uid, etc */ - mi = camel_spool_summary_add((CamelSpoolSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set(ex)) - goto fail; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY|O_APPEND, 0600); - if (output_stream == NULL) { - camel_exception_setv(ex, 1, _("Cannot open mailbox: %s: %s\n"), lf->folder_path, strerror(errno)); - goto fail; - } - - /* and we need to set the frompos/XEV explicitly */ - ((CamelSpoolMessageInfo *)mi)->frompos = mbs->folder_size?mbs->folder_size+1:0; -#if 0 - xev = camel_spool_summary_encode_x_evolution((CamelLocalSummary *)folder->summary, mi); - if (xev) { - /* the x-ev header should match the 'current' flags, no problem, so store as much */ - camel_medium_set_header((CamelMedium *)message, "X-Evolution", xev); - mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED; - g_free(xev); - } -#endif - - /* we must write this to the non-filtered stream ... prepend a \n if not at the start of the file */ - fromline = camel_spool_summary_build_from(((CamelMimePart *)message)->headers); - if (camel_stream_printf(output_stream, mbs->folder_size==0?"%s":"\n%s", fromline) == -1) - goto fail_write; - - /* 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((CamelDataWrapper *)message, filter_stream) == -1) - goto fail_write; - - if (camel_stream_close(filter_stream) == -1) - goto fail_write; - - /* unlock as soon as we can */ - camel_spool_folder_unlock(lf); - - /* filter stream ref's the output stream itself, so we need to unref it too */ - camel_object_unref((CamelObject *)filter_from); - camel_object_unref((CamelObject *)filter_stream); - camel_object_unref((CamelObject *)output_stream); - g_free(fromline); - - /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ - /* the stat really shouldn't fail, we just wrote to it */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return; - -fail_write: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to spool file: %s: %s"), - lf->folder_path, g_strerror (errno)); - - if (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); - - /* reset the file to original size */ - fd = open(lf->folder_path, O_WRONLY, 0600); - if (fd != -1) { - ftruncate(fd, mbs->folder_size); - close(fd); - } - - /* remove the summary info so we are not out-of-sync with the spool */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (mbs), camel_message_info_uid (mi)); - - /* and tell the summary its uptodate */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - -fail: - /* make sure we unlock the folder - before we start triggering events into appland */ - camel_spool_folder_unlock(lf); - - /* cascade the changes through, anyway, if there are any outstanding */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static CamelMimeMessage * -spool_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) -{ - CamelSpoolFolder *lf = (CamelSpoolFolder *)folder; - CamelMimeMessage *message; - CamelSpoolMessageInfo *info; - CamelMimeParser *parser; - int fd; - int retried = FALSE; - - d(printf("Getting message %s\n", uid)); - - /* lock the folder first, burn if we can't, need write lock for summary check */ - if (camel_spool_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return NULL; - - /* check for new messages, this may renumber uid's though */ - if (camel_spool_summary_check((CamelSpoolSummary *)folder->summary, lf->changes, ex) == -1) - return NULL; - -retry: - /* get the message summary info */ - info = (CamelSpoolMessageInfo *) camel_folder_summary_uid(folder->summary, uid); - - if (info == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), uid, _("No such message")); - camel_spool_folder_unlock(lf); - return NULL; - } - - /* no frompos, its an error in the library (and we can't do anything with it */ - g_assert(info->frompos != -1); - - /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache - the whole message in memory if the stream is non-seekable (which it is when built from a parser - with no stream). This means we dont have to lock the spool for the life of the message, but only - while it is being created. */ - - fd = open(lf->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - strerror(errno)); - camel_spool_folder_unlock(lf); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - return NULL; - } - - /* 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_fd(parser, fd); - camel_mime_parser_scan_from(parser, TRUE); - - camel_mime_parser_seek(parser, info->frompos, SEEK_SET); - if (camel_mime_parser_step(parser, NULL, NULL) != HSCAN_FROM - || camel_mime_parser_tell_start_from(parser) != info->frompos) { - - g_warning("Summary doesn't match the folder contents! eek!\n" - " expecting offset %ld got %ld, state = %d", (long int)info->frompos, - (long int)camel_mime_parser_tell_start_from(parser), - camel_mime_parser_state(parser)); - - camel_object_unref((CamelObject *)parser); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - - if (!retried) { - retried = TRUE; - camel_spool_summary_check((CamelSpoolSummary *)folder->summary, lf->changes, ex); - if (!camel_exception_is_set(ex)) - goto retry; - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("The folder appears to be irrecoverably corrupted.")); - - camel_spool_folder_unlock(lf); - return NULL; - } - - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - - message = camel_mime_message_new(); - if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) { - camel_exception_setv(ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("Message construction failed: Corrupt mailbox?")); - camel_object_unref((CamelObject *)parser); - camel_object_unref((CamelObject *)message); - camel_spool_folder_unlock(lf); - return NULL; - } - - /* and unlock now we're finished with it */ - camel_spool_folder_unlock(lf); - - camel_object_unref((CamelObject *)parser); - - /* use the opportunity to notify of changes (particularly if we had a rebuild) */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return message; -} - -static void -spool_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - g_return_if_fail(info != NULL); - - if (camel_flag_set(&info->user_flags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} - -static void -spool_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - g_return_if_fail(info != NULL); - - if (camel_tag_set(&info->user_tags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} diff --git a/camel/providers/local/camel-spool-folder.h b/camel/providers/local/camel-spool-folder.h deleted file mode 100644 index 717ec4abd9..0000000000 --- a/camel/providers/local/camel-spool-folder.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_SPOOL_FOLDER_H -#define CAMEL_SPOOL_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-spool-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_SPOOL_FOLDER_TYPE (camel_spool_folder_get_type ()) -#define CAMEL_SPOOL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolder)) -#define CAMEL_SPOOL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolderClass)) -#define CAMEL_IS_SPOOL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_FOLDER_TYPE)) - -typedef struct { - CamelFolder parent_object; - struct _CamelSpoolFolderPrivate *priv; - - guint32 flags; /* open mode flags */ - - int locked; /* lock counter */ - CamelLockType locktype; /* what type of lock we have */ - int lockfd; /* lock fd used for fcntl/etc locking */ - int lockid; /* lock id for dot locking */ - - char *base_path; /* base path of the spool folder */ - char *folder_path; /* the path to the folder itself */ -#if 0 - char *summary_path; /* where the summary lives */ - char *index_path; /* where the index file lives */ - - ibex *index; /* index for this folder */ -#endif - CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */ - CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */ -} CamelSpoolFolder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - - /* summary factory, only used at init */ - CamelSpoolSummary *(*create_summary)(const char *path, const char *folder, ibex *index); - - /* Lock the folder for my operations */ - int (*lock)(CamelSpoolFolder *, CamelLockType type, CamelException *ex); - - /* Unlock the folder for my operations */ - void (*unlock)(CamelSpoolFolder *); -} CamelSpoolFolderClass; - - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelSpoolFolder *camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, - const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_spool_folder_get_type(void); - -CamelFolder *camel_spool_folder_new(CamelStore *parent_store, const char *full_name, - guint32 flags, CamelException *ex); - -/* Lock the folder for internal use. May be called repeatedly */ -/* UNIMPLEMENTED */ -int camel_spool_folder_lock(CamelSpoolFolder *lf, CamelLockType type, CamelException *ex); -int camel_spool_folder_unlock(CamelSpoolFolder *lf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_FOLDER_H */ diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c deleted file mode 100644 index fdf5640d99..0000000000 --- a/camel/providers/local/camel-spool-store.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> - -#include "camel-spool-store.h" -#include "camel-spool-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" - -#define d(x) - -/* Returns the class for a CamelSpoolStore */ -#define CSPOOLS_CLASS(so) CAMEL_SPOOL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi); - -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_spool_store_class_init (CamelSpoolStoreClass *camel_spool_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_spool_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_spool_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = free_folder_info; - - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -CamelType -camel_spool_store_get_type (void) -{ - static CamelType camel_spool_store_type = CAMEL_INVALID_TYPE; - - if (camel_spool_store_type == CAMEL_INVALID_TYPE) { - camel_spool_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelSpoolStore", - sizeof (CamelSpoolStore), - sizeof (CamelSpoolStoreClass), - (CamelObjectClassInitFunc) camel_spool_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_spool_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - struct stat st; - - d(printf("constructing store of type %s '%s:%s'\n", - camel_type_to_name(((CamelObject *)service)->s.type), url->protocol, url->path)); - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (service->url->path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), service->url->path); - return; - } - - if (stat(service->url->path, &st) == -1 || !S_ISREG(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Spool `%s' does not exist or is not a regular file"), - service->url->path); - return; - } -} - -const char * -camel_spool_store_get_toplevel_dir (CamelSpoolStore *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 *path = ((CamelService *)store)->url->path; - CamelFolder *folder; - - d(printf("opening folder %s on path %s\n", folder_name, path)); - - /* we only support an 'INBOX' */ - if (strcmp(folder_name, "INBOX") != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s/%s' does not exist."), - path, folder_name); - return NULL; - } - - folder = camel_spool_folder_new(store, folder_name, flags, ex); - - return folder; -} - -static CamelFolder * -get_inbox(CamelStore *store, CamelException *ex) -{ - return get_folder (store, "INBOX", CAMEL_STORE_FOLDER_CREATE, ex); -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup (service->url->path); - else - return g_strdup_printf (_("Spool mail file %s"), service->url->path); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelService *service = (CamelService *)store; - CamelFolder *folder; - - if (top == NULL || strcmp(top, "INBOX") == 0) { - /* FIXME: if the folder is opened we could look it up? */ - fi = g_malloc0(sizeof(*fi)); - fi->full_name = "INBOX"; - fi->name = "INBOX"; - fi->url = g_strdup_printf("spool:%s#%s", service->url->path, fi->name); - - CAMEL_STORE_LOCK(store, cache_lock); - folder = g_hash_table_lookup(store->folders, fi->full_name); - if (folder) - fi->unread_message_count = camel_folder_get_message_count(folder); - else - fi->unread_message_count = -1; - CAMEL_STORE_UNLOCK(store, cache_lock); - - camel_folder_info_build_path(fi, '/'); - } - - return fi; -} - -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - if (fi) { - g_free(fi->url); - g_free(fi); - } -} - - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be renamed")); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be deleted")); -} diff --git a/camel/providers/local/camel-spool-store.h b/camel/providers/local/camel-spool-store.h deleted file mode 100644 index 677f6aa0ed..0000000000 --- a/camel/providers/local/camel-spool-store.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_SPOOL_STORE_H -#define CAMEL_SPOOL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-store.h" - -#define CAMEL_SPOOL_STORE_TYPE (camel_spool_store_get_type ()) -#define CAMEL_SPOOL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStore)) -#define CAMEL_SPOOL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStoreClass)) -#define CAMEL_IS_SPOOL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - -} CamelSpoolStore; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelSpoolStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_spool_store_get_type (void); - -const gchar *camel_spool_store_get_toplevel_dir (CamelSpoolStore *store); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_STORE_H */ - - diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c deleted file mode 100644 index f4b03b6aff..0000000000 --- a/camel/providers/local/camel-spool-summary.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2001 Ximian Inc. (www.ximian.com) - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-spool-summary.h" -#include "camel-mime-message.h" -#include "camel-file-utils.h" -#include "camel-operation.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_SPOOL_SUMMARY_VERSION (0x400) - -struct _CamelSpoolSummaryPrivate { -}; - -#define _PRIVATE(o) (((CamelSpoolSummary *)(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 *s, CamelMimeParser *mp); -static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *); -static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *); - -static int spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *mi); -static char *spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *mi); - -static int spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex); -static int spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static int spool_summary_sync_full(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static void camel_spool_summary_class_init (CamelSpoolSummaryClass *klass); -static void camel_spool_summary_init (CamelSpoolSummary *obj); -static void camel_spool_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_spool_summary_parent; - -CamelType -camel_spool_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelSpoolSummary", - sizeof (CamelSpoolSummary), - sizeof (CamelSpoolSummaryClass), - (CamelObjectClassInitFunc) camel_spool_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_spool_summary_init, - (CamelObjectFinalizeFunc) camel_spool_summary_finalise); - } - - return type; -} - -static void -camel_spool_summary_class_init(CamelSpoolSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass; - - camel_spool_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; - - klass->load = spool_summary_load; - klass->check = spool_summary_check; - klass->sync = spool_summary_sync; - klass->add = spool_summary_add; - - klass->encode_x_evolution = spool_summary_encode_x_evolution; - klass->decode_x_evolution = spool_summary_decode_x_evolution; -} - -static void -camel_spool_summary_init(CamelSpoolSummary *obj) -{ - struct _CamelSpoolSummaryPrivate *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(CamelSpoolMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_SPOOL_SUMMARY_VERSION; -} - -static void -camel_spool_summary_finalise(CamelObject *obj) -{ - CamelSpoolSummary *mbs = CAMEL_SPOOL_SUMMARY(obj); - - g_free(mbs->folder_path); -} - -CamelSpoolSummary * -camel_spool_summary_new(const char *filename) -{ - CamelSpoolSummary *new = (CamelSpoolSummary *)camel_object_new(camel_spool_summary_get_type()); - - camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE); - new->folder_path = g_strdup(filename); - - return new; -} - -static int -spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex) -{ - g_warning("spool_summary_load() should nto b e called\n"); - - return camel_folder_summary_load((CamelFolderSummary *)cls); -} - -/* load/check the summary */ -int -camel_spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex) -{ - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - g_warning("spool_summary_load() should nto b e called\n"); - - d(printf("Loading summary ...\n")); - - if (forceindex - || stat(s->summary_path, &st) == -1 - || ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) { - camel_folder_summary_clear((CamelFolderSummary *)cls); - } - - return camel_spool_summary_check(cls, NULL, ex); -} - -char * -camel_spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *info) -{ - return ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->encode_x_evolution(cls, info); -} - -int -camel_spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info) -{ - return ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info); -} - -int -camel_spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret; - - ret = ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->check(cls, changeinfo, ex); - - return ret; -} - -int -camel_spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - return ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->sync(cls, expunge, changeinfo, ex); -} - -CamelMessageInfo * -camel_spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - return ((CamelSpoolSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->add(cls, msg, info, ci, ex); -} - -/** - * camel_spool_summary_write_headers: - * @fd: - * @header: - * @xevline: - * - * Write a bunch of headers to the file @fd. IF xevline is non NULL, then - * an X-Evolution header line is created at the end of all of the headers. - * The headers written are termianted with a blank line. - * - * Return value: -1 on error, otherwise the number of bytes written. - **/ -int -camel_spool_summary_write_headers(int fd, struct _header_raw *header, char *xevline) -{ - int outlen = 0, len; - int newfd; - FILE *out; - - /* dum de dum, maybe the whole sync function should just use stdio for output */ - newfd = dup(fd); - if (newfd == -1) - return -1; - - out = fdopen(newfd, "w"); - if (out == NULL) { - close(newfd); - errno = EINVAL; - return -1; - } - - while (header) { - if (strcmp(header->name, "X-Evolution")) { - len = fprintf(out, "%s:%s\n", header->name, header->value); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - header = header->next; - } - - if (xevline) { - len = fprintf(out, "X-Evolution: %s\n\n", xevline); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (fclose(out) == -1) - return -1; - - return outlen; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelSpoolSummary *mbs = CAMEL_SPOOL_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_spool_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - return camel_file_util_decode_uint32(in, &mbs->folder_size); -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelSpoolSummary *mbs = CAMEL_SPOOL_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_spool_summary_parent)->summary_header_save(s, out) == -1) - return -1; - - return camel_file_util_encode_uint32(out, mbs->folder_size); -} - -static CamelMessageInfo * -message_info_new(CamelFolderSummary *s, struct _header_raw *h) -{ - CamelMessageInfo *mi; - CamelSpoolSummary *cls = (CamelSpoolSummary *)s; - - mi = ((CamelFolderSummaryClass *)camel_spool_summary_parent)->message_info_new(s, h); - if (mi) { - CamelSpoolMessageInfo *mbi = (CamelSpoolMessageInfo *)mi; - const char *xev; - - xev = header_raw_find(&h, "X-Evolution", NULL); - if (xev==NULL || camel_spool_summary_decode_x_evolution(cls, xev, mi) == -1) { - /* to indicate it has no xev header */ - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - } - - mbi->frompos = -1; - } - - return mi; -} - -static CamelMessageInfo * -message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) -{ - CamelMessageInfo *mi; - - mi = ((CamelFolderSummaryClass *)camel_spool_summary_parent)->message_info_new_from_parser(s, mp); - if (mi) { - CamelSpoolMessageInfo *mbi = (CamelSpoolMessageInfo *)mi; - - mbi->frompos = camel_mime_parser_tell_start_from(mp); - } - - return mi; -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - - io(printf("loading spool message info\n")); - - mi = ((CamelFolderSummaryClass *)camel_spool_summary_parent)->message_info_load(s, in); - if (mi) { - CamelSpoolMessageInfo *mbi = (CamelSpoolMessageInfo *)mi; - - if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1) - goto error; - } - - return mi; -error: - camel_folder_summary_info_free(s, mi); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) -{ - CamelSpoolMessageInfo *mbi = (CamelSpoolMessageInfo *)mi; - - io(printf("saving spool message info\n")); - - if (((CamelFolderSummaryClass *)camel_spool_summary_parent)->message_info_save(s, out, mi) == -1 - || camel_file_util_encode_off_t(out, mbi->frompos) == -1) - return -1; - - return 0; -} - -static int -summary_rebuild(CamelSpoolSummary *cls, off_t offset, CamelException *ex) -{ - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMimeParser *mp; - int fd; - int ok = 0; - struct stat st; - off_t size = 0; - - /* FIXME: If there is a failure, it shouldn't clear the summary and restart, - it should try and merge the summary info's. This is a bit tricky. */ - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - d(printf("%s failed to open: %s\n", cls->folder_path, strerror(errno))); - camel_exception_setv(ex, 1, _("Could not open folder: %s: %s"), - cls->folder_path, offset, strerror(errno)); - camel_operation_end(NULL); - return -1; - } - - if (fstat(fd, &st) == 0) - size = st.st_size; - - 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, building summary from start"); - camel_mime_parser_drop_step(mp); - offset = 0; - camel_mime_parser_seek(mp, offset, SEEK_SET); - camel_folder_summary_clear(s); - } else { - camel_mime_parser_unstep(mp); - } - } else { - d(printf("mime parser state ran out? state is %d\n", camel_mime_parser_state(mp))); - camel_object_unref(CAMEL_OBJECT(mp)); - /* end of file - no content? no error either */ - camel_operation_end(NULL); - return 0; - } - } - - while (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) { - CamelMessageInfo *info; - off_t pc = camel_mime_parser_tell_start_from (mp) + 1; - - camel_operation_progress (NULL, (int) (((float) pc / size) * 100)); - - info = camel_folder_summary_add_from_parser(s, mp); - if (info == NULL) { - camel_exception_setv(ex, 1, _("Fatal mail parser error near position %ld in folder %s"), - camel_mime_parser_tell(mp), cls->folder_path); - 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) { - if (stat(cls->folder_path, &st) == 0) { - camel_folder_summary_touch(s); - cls->folder_size = st.st_size; - s->time = st.st_mtime; - } - } - - camel_operation_end(NULL); - - return ok; -} - -/* like summary_rebuild, but also do changeinfo stuff (if supplied) */ -static int -summary_update(CamelSpoolSummary *cls, off_t offset, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret, i, count; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - d(printf("Calling summary update, from pos %d\n", (int)offset)); - - if (changeinfo) { - /* 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, camel_message_info_uid(mi)); - camel_folder_summary_info_free(s, mi); - } - } - - /* do the actual work */ - ret = summary_rebuild(cls, offset, ex); - - if (changeinfo) { - 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, camel_message_info_uid(mi)); - camel_folder_summary_info_free(s, mi); - } - camel_folder_change_info_build_diff(changeinfo); - } - - return ret; -} - -static int -spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct stat st; - int ret = 0; - - d(printf("Checking summary\n")); - - /* check if the summary is up-to-date */ - if (stat(cls->folder_path, &st) == -1) { - camel_folder_summary_clear(s); - camel_exception_setv(ex, 1, _("Cannot check folder: %s: %s"), cls->folder_path, strerror(errno)); - return -1; - } - - if (st.st_size == 0) { - /* empty? No need to scan at all */ - d(printf("Empty spool, clearing summary\n")); - camel_folder_summary_clear(s); - ret = 0; - } else if (s->messages->len == 0) { - /* if we are empty, then we rebuilt from scratch */ - d(printf("Empty summary, rebuilding from start\n")); - ret = summary_update(cls, 0, changeinfo, ex); - } else { - /* is the summary uptodate? */ - if (st.st_size != cls->folder_size || st.st_mtime != s->time) { - if (cls->folder_size < st.st_size) { - /* this will automatically rescan from 0 if there is a problem */ - d(printf("folder grew, attempting to rebuild from %d\n", cls->folder_size)); - ret = summary_update(cls, cls->folder_size, changeinfo, ex); - } else { - d(printf("folder shrank! rebuilding from start\n")); - camel_folder_summary_clear(s); - ret = summary_update(cls, 0, changeinfo, ex); - } - } - } - - if (ret != -1) { - int i, work, count; - - /* check to see if we need to copy/update the file; missing xev headers prompt this */ - work = FALSE; - count = camel_folder_summary_count(s); - for (i=0;!work && i<count; i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - g_assert(info); - work = (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0; - camel_folder_summary_info_free(s, info); - } - - /* if we do, then write out the headers using sync_full, etc */ - if (work) { - d(printf("Have to add new headers, re-syncing from the start to accomplish this\n")); - ret = spool_summary_sync_full(cls, FALSE, changeinfo, ex); - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unknown error: %s"), strerror(errno)); - return -1; - } - } - cls->folder_size = st.st_size; - s->time = st.st_mtime; - } - - return ret; -} - -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_spool_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 %d %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; -} - -/* perform a full sync */ -static int -spool_summary_sync_full(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMimeParser *mp = NULL; - int i, count; - CamelSpoolMessageInfo *info = NULL; - int fd = -1, fdout = -1; - char *tmpname = NULL; - char *buffer, *xevnew = NULL, *p; - int len; - const char *fromline; - int lastdel = FALSE; - off_t spoollen, outlen; - int size, sizeout; - struct stat st; - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, strerror(errno)); - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - -#ifdef HAVE_MKSTEMP - tmpname = alloca(64); - sprintf(tmpname, "/tmp/spool.camel.XXXXXX"); - fdout = mkstemp(tmpname); -#else -#warning "Your system has no mkstemp(3), spool updating may be insecure" - tmpname = alloca(L_tmpnam); - tmpnam(tmpname); - fdout = open(tmpname, O_RDWR|O_CREAT|O_EXCL, 0600); -#endif - d(printf("Writing tmp file to %s\n", tmpname)); - if (fdout == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), strerror(errno)); - goto error; - } - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int pc = (i + 1) * 100 / count; - - camel_operation_progress(NULL, pc); - - info = (CamelSpoolMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Looking at message %s\n", camel_message_info_uid(info))); - - /* only need to seek past deleted messages, otherwise we should be at the right spot/state already */ - if (lastdel) { - d(printf("seeking to %d\n", (int)info->frompos)); - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - } - - if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - lastdel = FALSE; - if (expunge && info->info.flags & CAMEL_MESSAGE_DELETED) { - const char *uid = camel_message_info_uid(info); - - d(printf("Deleting %s\n", uid)); - -#if 0 - if (cls->index) - ibex_unindex(cls->index, (char *)uid); -#endif - /* remove it from the change list */ - camel_folder_change_info_remove_uid(changeinfo, uid); - camel_folder_summary_remove(s, (CamelMessageInfo *)info); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - count--; - i--; - info = NULL; - lastdel = TRUE; - } else { - /* otherwise, the message is staying, copy its From_ line across */ - if (i>0) { - write(fdout, "\n", 1); - } - info->frompos = lseek(fdout, 0, SEEK_CUR); - fromline = camel_mime_parser_from_line(mp); - write(fdout, fromline, strlen(fromline)); - } - - if (info && info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) { - d(printf("Updating header for %s flags = %08x\n", camel_message_info_uid(info), info->info.flags)); - - if (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xevnew = camel_spool_summary_encode_x_evolution(cls, (CamelMessageInfo *)info); - if (camel_spool_summary_write_headers(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; - } - - /* mark this message as recent */ - if (info->info.flags & CAMEL_MESSAGE_FOLDER_NOXEV) - camel_folder_change_info_recent_uid(changeinfo, camel_message_info_uid(info)); - - info->info.flags &= 0xffff; - g_free(xevnew); - xevnew = NULL; - camel_mime_parser_drop_step(mp); - } - - camel_mime_parser_drop_step(mp); - if (info) { - d(printf("looking for message content to copy across from %d\n", (int)camel_mime_parser_tell(mp))); - while (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_PRE_FROM) { - d(printf("copying spool contents to tmp: '%.*s'\n", len, buffer)); - if (write(fdout, buffer, len) != len) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Writing to tmp mailbox failed: %s: %s"), - cls->folder_path, strerror(errno)); - goto error; - } - } - d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp), - (int)camel_mime_parser_tell_start_from(mp))); - camel_mime_parser_unstep(mp); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - } - } - - /* sync out content */ - if (fsync(fdout) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror(errno)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - cls->folder_path, strerror(errno)); - goto error; - } - - /* see if we can write this much to the spool file */ - if (fstat(fd, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror(errno)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - cls->folder_path, strerror(errno)); - goto error; - } - spoollen = st.st_size; - - if (fstat(fdout, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror(errno)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - cls->folder_path, strerror(errno)); - goto error; - } - outlen = st.st_size; - - /* I think this is the right way to do this */ - if (outlen>0 - && (lseek(fd, outlen-1, SEEK_SET) == -1 - || write(fd, "", 1) != 1 - || fsync(fd) == -1 - || lseek(fd, 0, SEEK_SET) == -1 - || lseek(fdout, 0, SEEK_SET) == -1)) { - g_warning("Cannot sync spool folder: %s", strerror(errno)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s"), - cls->folder_path, strerror(errno)); - /* incase we ran out of room, remove any trailing space first */ - ftruncate(fd, spoollen); - goto error; - } - - - /* now copy content back */ - buffer = g_malloc(8192); - size = 1; - while (size>0) { - do { - size = read(fdout, buffer, 8192); - } while (size == -1 && errno == EINTR); - - if (size > 0) { - p = buffer; - do { - sizeout = write(fd, p, size); - if (sizeout > 0) { - p+= sizeout; - size -= sizeout; - } - } while ((sizeout == -1 && errno == EINTR) && size > 0); - size = sizeout; - } - - if (size == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - cls->folder_path, strerror(errno), tmpnam); - /* so we dont delete it */ - close(fdout); - tmpname = NULL; - fdout = -1; - g_free(buffer); - goto error; - } - } - - g_free(buffer); - - d(printf("Closing folders\n")); - - if (ftruncate(fd, outlen) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - cls->folder_path, strerror(errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - goto error; - } - - if (close(fd) == -1) { - g_warning("Cannot close source folder: %s", strerror(errno)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - cls->folder_path, strerror(errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - fd = -1; - goto error; - } - - close(fdout); - unlink(tmpname); - - camel_object_unref((CamelObject *)mp); - camel_operation_end(NULL); - - 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((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -/* perform a quick sync - only system flags have changed */ -static int -spool_summary_sync_quick(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMimeParser *mp = NULL; - int i, count; - CamelSpoolMessageInfo *info = NULL; - int fd = -1; - char *xevnew, *xevtmp; - const char *xev; - int len; - off_t lastpos; - - d(printf("Performing quick summary sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not file: %s: %s"), - cls->folder_path, strerror(errno)); - - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int xevoffset; - int pc = (i+1)*100/count; - - camel_operation_progress(NULL, pc); - - info = (CamelSpoolMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags)); - - if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - continue; - } - - d(printf("Updating message %s\n", camel_message_info_uid(info))); - - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - - if (camel_mime_parser_step(mp, 0, 0) != HSCAN_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_step(mp, 0, 0) == HSCAN_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - if (xev == NULL || camel_spool_summary_decode_x_evolution(cls, xev, NULL) == -1) { - g_warning("We're supposed to have a valid x-ev header, but we dont"); - goto error; - } - xevnew = camel_spool_summary_encode_x_evolution(cls, (CamelMessageInfo *)info); - /* SIGH: encode_param_list is about the only function which folds headers by itself. - This should be fixed somehow differently (either parser doesn't fold headers, - or param_list doesn't, or something */ - xevtmp = header_unfold(xevnew); - /* the raw header contains a leading ' ', so (dis)count that too */ - if (strlen(xev)-1 != strlen(xevtmp)) { - g_free(xevnew); - g_free(xevtmp); - g_warning("Hmm, the xev headers shouldn't have changed size, but they did"); - goto error; - } - g_free(xevtmp); - - /* we write out the xevnew string, assuming its been folded identically to the original too! */ - - lastpos = lseek(fd, 0, SEEK_CUR); - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - lseek(fd, lastpos, SEEK_SET); - g_free(xevnew); - - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - - info->info.flags &= 0xffff; - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - } - - 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"), - cls->folder_path, strerror(errno)); - fd = -1; - goto error; - } - - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -static int -spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - int i, count; - int quick = TRUE, work=FALSE; - int ret; - - /* first, sync ourselves up, just to make sure */ - summary_update(cls, cls->folder_size, changeinfo, ex); - if (camel_exception_is_set(ex)) - return -1; - - count = camel_folder_summary_count(s); - if (count == 0) - return 0; - - /* check what work we have to do, if any */ - for (i=0;quick && i<count; i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - g_assert(info); - if ((expunge && (info->flags & CAMEL_MESSAGE_DELETED)) || - (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE))) - quick = FALSE; - else - work |= (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; - camel_folder_summary_info_free(s, info); - } - - /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */ - ret = -1; - if (quick) { - if (work) { - ret = spool_summary_sync_quick(cls, expunge, changeinfo, ex); - if (ret == -1) { - g_warning("failed a quick-sync, trying a full sync"); - camel_exception_clear(ex); - } - } else { - ret = 0; - } - } - - if (ret == -1) - ret = spool_summary_sync_full(cls, expunge, changeinfo, ex); - if (ret == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unknown error: %s"), strerror(errno)); - return -1; - } - - camel_folder_summary_touch(s); - s->time = st.st_mtime; - cls->folder_size = st.st_size; - /*camel_folder_summary_save(s);*/ - - return 0; -} - - -static CamelMessageInfo * -spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelMessageInfo *mi; - char *xev; - - d(printf("Adding message to summary\n")); - - mi = camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg); - if (mi) { - d(printf("Added, uid = %s\n", camel_message_info_uid(mi))); - if (info) { - CamelTag *tag = info->user_tags; - CamelFlag *flag = info->user_flags; - - while (flag) { - camel_flag_set(&mi->user_flags, flag->name, TRUE); - flag = flag->next; - } - - while (tag) { - camel_tag_set(&mi->user_tags, tag->name, tag->value); - tag = tag->next; - } - - mi->flags = mi->flags | (info->flags & 0xffff); - } - mi->flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED); - xev = camel_spool_summary_encode_x_evolution(cls, mi); - camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev); - g_free(xev); - camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi)); - } else { - d(printf("Failed!\n")); - camel_exception_set(ex, 1, _("Unable to add message to summary: unknown reason")); - } - return mi; -} - -static char * -spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *mi) -{ - GString *out = g_string_new(""); - struct _header_param *params = NULL; - GString *val = g_string_new(""); - CamelFlag *flag = mi->user_flags; - CamelTag *tag = mi->user_tags; - char *ret; - const char *p, *uidstr; - guint32 uid; - - /* FIXME: work out what to do with uid's that aren't stored here? */ - /* FIXME: perhaps make that a mbox folder only issue?? */ - p = uidstr = camel_message_info_uid(mi); - while (*p && isdigit(*p)) - p++; - if (*p == 0 && sscanf(uidstr, "%u", &uid) == 1) { - g_string_sprintf(out, "%08x-%04x", uid, mi->flags & 0xffff); - } else { - g_string_sprintf(out, "%s-%04x", uidstr, mi->flags & 0xffff); - } - - if (flag || tag) { - val = g_string_new(""); - - if (flag) { - while (flag) { - g_string_append(val, flag->name); - if (flag->next) - g_string_append_c(val, ','); - flag = flag->next; - } - header_set_param(¶ms, "flags", val->str); - g_string_truncate(val, 0); - } - if (tag) { - while (tag) { - g_string_append(val, tag->name); - g_string_append_c(val, '='); - g_string_append(val, tag->value); - if (tag->next) - g_string_append_c(val, ','); - tag = tag->next; - } - header_set_param(¶ms, "tags", val->str); - } - g_string_free(val, TRUE); - header_param_list_format_append(out, params); - header_param_list_free(params); - } - ret = out->str; - g_string_free(out, FALSE); - return ret; -} - -static int -spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *mi) -{ - struct _header_param *params, *scan; - guint32 uid, flags; - char *header; - int i; - - /* check for uid/flags */ - header = header_token_decode(xev); - if (header && strlen(header) == strlen("00000000-0000") - && sscanf(header, "%08x-%04x", &uid, &flags) == 2) { - char uidstr[20]; - if (mi) { - sprintf(uidstr, "%u", uid); - camel_message_info_set_uid(mi, g_strdup(uidstr)); - mi->flags = flags; - } - } else { - g_free(header); - return -1; - } - g_free(header); - - if (mi == NULL) - return 0; - - /* check for additional data */ - header = strchr(xev, ';'); - if (header) { - params = header_param_list_decode(header+1); - scan = params; - while (scan) { - if (!strcasecmp(scan->name, "flags")) { - char **flagv = g_strsplit(scan->value, ",", 1000); - - for (i=0;flagv[i];i++) { - camel_flag_set(&mi->user_flags, flagv[i], TRUE); - } - g_strfreev(flagv); - } else if (!strcasecmp(scan->name, "tags")) { - char **tagv = g_strsplit(scan->value, ",", 10000); - char *val; - - for (i=0;tagv[i];i++) { - val = strchr(tagv[i], '='); - if (val) { - *val++ = 0; - camel_tag_set(&mi->user_tags, tagv[i], val); - val[-1]='='; - } - } - g_strfreev(tagv); - } - scan = scan->next; - } - header_param_list_free(params); - } - return 0; -} - diff --git a/camel/providers/local/camel-spool-summary.h b/camel/providers/local/camel-spool-summary.h deleted file mode 100644 index e0b63a1b6b..0000000000 --- a/camel/providers/local/camel-spool-summary.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. (www.ximian.com) - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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_SPOOL_SUMMARY_H -#define _CAMEL_SPOOL_SUMMARY_H - -#include <camel/camel-folder-summary.h> -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <libibex/ibex.h> - -#define CAMEL_SPOOL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_spool_summary_get_type (), CamelSpoolSummary) -#define CAMEL_SPOOL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_spool_summary_get_type (), CamelSpoolSummaryClass) -#define CAMEL_IS_SPOOL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_spool_summary_get_type ()) - -typedef struct _CamelSpoolSummary CamelSpoolSummary; -typedef struct _CamelSpoolSummaryClass CamelSpoolSummaryClass; - -/* extra summary flags */ -enum { - CAMEL_MESSAGE_FOLDER_NOXEV = 1<<17, - CAMEL_MESSAGE_FOLDER_XEVCHANGE = 1<<18, -}; - -typedef struct _CamelSpoolMessageInfo { - CamelMessageInfo info; - - off_t frompos; -} CamelSpoolMessageInfo; - -struct _CamelSpoolSummary { - CamelFolderSummary parent; - - struct _CamelSpoolSummaryPrivate *priv; - - char *folder_path; /* name of matching folder */ - - size_t folder_size; -}; - -struct _CamelSpoolSummaryClass { - CamelFolderSummaryClass parent_class; - - int (*load)(CamelSpoolSummary *cls, int forceindex, CamelException *ex); - int (*check)(CamelSpoolSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - int (*sync)(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - CamelMessageInfo *(*add)(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - - char *(*encode_x_evolution)(CamelSpoolSummary *cls, const CamelMessageInfo *info); - int (*decode_x_evolution)(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info); -}; - -guint camel_spool_summary_get_type (void); -void camel_spool_summary_construct (CamelSpoolSummary *new, const char *filename, const char *spool_name, ibex *index); - -/* create the summary, in-memory only */ -CamelSpoolSummary *camel_spool_summary_new(const char *filename); - -/* load/check the summary */ -int camel_spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* generate an X-Evolution header line */ -char *camel_spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *info); -int camel_spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header */ -int camel_spool_summary_write_headers(int fd, struct _header_raw *header, char *xevline); -/* build a from line: FIXME: remove, or move to common code */ -char *camel_spool_summary_build_from(struct _header_raw *header); - -#endif /* ! _CAMEL_SPOOL_SUMMARY_H */ - diff --git a/camel/providers/local/libcamellocal.urls b/camel/providers/local/libcamellocal.urls deleted file mode 100644 index 207c19a98f..0000000000 --- a/camel/providers/local/libcamellocal.urls +++ /dev/null @@ -1,4 +0,0 @@ -mh -mbox -maildir -spool |