From d56ec225b805cb7a071d10adf99a93979cb3d0e7 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 8 Feb 2002 02:10:46 +0000 Subject: The day number has to be 2 chars wide, space filled to work properly with 2002-02-08 Not Zed * providers/local/camel-spool-summary.c (camel_spool_summary_build_from): The day number has to be 2 chars wide, space filled to work properly with pine, etc. * providers/local/camel-spoold-store.[ch]: new type of provider 'spool directory', which lets you view external mbox dirs without adding any extra cruft. Perhaps it should use . files to store summaries? Still a bit experimental, there's a warning when you select it in the account editor. Finished off most of #1185. Can't rename or move folders. * camel-mime-utils.c (header_decode_date): If the date is 100->1900 then we actually want to use it as the year in the tm struct, not year+100. e.g. year 102 -> 2002, not 2102. 2002-02-07 Not Zed * providers/local/camel-spool-store.c (get_folder): Pass path into spool_folder_new. * providers/local/camel-spool-folder.c (camel_spool_folder_new): (camel_spool_folder_construct): Take the full path to the folder and use that as the file path, independent of the full_name we use. 2002-02-07 Not Zed * providers/local/camel-local-provider.c: Added new type, spoold provider, spoold: for local directories. * providers/imap/camel-imap-store.c (get_one_folder_offline): Create offline uri's in a compatible manner to online ones. svn path=/trunk/; revision=15606 --- camel/ChangeLog | 35 +++ camel/camel-mime-utils.c | 4 +- camel/providers/imap/camel-imap-store.c | 14 +- camel/providers/local/Makefile.am | 6 +- camel/providers/local/camel-local-provider.c | 20 +- camel/providers/local/camel-maildir-store.c | 2 +- camel/providers/local/camel-spool-folder.c | 15 +- camel/providers/local/camel-spool-folder.h | 4 +- camel/providers/local/camel-spool-store.c | 2 +- camel/providers/local/camel-spool-summary.c | 2 +- camel/providers/local/camel-spoold-store.c | 388 +++++++++++++++++++++++++++ camel/providers/local/camel-spoold-store.h | 66 +++++ camel/providers/local/libcamellocal.urls | 1 + 13 files changed, 538 insertions(+), 21 deletions(-) create mode 100644 camel/providers/local/camel-spoold-store.c create mode 100644 camel/providers/local/camel-spoold-store.h (limited to 'camel') diff --git a/camel/ChangeLog b/camel/ChangeLog index 920cc6df90..788b1ccfe1 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,38 @@ +2002-02-08 Not Zed + + * providers/local/camel-spool-summary.c + (camel_spool_summary_build_from): The day number has to be 2 chars + wide, space filled to work properly with pine, etc. + + * providers/local/camel-spoold-store.[ch]: new type of provider + 'spool directory', which lets you view external mbox dirs without + adding any extra cruft. Perhaps it should use . files to store + summaries? Still a bit experimental, there's a warning when you + select it in the account editor. Finished off most of #1185. + Can't rename or move folders. + + * camel-mime-utils.c (header_decode_date): If the date is + 100->1900 then we actually want to use it as the year in the tm + struct, not year+100. e.g. year 102 -> 2002, not 2102. + +2002-02-07 Not Zed + + * providers/local/camel-spool-store.c (get_folder): Pass path into + spool_folder_new. + + * providers/local/camel-spool-folder.c (camel_spool_folder_new): + (camel_spool_folder_construct): Take the full path to the folder + and use that as the file path, independent of the full_name we + use. + +2002-02-07 Not Zed + + * providers/local/camel-local-provider.c: Added new type, spoold + provider, spoold: for local directories. + + * providers/imap/camel-imap-store.c (get_one_folder_offline): + Create offline uri's in a compatible manner to online ones. + 2002-02-07 Dan Winship * camel-sasl-ntlm.c: Implementation of NTLM (aka "Secure Password diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 660cc3575d..257c0e323e 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -3357,10 +3357,12 @@ header_decode_date(const char *in, int *saveoffset) g_free(monthname); } year = header_decode_int(&inptr); - if (year < 69 || (year >= 100 && year < 1900)) { + if (year < 69) { tm.tm_year = 100 + year; } else if (year < 100) { tm.tm_year = year; + } else if (year >= 100 && year < 1900) { + tm.tm_year = year; } else { tm.tm_year = year - 1900; } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 4b3855e73f..8253e3bdb9 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -1552,7 +1552,7 @@ get_folder_info_online (CamelStore *store, const char *top, g_ptr_array_free (folders, TRUE); return NULL; } - + /* Add INBOX, if necessary */ if (need_inbox) { for (i = 0; i < folders->len; i++) { @@ -1582,7 +1582,7 @@ get_folder_info_online (CamelStore *store, const char *top, g_ptr_array_add (folders, fi); } } - + /* Assemble. */ tree = camel_folder_info_build (folders, name, imap_store->dir_sep, TRUE); if (flags & CAMEL_STORE_FOLDER_INFO_FAST) { @@ -1643,19 +1643,23 @@ get_one_folder_offline (const char *physical_path, const char *path, gpointer da GPtrArray *folders = data; CamelImapStore *imap_store = folders->pdata[0]; CamelFolderInfo *fi; + CamelURL *url; - if (*path++ != '/') + if (*path != '/') return TRUE; fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (path); + fi->full_name = g_strdup (path+1); fi->name = strrchr (fi->full_name, imap_store->dir_sep); if (fi->name) fi->name = g_strdup (fi->name + 1); else fi->name = g_strdup (fi->full_name); - fi->url = g_strdup_printf ("%s/%s", imap_store->base_url, path); + url = camel_url_new(imap_store->base_url, NULL); + camel_url_set_path(url, path); + fi->url = camel_url_to_string(url, 0); + camel_url_free(url); /* FIXME: check summary */ fi->unread_message_count = -1; diff --git a/camel/providers/local/Makefile.am b/camel/providers/local/Makefile.am index f0ad0c7f6c..b0f033cf66 100644 --- a/camel/providers/local/Makefile.am +++ b/camel/providers/local/Makefile.am @@ -34,7 +34,8 @@ libcamellocal_la_SOURCES = \ camel-maildir-summary.c \ camel-spool-folder.c \ camel-spool-store.c \ - camel-spool-summary.c + camel-spool-summary.c \ + camel-spoold-store.c libcamellocalinclude_HEADERS = \ camel-local-folder.h \ @@ -51,7 +52,8 @@ libcamellocalinclude_HEADERS = \ camel-maildir-summary.h \ camel-spool-folder.h \ camel-spool-store.h \ - camel-spool-summary.h + camel-spool-summary.h \ + camel-spoold-store.h noinst_HEADERS = \ camel-local-private.h diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c index f4a4301022..17c3576ae2 100644 --- a/camel/providers/local/camel-local-provider.c +++ b/camel/providers/local/camel-local-provider.c @@ -34,6 +34,7 @@ #include "camel-mbox-store.h" #include "camel-maildir-store.h" #include "camel-spool-store.h" +#include "camel-spoold-store.h" #define d(x) @@ -68,8 +69,7 @@ static CamelProvider maildir_provider = { 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_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, local_conf_entries, /* ... */ @@ -86,6 +86,16 @@ static CamelProvider spool_provider = { /* ... */ }; +static CamelProvider spoold_provider = { + "spoold", + N_("Directory tree of mbox files"), + N_("For accessing mail storedin an external tree of mbox files.\nThis will allow you to directly access pine and elm folders.\nNOTE: This provider is still experimental so ensure you backup any mail folders first."), + "mail", + CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, + CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE, + /* ... */ +}; + /* build a canonical 'path' */ static char * make_can_path(char *p, char *o) @@ -193,4 +203,10 @@ void camel_provider_module_init(CamelSession * session) spool_provider.url_hash = local_url_hash; spool_provider.url_equal = local_url_equal; camel_session_register_provider(session, &spool_provider); + + spoold_provider.object_types[CAMEL_PROVIDER_STORE] = camel_spoold_store_get_type(); + spoold_provider.service_cache = g_hash_table_new(local_url_hash, local_url_equal); + spoold_provider.url_hash = local_url_hash; + spoold_provider.url_equal = local_url_equal; + camel_session_register_provider(session, &spoold_provider); } diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c index e26ab6b23e..788f1a7abb 100644 --- a/camel/providers/local/camel-maildir-store.c +++ b/camel/providers/local/camel-maildir-store.c @@ -225,7 +225,7 @@ static CamelFolderInfo *camel_folder_info_new(const char *url, const char *full, 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)); + d(printf("Adding maildir info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); return fi; } diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c index d63e760df4..3728b26fa2 100644 --- a/camel/providers/local/camel-spool-folder.c +++ b/camel/providers/local/camel-spool-folder.c @@ -171,7 +171,7 @@ CamelType camel_spool_folder_get_type(void) } CamelSpoolFolder * -camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) +camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, const char *full_name, const char *path, guint32 flags, CamelException *ex) { CamelFolderInfo *fi; CamelFolder *folder; @@ -189,9 +189,13 @@ camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, con root_dir_path = camel_spool_store_get_toplevel_dir(CAMEL_SPOOL_STORE(folder->parent_store)); +#if 0 lf->base_path = g_strdup(root_dir_path); lf->folder_path = g_strdup(root_dir_path); - +#else + lf->base_path = g_strdup(path); + lf->folder_path = g_strdup(path); +#endif lf->changes = camel_folder_change_info_new(); lf->flags = flags; @@ -207,7 +211,7 @@ camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, con 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->url = g_strdup_printf("spool:%s#%s", ((CamelService *)parent_store)->url->path, full_name); fi->unread_message_count = camel_folder_get_unread_message_count(folder); camel_folder_info_build_path(fi, '/'); @@ -218,7 +222,7 @@ camel_spool_folder_construct(CamelSpoolFolder *lf, CamelStore *parent_store, con } CamelFolder * -camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) +camel_spool_folder_new(CamelStore *parent_store, const char *full_name, const char *path, guint32 flags, CamelException *ex) { CamelFolder *folder; @@ -229,8 +233,7 @@ camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 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); + folder = (CamelFolder *)camel_spool_folder_construct((CamelSpoolFolder *)folder, parent_store, full_name, path, flags, ex); return folder; } diff --git a/camel/providers/local/camel-spool-folder.h b/camel/providers/local/camel-spool-folder.h index 717ec4abd9..79f3e9ec88 100644 --- a/camel/providers/local/camel-spool-folder.h +++ b/camel/providers/local/camel-spool-folder.h @@ -82,12 +82,12 @@ typedef struct { /* 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); + const char *full_name, const char *path, 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, +CamelFolder *camel_spool_folder_new(CamelStore *parent_store, const char *full_name, const char *path, guint32 flags, CamelException *ex); /* Lock the folder for internal use. May be called repeatedly */ diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c index fdf5640d99..e35581e3b2 100644 --- a/camel/providers/local/camel-spool-store.c +++ b/camel/providers/local/camel-spool-store.c @@ -143,7 +143,7 @@ get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelExce return NULL; } - folder = camel_spool_folder_new(store, folder_name, flags, ex); + folder = camel_spool_folder_new(store, folder_name, path, flags, ex); return folder; } diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c index f4b03b6aff..823b26fc77 100644 --- a/camel/providers/local/camel-spool-summary.c +++ b/camel/providers/local/camel-spool-summary.c @@ -611,7 +611,7 @@ camel_spool_summary_build_from(struct _header_raw *header) /*memcpy(&tm, gmtime(&thetime), sizeof(tm));*/ gmtime_r(&thetime, &tm); - g_string_sprintfa(out, " %s %s %d %02d:%02d:%02d %4d\n", + 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); diff --git a/camel/providers/local/camel-spoold-store.c b/camel/providers/local/camel-spoold-store.c new file mode 100644 index 0000000000..addd727214 --- /dev/null +++ b/camel/providers/local/camel-spoold-store.c @@ -0,0 +1,388 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Authors: Michael Zucchi + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include + +#include "camel-spoold-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 CamelSpoolDStore */ +#define CSPOOLS_CLASS(so) CAMEL_SPOOLD_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_spoold_store_class_init (CamelSpoolDStoreClass *camel_spoold_store_class) +{ + CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_spoold_store_class); + CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_spoold_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_spoold_store_get_type (void) +{ + static CamelType camel_spoold_store_type = CAMEL_INVALID_TYPE; + + if (camel_spoold_store_type == CAMEL_INVALID_TYPE) { + camel_spoold_store_type = camel_type_register (CAMEL_SPOOL_STORE_TYPE, "CamelSpoolDStore", + sizeof (CamelSpoolDStore), + sizeof (CamelSpoolDStoreClass), + (CamelObjectClassInitFunc) camel_spoold_store_class_init, + NULL, + NULL, + NULL); + } + + return camel_spoold_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_ISDIR(st.st_mode)) { + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Store `%s' does not exist or is not a directory"), + service->url->path); + return; + } +} + +const char * +camel_spoold_store_get_toplevel_dir (CamelSpoolDStore *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; + + + path = alloca(strlen(((CamelService *)store)->url->path) + strlen(folder_name)+2); + sprintf(path, "%s/%s", ((CamelService *)store)->url->path, folder_name); + + d(printf("opening folder %s on path %s\n", folder_name, path)); + +#if 0 + /* need to check path? */ + 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; + } +#endif + folder = camel_spool_folder_new(store, folder_name, path, flags, ex); + + return folder; +} + +static CamelFolder * +get_inbox(CamelStore *store, CamelException *ex) +{ + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Store does not support an INBOX")); + + return NULL; +} + +static char * +get_name (CamelService *service, gboolean brief) +{ + if (brief) + return g_strdup (service->url->path); + else + return g_strdup_printf (_("Mail tree %s"), service->url->path); +} + +static void free_folder_info (CamelStore *store, CamelFolderInfo *fi) +{ + if (fi) { + g_free(fi->url); + g_free(fi->name); + g_free(fi->full_name); + g_free(fi->path); + 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")); +} + + + +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 spoold info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); + + 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, *fname; + CamelFolderInfo *fi = NULL; + struct stat st; + CamelFolder *folder; + int unread; + char from[80]; + FILE *fp; + + d(printf("checking dir '%s' part '%s' for mbox content\n", root, path)); + + /* look for folders matching the right structure, recursively */ + if (path) { + name = alloca(strlen(root)+strlen(path)+2); + sprintf(name, "%s/%s", root, path); + } else + name = root; + + 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; + } + + if (path != NULL) { + uri = g_strdup_printf("spoold:%s;noselect=yes#%s", root, path); + tmp = strrchr(path, '/'); + if (tmp == NULL) + tmp = path; + else + tmp++; + fi = camel_folder_info_new(uri, path, tmp, -1); + fi->parent = parent; + fi->sibling = *fip; + *fip = fi; + g_free(uri); + + fip = &fi->child; + parent = fi; + } + + while ( (d = readdir(dir)) ) { + if (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) { + if (path) + fname = g_strdup_printf("%s/%s", path, d->d_name); + else + fname = g_strdup(d->d_name); + + if (S_ISREG(st.st_mode)) { + /* first, see if we already have it open */ + CAMEL_STORE_LOCK(store, cache_lock); + folder = g_hash_table_lookup(store->folders, fname); + if (folder) + unread = camel_folder_get_unread_message_count(folder); + else + unread = -1; + CAMEL_STORE_UNLOCK(store, cache_lock); + + /* no? check its content to see if its a folder or not */ + if (folder == NULL) { + fp = fopen(tmp, "r"); + if (fp != NULL) { + if (fgets(from, sizeof(from), fp) != NULL + && strncmp(from, "From ", 5) == 0) { + folder = (CamelFolder *)1; + /* TODO: if slow mode selected, we could look up unread counts here - + but its pretty expensive */ + } + fclose(fp); + } + } + + if (folder != NULL) { + uri = g_strdup_printf("spoold:%s#%s", root, fname); + fi = camel_folder_info_new(uri, fname, d->d_name, unread); + fi->parent = parent; + fi->sibling = *fip; + *fip = fi; + g_free(uri); + } + + } else if (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); + + if (scan_dir(store, visited, root, fname, flags, parent, fip, ex) == -1) { + g_free(tmp); + g_free(fname); + closedir(dir); + return -1; + } + } + } + g_free(fname); + + } + g_free(tmp); + } + closedir(dir); + + 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; + GHashTable *visited; + + visited = g_hash_table_new(inode_hash, inode_equal); + + if (scan_dir(store, visited, ((CamelService *)store)->url->path, 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-spoold-store.h b/camel/providers/local/camel-spoold-store.h new file mode 100644 index 0000000000..0f80e1bdfb --- /dev/null +++ b/camel/providers/local/camel-spoold-store.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Authors: Michael Zucchi + * + * 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_SPOOLD_STORE_H +#define CAMEL_SPOOLD_STORE_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include "camel-spool-store.h" + +#define CAMEL_SPOOLD_STORE_TYPE (camel_spoold_store_get_type ()) +#define CAMEL_SPOOLD_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOLD_STORE_TYPE, CamelSpoolDStore)) +#define CAMEL_SPOOLD_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOLD_STORE_TYPE, CamelSpoolDStoreClass)) +#define CAMEL_IS_SPOOLD_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOLD_STORE_TYPE)) + + +typedef struct { + CamelSpoolStore parent_object; + +} CamelSpoolDStore; + + + +typedef struct { + CamelSpoolStoreClass parent_class; + +} CamelSpoolDStoreClass; + + +/* public methods */ + +/* Standard Camel function */ +CamelType camel_spoold_store_get_type (void); + +const gchar *camel_spoold_store_get_toplevel_dir (CamelSpoolDStore *store); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_SPOOLD_STORE_H */ + + diff --git a/camel/providers/local/libcamellocal.urls b/camel/providers/local/libcamellocal.urls index 207c19a98f..e2279ed72a 100644 --- a/camel/providers/local/libcamellocal.urls +++ b/camel/providers/local/libcamellocal.urls @@ -2,3 +2,4 @@ mh mbox maildir spool +spoold -- cgit v1.2.3