From 921c64fb60dfb696590d45f2521a041213a91b0a Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Mon, 29 Oct 2001 23:23:12 +0000 Subject: Don't emit a folder_subscribed signal if we are in the process of renaming 2001-10-29 Jeffrey Stedfast * 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. svn path=/trunk/; revision=14378 --- camel/ChangeLog | 12 +++ camel/camel-store.c | 11 +++ camel/providers/imap/camel-imap-folder.c | 2 +- camel/providers/imap/camel-imap-store.c | 150 +++++++++++++++++++------------ camel/providers/imap/camel-imap-store.h | 4 +- 5 files changed, 119 insertions(+), 60 deletions(-) (limited to 'camel') 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 + * 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;ilen;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 -- cgit v1.2.3