aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog43
-rw-r--r--camel/camel-store-summary.c2
-rw-r--r--camel/camel-store.c38
-rw-r--r--camel/providers/imap/camel-imap-store-summary.c114
-rw-r--r--camel/providers/imap/camel-imap-store-summary.h4
-rw-r--r--camel/providers/imap/camel-imap-store.c100
-rw-r--r--camel/providers/imap/camel-imap-store.h1
7 files changed, 215 insertions, 87 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 410266a4ef..5c7fe65570 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,46 @@
+2002-10-24 Not Zed <NotZed@Ximian.com>
+
+ ** For bug #31647 and bug #31456.
+
+ * camel-store-summary.c (store_info_string): for STORE_INFO_NAME,
+ skip the leading /.
+
+ * providers/imap/camel-imap-store.c
+ (parse_list_response_as_folder_info): Remove jeff's last patch,
+ and use the store summary to create the name and path of the
+ folderinfo so it manages namespace issues.
+ (get_folder_info_online): Just pass @top directly to
+ build_folder_info always, since namespace is mapped to 1 tree
+ level.
+ (imap_build_folder_info): Remove jeff's last patch, dont strip
+ leading /'s, they shouldn't exist.
+ (imap_connect_online): Remove adding the INBOX here, we add it
+ later.
+ (get_subscribed_folders): Make sure INBOX is always in the list.
+ some imap servers dont seem to let you subscribe to it(?), so
+ always have it act as subscribed.
+
+ * camel-store.c (camel_folder_info_build): back out the last 2
+ patches from Jeff (for #31456) to get the original behaviour.
+ (camel_folder_info_build): When creating a fake
+ parent, dont strip the namespace from the full_name. malloc keys
+ in hash since we dont have them anymore.
+ (free_name): Helper to free names.
+
+ * providers/imap/camel-imap-store-summary.c
+ (camel_imap_store_summary_namespace_new): Canonicalise the
+ namespace (strip trailing dir_sep), and change the path to remove
+ any /'s.
+ (camel_imap_store_summary_namespace_find_path):
+ (camel_imap_store_summary_namespace_find_full): new, find
+ namespace by path/full name.
+ (camel_imap_store_summary_full_from_path): Changed to a simple
+ wrapper around path_to_full, after checking namespace.
+ (camel_imap_store_summary_add_from_full): map the namespace if
+ present.
+ (camel_imap_store_summary_path_to_full): If namespace exists,
+ unmap it.
+
2002-10-18 Jeffrey Stedfast <fejj@ximian.com>
* camel-filter-driver.c (camel_filter_driver_filter_folder):
diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c
index fc839dfed7..f33205dd50 100644
--- a/camel/camel-store-summary.c
+++ b/camel/camel-store-summary.c
@@ -870,7 +870,7 @@ store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type)
case CAMEL_STORE_INFO_NAME:
p = strrchr(mi->path, '/');
if (p)
- return p;
+ return p+1;
else
return mi->path;
case CAMEL_STORE_INFO_URI:
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 43528a8353..d76af40e60 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -843,6 +843,12 @@ folder_info_cmp (const void *ap, const void *bp)
return strcmp (a->full_name, b->full_name);
}
+static void
+free_name(void *key, void *data, void *user)
+{
+ g_free(key);
+}
+
/**
* camel_folder_info_build:
* @folders: an array of CamelFolderInfo
@@ -873,25 +879,36 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
if (!namespace)
namespace = "";
nlen = strlen (namespace);
-
+
qsort (folders->pdata, folders->len, sizeof (folders->pdata[0]), folder_info_cmp);
/* Hash the folders. */
hash = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < folders->len; i++) {
fi = folders->pdata[i];
- g_hash_table_insert (hash, fi->full_name, fi);
+ if (!strncmp (namespace, fi->full_name, nlen))
+ name = fi->full_name + nlen;
+ else
+ name = fi->full_name;
+ if (*name == separator)
+ name++;
+ g_hash_table_insert (hash, g_strdup(name), fi);
}
/* Now find parents. */
for (i = 0; i < folders->len; i++) {
fi = folders->pdata[i];
- name = fi->full_name;
-
+ if (!strncmp (namespace, fi->full_name, nlen))
+ name = fi->full_name + nlen;
+ else
+ name = fi->full_name;
+ if (*name == separator)
+ name++;
+
/* set the path if it isn't already set */
if (!fi->path)
camel_folder_info_build_path (fi, separator);
-
+
p = strrchr (name, separator);
if (p) {
pname = g_strndup (name, p - name);
@@ -903,9 +920,8 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
create a fake folder node */
CamelURL *url;
char *sep;
-
+
pfi = g_new0 (CamelFolderInfo, 1);
- pfi->full_name = pname;
if (short_names) {
pfi->name = strrchr (pname, separator);
if (pfi->name)
@@ -914,7 +930,8 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
pfi->name = g_strdup (pname);
} else
pfi->name = g_strdup (pname);
-
+
+ /* FIXME: url's with fragments should have the fragment truncated, not path */
url = camel_url_new (fi->url, NULL);
sep = strrchr (url->path, separator);
if (sep)
@@ -922,11 +939,13 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
else
d(g_warning ("huh, no \"%c\" in \"%s\"?", separator, fi->url));
+ pfi->full_name = g_strdup(url->path+1);
+
/* since this is a "fake" folder node, it is not selectable */
camel_url_set_param (url, "noselect", "yes");
pfi->url = camel_url_to_string (url, 0);
camel_url_free (url);
-
+
g_hash_table_insert (hash, pname, pfi);
g_ptr_array_add (folders, pfi);
}
@@ -936,6 +955,7 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
} else if (!top)
top = fi;
}
+ g_hash_table_foreach(hash, free_name, NULL);
g_hash_table_destroy (hash);
/* Link together the top-level folders */
diff --git a/camel/providers/imap/camel-imap-store-summary.c b/camel/providers/imap/camel-imap-store-summary.c
index 4ba5bb9b68..9cdebba3e9 100644
--- a/camel/providers/imap/camel-imap-store-summary.c
+++ b/camel/providers/imap/camel-imap-store-summary.c
@@ -214,6 +214,7 @@ camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path
int state=0;
char *subpath, *last = NULL;
CamelStoreInfo *si;
+ CamelImapStoreNamespace *ns;
/* check to see if we have a subpath of path already defined */
subpath = alloca(strlen(path)+1);
@@ -234,11 +235,16 @@ camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path
return f;
}
+ ns = camel_imap_store_summary_namespace_find_path(s, path);
+
f = full = alloca(strlen(path)*2+1);
if (si)
p = path + strlen(subpath);
+ else if (ns)
+ p = path + strlen(ns->path);
else
p = path;
+
while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) {
switch(state) {
case 0:
@@ -270,18 +276,31 @@ camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path
g_free(f);
camel_store_summary_info_free((CamelStoreSummary *)s, si);
f = full;
+ } else if (ns) {
+ full = g_strdup_printf("%s%s", ns->full_name, f);
+ g_free(f);
+ f = full;
}
return f;
}
CamelImapStoreInfo *
-camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep)
+camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full, char dir_sep)
{
CamelImapStoreInfo *info;
- char *pathu8;
+ char *pathu8, *prefix;
+ int len;
+ char *full_name;
+ CamelImapStoreNamespace *ns;
+
+ d(printf("adding full name '%s' '%c'\n", full, dir_sep));
- d(printf("adding full name '%s' '%c'\n", full_name, dir_sep));
+ len = strlen(full);
+ full_name = alloca(len+1);
+ strcpy(full_name, full);
+ if (full_name[len-1] == dir_sep)
+ full_name[len-1] = 0;
info = camel_imap_store_summary_full_name(s, full_name);
if (info) {
@@ -290,7 +309,24 @@ camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *ful
return info;
}
- pathu8 = camel_imap_store_summary_full_to_path(s, full_name, dir_sep);
+ ns = camel_imap_store_summary_namespace_find_full(s, full_name);
+ if (ns) {
+ d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path));
+ len = strlen(ns->full_name);
+ if (len >= strlen(full_name)) {
+ pathu8 = g_strdup(ns->path);
+ } else {
+ if (full_name[len] == ns->sep)
+ len++;
+ prefix = camel_imap_store_summary_full_to_path(s, full_name+len, ns->sep);
+ pathu8 = g_strdup_printf("%s/%s", ns->path, prefix);
+ g_free(prefix);
+ }
+ d(printf(" (pathu8 = '%s')", pathu8));
+ } else {
+ d(printf("(Cannot find namespace for '%s')\n", full_name));
+ 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) {
@@ -303,30 +339,44 @@ camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *ful
}
/* should this be const? */
+/* TODO: deprecate/merge this function with path_to_full */
char *
camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path)
{
CamelImapStoreInfo *si;
+ CamelImapStoreNamespace *ns;
+ char *name = NULL;
- si = (CamelImapStoreInfo *)camel_store_summary_path((CamelStoreSummary *)s, path);
+ ns = camel_imap_store_summary_namespace_find_path(s, path);
+ if (ns)
+ name = camel_imap_store_summary_path_to_full(s, path, ns->sep);
- d(printf("looking up path %s -> %s\n", path, si?si->full_name:"not found"));
+ d(printf("looking up path %s -> %s\n", path, name?name:"not found"));
- if (si)
- return g_strdup(si->full_name);
-
- return NULL;
+ return name;
}
/* 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;
+ char *p;
+ int len;
+ GString *tmp;
ns = g_malloc0(sizeof(*ns));
ns->full_name = g_strdup(full_name);
+ len = strlen(ns->full_name)-1;
+ if (len >= 0 && ns->full_name[len] == dir_sep)
+ ns->full_name[len] = 0;
ns->sep = dir_sep;
- ns->path = camel_imap_store_summary_full_to_path(s, full_name, dir_sep);
+
+ p = ns->path = camel_imap_store_summary_full_to_path(s, ns->full_name, dir_sep);
+ while (*p) {
+ if (*p == '/')
+ *p = '.';
+ p++;
+ }
return ns;
}
@@ -335,11 +385,53 @@ void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapS
{
static void namespace_clear(CamelStoreSummary *s);
+ d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path));
namespace_clear((CamelStoreSummary *)s);
s->namespace = ns;
camel_store_summary_touch((CamelStoreSummary *)s);
}
+CamelImapStoreNamespace *
+camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path)
+{
+ int len;
+ CamelImapStoreNamespace *ns;
+
+ /* NB: this currently only compares against 1 namespace, in future compare against others */
+ ns = s->namespace;
+ while (ns) {
+ len = strlen(ns->path);
+ if (strncmp(ns->path, path, len) == 0
+ && (path[len] == '/' || path[len] == 0))
+ break;
+ ns = NULL;
+ }
+
+ /* have a default? */
+ return ns;
+}
+
+CamelImapStoreNamespace *
+camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full)
+{
+ int len;
+ CamelImapStoreNamespace *ns;
+
+ /* NB: this currently only compares against 1 namespace, in future compare against others */
+ ns = s->namespace;
+ while (ns) {
+ len = strlen(ns->full_name);
+ d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full));
+ if (strncmp(ns->full_name, full, len) == 0
+ && (full[len] == ns->sep || full[len] == 0))
+ break;
+ ns = NULL;
+ }
+
+ /* have a default? */
+ return ns;
+}
+
static void
namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns)
{
diff --git a/camel/providers/imap/camel-imap-store-summary.h b/camel/providers/imap/camel-imap-store-summary.h
index 013283b5c1..0fa6be0df3 100644
--- a/camel/providers/imap/camel-imap-store-summary.h
+++ b/camel/providers/imap/camel-imap-store-summary.h
@@ -76,9 +76,11 @@ struct _CamelImapStoreSummaryClass {
CamelType camel_imap_store_summary_get_type (void);
CamelImapStoreSummary *camel_imap_store_summary_new (void);
-/* TODO: this api needs some more work */
+/* TODO: this api needs some more work, needs to support lists */
CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep);
void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns);
+CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path);
+CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full_name);
/* converts to/from utf8 canonical nasmes */
char *camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep);
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 1da03ffdef..ac8d3e93ab 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -816,31 +816,26 @@ imap_build_folder_info(CamelImapStore *imap_store, const char *folder_name)
CamelURL *url;
const char *name;
CamelFolderInfo *fi;
-
+
fi = g_malloc0(sizeof(*fi));
-
+
fi->full_name = g_strdup(folder_name);
fi->unread_message_count = 0;
-
+
url = camel_url_new (imap_store->base_url, NULL);
g_free (url->path);
url->path = g_strdup_printf ("/%s", folder_name);
fi->url = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_url_free(url);
-
- /* strip extranious leading /'s */
- while (*folder_name == '/')
- folder_name++;
-
fi->path = g_strdup_printf("/%s", folder_name);
name = strrchr (fi->path, '/');
if (name)
name++;
else
name = fi->path;
-
+
fi->name = g_strdup (name);
-
+
return fi;
}
@@ -1271,33 +1266,29 @@ imap_connect_online (CamelService *service, CamelException *ex)
/* canonicalize the namespace to end with dir_sep */
len = strlen (store->namespace);
if (len && store->namespace[len - 1] != store->dir_sep) {
- char *tmp;
+ gchar *tmp;
tmp = g_strdup_printf ("%s%c", store->namespace, store->dir_sep);
g_free (store->namespace);
store->namespace = tmp;
}
-
+
ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep);
camel_imap_store_summary_namespace_set(store->summary, ns);
if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) {
GPtrArray *folders;
char *pattern;
-
+
/* this pre-fills the summary, and checks that lsub is useful */
- folders = g_ptr_array_new ();
- pattern = g_strdup_printf ("%s*", store->namespace);
- get_folders_online (store, pattern, folders, TRUE, ex);
- g_free (pattern);
-
- /* if we have a namespace, then our LSUB won't include INBOX so LSUB for the INBOX too */
- if (*store->namespace && !camel_exception_is_set (ex))
- get_folders_online (store, "INBOX", folders, TRUE, ex);
-
+ folders = g_ptr_array_new();
+ pattern = g_strdup_printf("%s*", store->namespace);
+ get_folders_online(store, pattern, folders, TRUE, ex);
+ g_free(pattern);
+
for (i=0;i<folders->len;i++) {
CamelFolderInfo *fi = folders->pdata[i];
-
+
if (fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED))
store->capabilities |= IMAP_CAPABILITY_useful_lsub;
camel_folder_info_free(fi);
@@ -1312,7 +1303,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
done:
/* save any changes we had */
camel_store_summary_save((CamelStoreSummary *)store->summary);
-
+
CAMEL_SERVICE_UNLOCK (store, connect_lock);
if (camel_exception_is_set (ex))
@@ -1926,19 +1917,17 @@ parse_list_response_as_folder_info (CamelImapStore *imap_store,
const char *response)
{
CamelFolderInfo *fi;
- int flags;
- char sep, *dir, *name = NULL, *path, *p;
+ int flags, i;
+ char sep, *dir, *name = NULL, *path;
CamelURL *url;
CamelImapStoreInfo *si;
guint32 newflags;
-
+
if (!imap_parse_list_response (imap_store, response, &flags, &sep, &dir))
return NULL;
-
+
/* FIXME: should use imap_build_folder_info, note the differences with param setting tho */
- path = camel_utf7_utf8(dir);
-
- /* hack: pokes in value from any list response */
+
si = camel_imap_store_summary_add_from_full(imap_store->summary, dir, sep?sep:'/');
newflags = (si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) | (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
if (si->info.flags != newflags) {
@@ -1946,45 +1935,24 @@ parse_list_response_as_folder_info (CamelImapStore *imap_store,
camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
}
- if (sep && sep != '/') {
- for (p = path; *p; p++) {
- if (*p == sep)
- *p = '/';
- }
- }
-
- if ((name = strrchr (path, '/'))) {
- name++;
- if (!*name) {
- g_free(dir);
- g_free(path);
- return NULL;
- }
- } else
- name = path;
-
fi = g_new0 (CamelFolderInfo, 1);
fi->flags = flags;
- fi->name = g_strdup (name);
- fi->full_name = path;
-
- while (*path == '/')
- path++;
- fi->path = g_strdup_printf ("/%s", path);
+ fi->name = g_strdup(camel_store_info_name(imap_store->summary, si));
+ fi->path = g_strdup_printf("/%s", camel_store_info_path(imap_store->summary, si));
+ fi->full_name = g_strdup(fi->path+1);
url = camel_url_new (imap_store->base_url, NULL);
- g_free (url->path);
- url->path = g_strdup_printf ("/%s", fi->full_name);
-
+ camel_url_set_path(url, fi->path);
+
if (flags & CAMEL_FOLDER_NOSELECT || fi->name[0] == 0)
camel_url_set_param (url, "noselect", "yes");
fi->url = camel_url_to_string (url, 0);
camel_url_free (url);
-
+
/* FIXME: redundant */
if (flags & CAMEL_IMAP_FOLDER_UNMARKED)
fi->unread_message_count = -1;
-
+
return fi;
}
@@ -1998,16 +1966,19 @@ get_subscribed_folders (CamelImapStore *imap_store, const char *top, CamelExcept
CamelImapResponse *response;
CamelFolderInfo *fi;
char *result;
+ int haveinbox = FALSE;
folders = g_ptr_array_new ();
names = g_ptr_array_new ();
for (i=0;(si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i));i++) {
- if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)
+ if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) {
g_ptr_array_add(names, (char *)camel_imap_store_info_full_name(imap_store->summary, si));
+ haveinbox = haveinbox || strcasecmp(camel_imap_store_info_full_name(imap_store->summary, si), "INBOX") == 0;
+ }
camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
}
-
- if (names->len == 0)
+
+ if (!haveinbox)
g_ptr_array_add (names, "INBOX");
for (i = 0; i < names->len; i++) {
@@ -2399,14 +2370,13 @@ get_folder_info_online (CamelStore *store, const char *top, guint32 flags, Camel
if (folders == NULL)
return NULL;
- /* note the weird top stuff, it is so a namespace based list "" is properly tree-ised */
- tree = camel_folder_info_build(folders, top[0] == 0 && imap_store->namespace?"":top, '/', TRUE);
+ tree = camel_folder_info_build(folders, top, '/', TRUE);
g_ptr_array_free(folders, TRUE);
if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST))
get_folder_counts(imap_store, tree, ex);
- dumpfi(tree);
+ d(dumpfi(tree));
camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
return tree;
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index 38df1880a0..d461b51440 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -114,6 +114,7 @@ struct _CamelImapStore {
/* Information about the server */
CamelImapServerLevel server_level;
guint32 capabilities, parameters;
+ /* NB: namespace should be handled by summary->namespace */
char *namespace, dir_sep, *base_url, *storage_path;
GHashTable *authtypes;