diff options
author | Not Zed <NotZed@Ximian.com> | 2002-09-03 22:55:03 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2002-09-03 22:55:03 +0800 |
commit | 5e144756c987f97f4289d554d9bcdf222cd9b326 (patch) | |
tree | 825dfc4f57e5fade9bd8b31d3dfb0da03fc25801 /camel/providers/imap/camel-imap-store-summary.c | |
parent | cac5803b45b39a56744dc5c9dea08bcd495c65b4 (diff) | |
download | gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar.gz gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar.bz2 gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar.lz gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar.xz gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.tar.zst gsoc2013-evolution-5e144756c987f97f4289d554d9bcdf222cd9b326.zip |
Lots of changes, too numerous to list. Changed to use
2002-09-04 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-store.c,
providers/imap/camel-imap-folder.c: Lots of changes, too numerous
to list. Changed to use camel-imap-store-summary to cache list
requests. Changed to use a canonicalised url path with / instead
of per-store directory separator. Indirects folder name so
invalid folder names can still be accessed. Summary now stored in
a new expandable format in .ev-store-summary.
2002-08-28 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-store.c (construct): Load store
summary if it exists.
(can_work_offline): Just see if we have any folders to say whether
we can work offline or not. Should probably always just return
true.
2002-08-27 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-store-summary.[ch]: New files to
handle offline definition of folders, etc.
* camel-url.h: Define CamelURL to be struct _CamelURL rather than
anonymous struct.
* camel-store-summary.[ch]: a few api tweaks. Also, the summary
header is versioned separately at each level, so that version
upgrades can be handled separately. Renamed FolderInfo ->
StoreInfo to avoid namespace with current FolderInfo code. This
should be reversed when the FolderInfo code is rationalised to
this new base.
2002-08-23 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-command.c (camel_imap_command): domt
encode folder name.
* providers/imap/camel-imap-folder.c (do_copy): dont encode folder
name.
(do_append): dont encode folder name.
* providers/imap/camel-imap-store.c (get_folder_status): don
encode folder name in imap request.
(get_folder_online): here too for creating folder.
(rename_folder): Assume the incoming 'new name' is a utf8 path,
whereas the 'old name' is as from get folder info (raw).
(create_folder): Dont encode parent_name, assume its the raw
thing.
2002-08-22 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-store.c (get_folder_online): Select
based on unconverted name.
(imap_build_folder_info): New function to create a folderinfo
properly based on raw name.
(subscribe_folder): Use above helper.
(imap_folder_effectively_unsubscribed): Same here.
(imap_forget_folder): Same here.
(get_one_folder_offline): "
2002-08-21 Not Zed <NotZed@Ximian.com>
* providers/imap/camel-imap-store.c
(parse_list_response_as_folder_info): Setup path properly, as
decoded path with / separator. Setup full_name as non-decoded raw
name. Keep url as decoded path but with server separator
... (ick).
(create_folder): Dont call build_path anymore, get_folders() does
it for us.
(subscribe_folder): Build the path ourself.
(imap_folder_effectively_unsubscribed): Same here.
(get_subscribed_folders): list using %S not %F, we're using the
raw server provided name directly.
(subscribe_folder): As above, for SUBSCRIBE.
(unsubscribe_folder): Same here.
(delete_folder): Same.
(rename_folder_info): Same here for source name.
(rename_folder): And here?
(get_folders_online): Amd here.
* providers/imap/camel-imap-utils.c:
(imap_parse_list_response): Dont decode the mailbox.
* camel-utf8.[ch]: some new utf8 & utf7 utilities.
* providers/imap/camel-imap-utils.c (imap_mailbox_encode):
(imap_mailbox_decode): use camel_utf7/8* functions instead.
: Add config.h and alloca.h headers.
svn path=/trunk/; revision=17943
Diffstat (limited to 'camel/providers/imap/camel-imap-store-summary.c')
-rw-r--r-- | camel/providers/imap/camel-imap-store-summary.c | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/camel/providers/imap/camel-imap-store-summary.c b/camel/providers/imap/camel-imap-store-summary.c new file mode 100644 index 0000000000..4ba5bb9b68 --- /dev/null +++ b/camel/providers/imap/camel-imap-store-summary.c @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2002 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 <unistd.h> +#include <ctype.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include "camel-imap-store-summary.h" + +#include "camel-file-utils.h" + +#include "hash-table-utils.h" +#include "e-util/md5-utils.h" +#include "e-util/e-memory.h" + +#include "camel-private.h" +#include "camel-utf8.h" + +#define d(x) +#define io(x) /* io debug */ + +#define CAMEL_IMAP_STORE_SUMMARY_VERSION_0 (0) + +#define CAMEL_IMAP_STORE_SUMMARY_VERSION (0) + +#define _PRIVATE(o) (((CamelImapStoreSummary *)(o))->priv) + +static int summary_header_load(CamelStoreSummary *, FILE *); +static int summary_header_save(CamelStoreSummary *, FILE *); + +/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ +static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); +static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); +static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); + +static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); +static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); + +static void camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass); +static void camel_imap_store_summary_init (CamelImapStoreSummary *obj); +static void camel_imap_store_summary_finalise (CamelObject *obj); + +static CamelStoreSummaryClass *camel_imap_store_summary_parent; + +static void +camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass) +{ + CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; + + ssklass->summary_header_load = summary_header_load; + ssklass->summary_header_save = summary_header_save; + + /*ssklass->store_info_new = store_info_new;*/ + ssklass->store_info_load = store_info_load; + ssklass->store_info_save = store_info_save; + ssklass->store_info_free = store_info_free; + + ssklass->store_info_string = store_info_string; + ssklass->store_info_set_string = store_info_set_string; +} + +static void +camel_imap_store_summary_init (CamelImapStoreSummary *s) +{ + /*struct _CamelImapStoreSummaryPrivate *p; + + p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ + + ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelImapStoreInfo); + s->version = CAMEL_IMAP_STORE_SUMMARY_VERSION; +} + +static void +camel_imap_store_summary_finalise (CamelObject *obj) +{ + /*struct _CamelImapStoreSummaryPrivate *p;*/ + /*CamelImapStoreSummary *s = (CamelImapStoreSummary *)obj;*/ + + /*p = _PRIVATE(obj); + g_free(p);*/ +} + +CamelType +camel_imap_store_summary_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + camel_imap_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); + type = camel_type_register((CamelType)camel_imap_store_summary_parent, "CamelImapStoreSummary", + sizeof (CamelImapStoreSummary), + sizeof (CamelImapStoreSummaryClass), + (CamelObjectClassInitFunc) camel_imap_store_summary_class_init, + NULL, + (CamelObjectInitFunc) camel_imap_store_summary_init, + (CamelObjectFinalizeFunc) camel_imap_store_summary_finalise); + } + + return type; +} + +/** + * camel_imap_store_summary_new: + * + * Create a new CamelImapStoreSummary object. + * + * Return value: A new CamelImapStoreSummary widget. + **/ +CamelImapStoreSummary * +camel_imap_store_summary_new (void) +{ + CamelImapStoreSummary *new = CAMEL_IMAP_STORE_SUMMARY ( camel_object_new (camel_imap_store_summary_get_type ())); + + return new; +} + +/** + * camel_imap_store_summary_full_name: + * @s: + * @path: + * + * Retrieve a summary item by full name. + * + * A referenced to the summary item is returned, which may be + * ref'd or free'd as appropriate. + * + * Return value: The summary item, or NULL if the @full_name name + * is not available. + * It must be freed using camel_store_summary_info_free(). + **/ +CamelImapStoreInfo * +camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name) +{ + int count, i; + CamelImapStoreInfo *info; + + count = camel_store_summary_count((CamelStoreSummary *)s); + for (i=0;i<count;i++) { + info = (CamelImapStoreInfo *)camel_store_summary_index((CamelStoreSummary *)s, i); + if (info) { + if (strcmp(info->full_name, full_name) == 0) + return info; + camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); + } + } + + return NULL; +} + +char * +camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep) +{ + char *path, *p; + int c; + const char *f; + + if (dir_sep != '/') { + p = path = alloca(strlen(full_name)*3+1); + f = full_name; + while ( (c = *f++ & 0xff) ) { + if (c == dir_sep) + *p++ = '/'; + else if (c == '/' || c == '%') + p += sprintf(p, "%%%02X", c); + else + *p++ = c; + } + *p = 0; + } else + path = (char *)full_name; + + return camel_utf7_utf8(path); +} + +static guint32 hexnib(guint32 c) +{ + if (c >= '0' && c <= '9') + return c-'0'; + else if (c>='A' && c <= 'Z') + return c-'A'+10; + else + return 0; +} + +char * +camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep) +{ + unsigned char *full, *f; + guint32 c, v = 0; + const char *p; + int state=0; + char *subpath, *last = NULL; + CamelStoreInfo *si; + + /* check to see if we have a subpath of path already defined */ + subpath = alloca(strlen(path)+1); + strcpy(subpath, path); + do { + si = camel_store_summary_path((CamelStoreSummary *)s, subpath); + if (si == NULL) { + last = strrchr(subpath, '/'); + if (last) + *last = 0; + } + } while (si == NULL && last); + + /* path is already present, use the raw version we have */ + if (si && strlen(subpath) == strlen(path)) { + f = g_strdup(camel_imap_store_info_full_name(s, si)); + camel_store_summary_info_free((CamelStoreSummary *)s, si); + return f; + } + + f = full = alloca(strlen(path)*2+1); + if (si) + p = path + strlen(subpath); + else + p = path; + while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) { + switch(state) { + case 0: + if (c == '%') + state = 1; + else { + if (c == '/') + c = dir_sep; + camel_utf8_putc(&f, c); + } + break; + case 1: + state = 2; + v = hexnib(c)<<4; + break; + case 2: + state = 0; + v |= hexnib(c); + camel_utf8_putc(&f, v); + break; + } + } + camel_utf8_putc(&f, c); + + /* merge old path part if required */ + f = camel_utf8_utf7(full); + if (si) { + full = g_strdup_printf("%s%s", camel_imap_store_info_full_name(s, si), f); + g_free(f); + camel_store_summary_info_free((CamelStoreSummary *)s, si); + f = full; + } + + return f; +} + +CamelImapStoreInfo * +camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep) +{ + CamelImapStoreInfo *info; + char *pathu8; + + d(printf("adding full name '%s' '%c'\n", full_name, dir_sep)); + + info = camel_imap_store_summary_full_name(s, full_name); + if (info) { + camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); + d(printf(" already there\n")); + return info; + } + + pathu8 = camel_imap_store_summary_full_to_path(s, full_name, dir_sep); + + info = (CamelImapStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8); + if (info) { + d(printf(" '%s' -> '%s'\n", pathu8, full_name)); + camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAP_STORE_INFO_FULL_NAME, full_name); + } else + d(printf(" failed\n")); + + return info; +} + +/* should this be const? */ +char * +camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path) +{ + CamelImapStoreInfo *si; + + si = (CamelImapStoreInfo *)camel_store_summary_path((CamelStoreSummary *)s, path); + + d(printf("looking up path %s -> %s\n", path, si?si->full_name:"not found")); + + if (si) + return g_strdup(si->full_name); + + return NULL; +} + +/* TODO: this api needs some more work */ +CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep) +{ + CamelImapStoreNamespace *ns; + + ns = g_malloc0(sizeof(*ns)); + ns->full_name = g_strdup(full_name); + ns->sep = dir_sep; + ns->path = camel_imap_store_summary_full_to_path(s, full_name, dir_sep); + + return ns; +} + +void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns) +{ + static void namespace_clear(CamelStoreSummary *s); + + namespace_clear((CamelStoreSummary *)s); + s->namespace = ns; + camel_store_summary_touch((CamelStoreSummary *)s); +} + +static void +namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns) +{ + g_free(ns->path); + g_free(ns->full_name); + g_free(ns); +} + +static void +namespace_clear(CamelStoreSummary *s) +{ + CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; + + if (is->namespace) + namespace_free(s, is->namespace); + is->namespace = NULL; +} + +static CamelImapStoreNamespace * +namespace_load(CamelStoreSummary *s, FILE *in) +{ + CamelImapStoreNamespace *ns; + guint32 sep = '/'; + + ns = g_malloc0(sizeof(*ns)); + if (camel_file_util_decode_string(in, &ns->path) == -1 + || camel_file_util_decode_string(in, &ns->full_name) == -1 + || camel_file_util_decode_uint32(in, &sep) == -1) { + namespace_free(s, ns); + ns = NULL; + } else { + ns->sep = sep; + } + + return ns; +} + +static int +namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns) +{ + if (camel_file_util_encode_string(in, ns->path) == -1 + || camel_file_util_encode_string(in, ns->full_name) == -1 + || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) + return -1; + + return 0; +} + +static int +summary_header_load(CamelStoreSummary *s, FILE *in) +{ + CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; + gint32 version, capabilities, count; + + namespace_clear(s); + + if (camel_imap_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1 + || camel_file_util_decode_fixed_int32(in, &version) == -1) + return -1; + + is->version = version; + + if (version < CAMEL_IMAP_STORE_SUMMARY_VERSION_0) { + g_warning("Store summary header version too low"); + return -1; + } + + /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ + if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 + || camel_file_util_decode_fixed_int32(in, &count) == -1 + || count > 1) + return -1; + + is->capabilities = capabilities; + if (count == 1) { + if ((is->namespace = namespace_load(s, in)) == NULL) + return -1; + } + + return 0; +} + +static int +summary_header_save(CamelStoreSummary *s, FILE *out) +{ + CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; + guint32 count; + + count = is->namespace?1:0; + + /* always write as latest version */ + if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 + || camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1 + || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 + || camel_file_util_encode_fixed_int32(out, count) == -1) + return -1; + + if (is->namespace && namespace_save(s, out, is->namespace) == -1) + return -1; + + return 0; +} + +static CamelStoreInfo * +store_info_load(CamelStoreSummary *s, FILE *in) +{ + CamelImapStoreInfo *mi; + + mi = (CamelImapStoreInfo *)camel_imap_store_summary_parent->store_info_load(s, in); + if (mi) { + if (camel_file_util_decode_string(in, &mi->full_name) == -1) { + camel_store_summary_info_free(s, (CamelStoreInfo *)mi); + mi = NULL; + } + } + + return (CamelStoreInfo *)mi; +} + +static int +store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) +{ + CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; + + if (camel_imap_store_summary_parent->store_info_save(s, out, mi) == -1 + || camel_file_util_encode_string(out, isi->full_name) == -1) + return -1; + + return 0; +} + +static void +store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) +{ + CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; + + g_free(isi->full_name); + camel_imap_store_summary_parent->store_info_free(s, mi); +} + +static const char * +store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) +{ + CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; + + /* FIXME: Locks? */ + + g_assert (mi != NULL); + + switch (type) { + case CAMEL_IMAP_STORE_INFO_FULL_NAME: + return isi->full_name; + default: + return camel_imap_store_summary_parent->store_info_string(s, mi, type); + } +} + +static void +store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) +{ + CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; + + g_assert(mi != NULL); + + switch(type) { + case CAMEL_IMAP_STORE_INFO_FULL_NAME: + d(printf("Set full name %s -> %s\n", isi->full_name, str)); + CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); + g_free(isi->full_name); + isi->full_name = g_strdup(str); + CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); + break; + default: + camel_imap_store_summary_parent->store_info_set_string(s, mi, type, str); + break; + } +} |