aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog12
-rw-r--r--camel/camel-store.c11
-rw-r--r--camel/providers/imap/camel-imap-folder.c2
-rw-r--r--camel/providers/imap/camel-imap-store.c150
-rw-r--r--camel/providers/imap/camel-imap-store.h4
5 files changed, 119 insertions, 60 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 59f88d6220..35134971cd 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,17 @@
2001-10-29 Jeffrey Stedfast <fejj@ximian.com>
+ * providers/imap/camel-imap-store.c (subscribe_folder): Don't emit
+ a folder_subscribed signal if we are in the process of renaming
+ folders.
+ (unsubscribe_folder): Same here but for the unsubscribe signal.
+ (rename_folder): Unsubscribe from the folder being renamed and any
+ subfolders it may have before actually renaming. Once the folder
+ has been renamed, re-subscribe to it and it's subfolders with the
+ new name.
+
+ * camel-store.c (camel_folder_info_build): Sort the folder info's
+ before constructing the tree.
+
* camel-mime-utils.c (header_decode_param): Minor fix - should
have been using a strNcmp when checking if it was an rfc2047
encoded word.
diff --git a/camel/camel-store.c b/camel/camel-store.c
index d98df75d55..5fd2032239 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -802,6 +802,15 @@ camel_folder_info_build_path (CamelFolderInfo *fi, char separator)
}
}
+static int
+folder_info_cmp (const void *ap, const void *bp)
+{
+ const CamelFolderInfo *a = ((CamelFolderInfo **)ap)[0];
+ const CamelFolderInfo *b = ((CamelFolderInfo **)bp)[0];
+
+ return strcmp (a->full_name, b->full_name);
+}
+
/**
* camel_folder_info_build:
* @folders: an array of CamelFolderInfo
@@ -833,6 +842,8 @@ camel_folder_info_build (GPtrArray *folders, const char *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++) {
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index adc43514a0..c353b040a7 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -372,7 +372,7 @@ imap_finalize (CamelObject *object)
}
static void
-imap_rename(CamelFolder *folder, const char *new)
+imap_rename (CamelFolder *folder, const char *new)
{
CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
CamelImapStore *imap_store = (CamelImapStore *)folder->parent_store;
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 5e7cd62bf6..ca5af7d3c9 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -1102,32 +1102,50 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
}
}
-struct _fix_subscribe {
- char dir_sep;
-
- const char *old_name;
- const char *new_name;
+static void
+manage_subscriptions (CamelStore *store, CamelFolderInfo *fi, gboolean subscribe)
+{
+ while (fi) {
+ if (fi->child)
+ manage_subscriptions (store, fi->child, subscribe);
+
+ if (subscribe)
+ subscribe_folder (store, fi->full_name, NULL);
+ else
+ unsubscribe_folder (store, fi->full_name, NULL);
+
+ fi = fi->sibling;
+ }
+}
- GPtrArray *old;
- GPtrArray *new;
-};
+#define subscribe_folders(store, fi) manage_subscriptions (store, fi, TRUE)
+#define unsubscribe_folders(store, fi) manage_subscriptions (store, fi, FALSE)
-/* Fixes subscribed names to take into account a rename */
static void
-fix_subscribed(char *key, void *val, struct _fix_subscribe *data)
+rename_folder_info (CamelImapStore *imap_store, CamelFolderInfo *fi, const char *old_name, const char *new_name)
{
- int oldlen, namelen;
-
- namelen = strlen(key);
- oldlen = strlen(data->old_name);
-
- if ((namelen == oldlen &&
- strcmp(data->old_name, key) == 0)
- || ((namelen > oldlen)
- && strncmp(data->old_name, key, oldlen) == 0
- && key[oldlen] == data->dir_sep)) {
- g_ptr_array_add(data->old, key);
- g_ptr_array_add(data->new, g_strdup_printf("%s%s", data->new_name, key+oldlen));
+ CamelImapResponse *response;
+ char *name;
+
+ while (fi) {
+ if (fi->child)
+ rename_folder_info (imap_store, fi->child, old_name, new_name);
+
+ name = g_strdup_printf ("%s%s", new_name, fi->full_name + strlen (old_name));
+
+ if (imap_store->dir_sep == '.') {
+ /* kludge around imap servers like Courier that don't rename
+ subfolders when you rename the parent folder - like
+ the spec says to do!!! */
+ response = camel_imap_command (imap_store, NULL, NULL, "RENAME %F %F", fi->full_name, name);
+ if (response)
+ camel_imap_response_free (imap_store, response);
+ }
+
+ g_free (fi->full_name);
+ fi->full_name = name;
+
+ fi = fi->sibling;
}
}
@@ -1137,7 +1155,9 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name, Ca
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
CamelImapResponse *response;
char *oldpath, *newpath;
-
+ CamelFolderInfo *fi;
+ guint32 flags;
+
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
return;
@@ -1155,47 +1175,47 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name, Ca
} else
return;
- response = camel_imap_command(imap_store, NULL, ex, "RENAME %F %F", old_name, new_name);
+ imap_store->renaming = TRUE;
- if (response)
- camel_imap_response_free (imap_store, response);
-
- if (camel_exception_is_set(ex))
+ flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE |
+ (store->flags & CAMEL_STORE_SUBSCRIPTIONS ? CAMEL_STORE_FOLDER_INFO_SUBSCRIBED : 0);
+
+ fi = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info (store, old_name, flags, ex);
+ if (fi && store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ unsubscribe_folders (store, fi);
+
+ response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %F", old_name, new_name);
+
+ if (!response) {
+ if (fi && store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ subscribe_folders (store, fi);
+
+ camel_store_free_folder_info (store, fi);
+ imap_store->renaming = FALSE;
return;
-
- /* Fix up the subscriptions table */
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) {
- struct _fix_subscribe data;
- int i;
-
- data.dir_sep = imap_store->dir_sep;
- data.old_name = old_name;
- data.new_name = new_name;
- data.old = g_ptr_array_new();
- data.new = g_ptr_array_new();
- g_hash_table_foreach(imap_store->subscribed_folders, (GHFunc)fix_subscribed, &data);
-
- for (i=0;i<data.old->len;i++) {
- printf("moving subscribed folder from '%s' to '%s'\n", (char *)data.old->pdata[i], (char *)data.new->pdata[i]);
- g_hash_table_remove(imap_store->subscribed_folders, data.old->pdata[i]);
- g_free(data.old->pdata[i]);
- g_hash_table_insert(imap_store->subscribed_folders, data.new->pdata[i], (void *)1);
- }
-
- g_ptr_array_free(data.old, TRUE);
- g_ptr_array_free(data.new, TRUE);
}
-
+
+ camel_imap_response_free (imap_store, response);
+
+ rename_folder_info (imap_store, fi, old_name, new_name);
+ if (fi && store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ subscribe_folders (store, fi);
+
+ camel_store_free_folder_info (store, fi);
+
oldpath = e_path_to_physical (imap_store->storage_path, old_name);
newpath = e_path_to_physical (imap_store->storage_path, new_name);
-
+
/* So do we care if this didn't work? Its just a cache? */
- if (rename(oldpath, newpath) == -1) {
- g_warning("Could not rename message cache '%s' to '%s': %s: cache reset", oldpath, newpath, strerror(errno));
+ if (rename (oldpath, newpath) == -1) {
+ g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset",
+ oldpath, newpath, strerror (errno));
}
- g_free(oldpath);
- g_free(newpath);
+ g_free (oldpath);
+ g_free (newpath);
+
+ imap_store->renaming = FALSE;
}
static CamelFolderInfo *
@@ -1712,7 +1732,14 @@ subscribe_folder (CamelStore *store, const char *folder_name,
g_hash_table_insert (imap_store->subscribed_folders,
g_strdup (folder_name), GUINT_TO_POINTER (1));
-
+
+ if (imap_store->renaming) {
+ /* we don't need to emit a "folder_subscribed" signal
+ if we are in the process of renaming folders, so we
+ are done here... */
+ return;
+ }
+
name = strrchr (folder_name, imap_store->dir_sep);
if (name)
name++;
@@ -1762,7 +1789,14 @@ unsubscribe_folder (CamelStore *store, const char *folder_name,
g_hash_table_remove (imap_store->subscribed_folders, key);
g_free (key);
}
-
+
+ if (imap_store->renaming) {
+ /* we don't need to emit a "folder_unsubscribed" signal
+ if we are in the process of renaming folders, so we
+ are done here... */
+ return;
+ }
+
name = strrchr (folder_name, imap_store->dir_sep);
if (name)
name++;
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index 25c416385e..09c7ddf9b2 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -91,7 +91,9 @@ struct _CamelImapStore {
guint32 capabilities, parameters;
char *namespace, dir_sep, *base_url, *storage_path;
GHashTable *authtypes, *subscribed_folders;
-
+
+ gboolean renaming;
+
#ifdef ENABLE_THREADS
EThread *async_thread;
#endif