aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-store-summary.c
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2002-09-03 22:55:03 +0800
committerMichael Zucci <zucchi@src.gnome.org>2002-09-03 22:55:03 +0800
commit5e144756c987f97f4289d554d9bcdf222cd9b326 (patch)
tree825dfc4f57e5fade9bd8b31d3dfb0da03fc25801 /camel/providers/imap/camel-imap-store-summary.c
parentcac5803b45b39a56744dc5c9dea08bcd495c65b4 (diff)
downloadgsoc2013-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.c519
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;
+ }
+}