diff options
-rw-r--r-- | camel/ChangeLog | 23 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 263 | ||||
-rw-r--r-- | mail/ChangeLog | 14 | ||||
-rw-r--r-- | mail/mail-folder-cache.c | 11 | ||||
-rw-r--r-- | mail/subscribe-dialog.c | 1 |
5 files changed, 216 insertions, 96 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 22355a69b7..ed4b1c1477 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,26 @@ +2002-07-29 Peter Williams <peterw@ximian.com> + + Fix bug #28238 + + * providers/imap/camel-imap-store.c (imap_forget_folder): New + function, breaking out the code in delete_folder() to handle when + a folder is removed. + (imap_folder_effectively_unsubscribed): New function, breaking out + the code in unsubscribe_folder() to handle when a folder is + unsubscribed. + (imap_check_folder_still_extant): New function, check whether a + folder exists by LIST'ing it. + (imap_store_refresh_folders): Add code here to check if the folder + still exists if we're unable to refresh its info. If so, pretend + that it was unsubscribed (to get the mailer to remove it from + the tree) and delete its cache. If somehow this goofs up, the + worst that can happen is that we must redownload the headers. + (get_folder_status): If we can't get the status, behave as above. + (delete_folder): Call imap_forget_folder() where the bulk of this + code has gone. + (unsubscribe_folder): Call imap_folder_effectively_unsubscribed() + where the bulk of this code has gone. + 2002-07-31 Jeffrey Stedfast <fejj@ximian.com> * providers/imap/camel-imap-folder.c (parse_fetch_response): diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 7781316f27..daee1cde70 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -112,6 +112,16 @@ static void unsubscribe_folder (CamelStore *store, const char *folder_name, static void get_folders_online (CamelImapStore *imap_store, const char *pattern, GPtrArray *folders, gboolean lsub, CamelException *ex); + +static void imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, + const char *folder_name, CamelException *ex); + +static gboolean imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, + CamelException *ex); + +static void imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, + CamelException *ex); + static void camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) { @@ -754,6 +764,136 @@ query_auth_types (CamelService *service, CamelException *ex) } static void +imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, + const char *folder_name, CamelException *ex) +{ + gpointer key, value; + CamelFolderInfo *fi; + const char *name; + + if (g_hash_table_lookup_extended (imap_store->subscribed_folders, + folder_name, &key, &value)) { + 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++; + else + name = folder_name; + + fi = g_new0 (CamelFolderInfo, 1); + fi->full_name = g_strdup (folder_name); + fi->name = g_strdup (name); + fi->url = g_strdup_printf ("%s/%s", imap_store->base_url, folder_name); + fi->unread_message_count = -1; + camel_folder_info_build_path (fi, imap_store->dir_sep); + + camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_unsubscribed", fi); + camel_folder_info_free (fi); +} + +static void +imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, CamelException *ex) +{ + CamelFolderSummary *summary; + CamelImapMessageCache *cache; + char *summary_file; + char *journal_file; + char *folder_dir, *storage_path; + CamelFolderInfo *fi; + const char *name; + + storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); + folder_dir = e_path_to_physical (storage_path, folder_name); + g_free(storage_path); + if (access (folder_dir, F_OK) != 0) { + g_free (folder_dir); + goto event; + } + + summary_file = g_strdup_printf ("%s/summary", folder_dir); + summary = camel_imap_summary_new (summary_file); + if (!summary) { + g_free (summary_file); + g_free (folder_dir); + goto event; + } + + cache = camel_imap_message_cache_new (folder_dir, summary, ex); + if (cache) + camel_imap_message_cache_clear (cache); + + camel_object_unref (CAMEL_OBJECT (cache)); + camel_object_unref (CAMEL_OBJECT (summary)); + + unlink (summary_file); + g_free (summary_file); + + journal_file = g_strdup_printf ("%s/summary", folder_dir); + unlink (journal_file); + g_free (journal_file); + + rmdir (folder_dir); + g_free (folder_dir); + + name = strrchr (folder_name, imap_store->dir_sep); + if (name) + name++; + else + name = folder_name; + + event: + + fi = g_new0 (CamelFolderInfo, 1); + fi->full_name = g_strdup (folder_name); + fi->name = g_strdup (name); + fi->url = g_strdup_printf ("%s/%s", imap_store->base_url, folder_name); + fi->unread_message_count = -1; + camel_folder_info_build_path (fi, imap_store->dir_sep); + camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_deleted", fi); + camel_folder_info_free (fi); +} + +static gboolean +imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, + CamelException *ex) +{ + CamelImapResponse *response; + + response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", + full_name); + + if (response) { + gboolean stillthere = FALSE; + + if (response->untagged->len) + stillthere = TRUE; + + camel_imap_response_free_without_processing (imap_store, response); + + if (stillthere) + return TRUE; + } + + /* either LIST command was rejected or it gave no results, + * we can be sure that the folder is gone. */ + + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, + _("The folder %s no longer exists"), + full_name); + return FALSE; +} + +static void copy_folder(char *key, CamelFolder *folder, GPtrArray *out) { g_ptr_array_add(out, folder); @@ -781,11 +921,26 @@ imap_store_refresh_folders (CamelImapStore *store, CamelException *ex) for (i = 0; i <folders->len; i++) { CamelFolder *folder = folders->pdata[i]; - + CAMEL_IMAP_FOLDER (folder)->need_rescan = TRUE; if (!camel_exception_is_set(ex)) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex); - camel_object_unref((CamelObject *)folder); + + if (camel_exception_is_set (ex) && + imap_check_folder_still_extant (store, folder->full_name, ex) == FALSE) { + gchar *namedup; + + /* the folder was deleted (may happen when we come back online + * after being offline */ + + namedup = g_strdup (folder->full_name); + camel_object_unref((CamelObject *)folder); + imap_folder_effectively_unsubscribed (store, namedup, ex); + imap_forget_folder (store, namedup, ex); + camel_exception_clear (ex); + g_free (namedup); + } else + camel_object_unref((CamelObject *)folder); } g_ptr_array_free (folders, TRUE); @@ -981,7 +1136,7 @@ imap_connect_online (CamelService *service, CamelException *ex) FILE *storeinfo; int i, flags; size_t len; - + CAMEL_IMAP_STORE_LOCK (store, command_lock); if (!connect_to_server_wrapper (service, ex) || !imap_auth_loop (service, ex)) { @@ -1285,8 +1440,17 @@ get_folder_status (CamelImapStore *imap_store, const char *folder_name, const ch folder_name, type); - if (!response) + if (!response) { + CamelException ex; + + camel_exception_init (&ex); + if (imap_check_folder_still_extant (imap_store, folder_name, &ex) == FALSE) { + imap_folder_effectively_unsubscribed (imap_store, folder_name, &ex); + imap_forget_folder (imap_store, folder_name, &ex); + } + camel_exception_clear (&ex); return -1; + } status = camel_imap_response_extract (imap_store, response, "STATUS", NULL); @@ -1434,63 +1598,8 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) folder_name); if (response) { - CamelFolderSummary *summary; - CamelImapMessageCache *cache; - char *summary_file; - char *journal_file; - char *folder_dir, *storage_path; - CamelFolderInfo *fi; - const char *name; - camel_imap_response_free (imap_store, response); - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = e_path_to_physical (storage_path, folder_name); - g_free(storage_path); - if (access (folder_dir, F_OK) != 0) { - g_free (folder_dir); - return; - } - - summary_file = g_strdup_printf ("%s/summary", folder_dir); - summary = camel_imap_summary_new (summary_file); - if (!summary) { - g_free (summary_file); - g_free (folder_dir); - return; - } - - cache = camel_imap_message_cache_new (folder_dir, summary, ex); - if (cache) - camel_imap_message_cache_clear (cache); - - camel_object_unref (CAMEL_OBJECT (cache)); - camel_object_unref (CAMEL_OBJECT (summary)); - - unlink (summary_file); - g_free (summary_file); - - journal_file = g_strdup_printf ("%s/summary", folder_dir); - unlink (journal_file); - g_free (journal_file); - - rmdir (folder_dir); - g_free (folder_dir); - - name = strrchr (folder_name, imap_store->dir_sep); - if (name) - name++; - else - name = folder_name; - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf ("%s/%s", imap_store->base_url, folder_name); - fi->unread_message_count = -1; - camel_folder_info_build_path (fi, imap_store->dir_sep); - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_deleted", fi); - camel_folder_info_free (fi); + imap_forget_folder (imap_store, folder_name, ex); } } @@ -2179,9 +2288,6 @@ unsubscribe_folder (CamelStore *store, const char *folder_name, { CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; - gpointer key, value; - CamelFolderInfo *fi; - const char *name; if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) return; @@ -2193,35 +2299,8 @@ unsubscribe_folder (CamelStore *store, const char *folder_name, if (!response) return; camel_imap_response_free (imap_store, response); - - if (g_hash_table_lookup_extended (imap_store->subscribed_folders, - folder_name, &key, &value)) { - 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++; - else - name = folder_name; - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf ("%s/%s", imap_store->base_url, folder_name); - fi->unread_message_count = -1; - camel_folder_info_build_path (fi, imap_store->dir_sep); - - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_unsubscribed", fi); - camel_folder_info_free (fi); + + imap_folder_effectively_unsubscribed (imap_store, folder_name, ex); } #if 0 diff --git a/mail/ChangeLog b/mail/ChangeLog index 0fbcac4fb1..ca365eefb5 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,17 @@ +2002-07-31 Peter Williams <peterw@ximian.com> + + * mail-folder-cache.c: Add another bitfield "unsub" + (real_flush_updates): If unsubscribing, manually remove the folder + from the shell. + (unset_folder_info): Add another parameter which is used to set + the unsub member. + (store_folder_unsubscribed): Pass true for @unsub. + (unset_folder_info_hash): Pass false for @unsub. + + * subscribe-dialog.c (fe_done_subscribing): Don't notify the shell + here. The folder cache does it now, and it was broken to make the + CORBA call in another thread anyway. + 2002-08-01 Jeffrey Stedfast <fejj@ximian.com> * mail-format.c (setup_mime_tables): Don't setup a handler for diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 5d7f1c879e..ab49fd0c25 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -76,6 +76,7 @@ struct _folder_update { unsigned int remove:1; /* removing from vfolders */ unsigned int delete:1; /* deleting as well? */ unsigned int add:1; /* add to vfolder */ + unsigned int unsub:1; /* unsubcribing? */ char *path; char *name; @@ -159,6 +160,8 @@ real_flush_updates(void *o, void *event_data, void *data) mail_vfolder_delete_uri(up->store, up->uri); mail_filter_delete_uri(up->store, up->uri); mail_config_uri_deleted(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(up->store))->compare_folder_name, up->uri); + if (up->unsub) + evolution_storage_removed_folder (storage, up->path); } else mail_vfolder_add_uri(up->store, up->uri, TRUE); } else { @@ -222,7 +225,7 @@ flush_updates(void) } static void -unset_folder_info(struct _folder_info *mfi, int delete) +unset_folder_info(struct _folder_info *mfi, int delete, int unsub) { struct _folder_update *up; @@ -242,7 +245,9 @@ unset_folder_info(struct _folder_info *mfi, int delete) up->remove = TRUE; up->delete = delete; + up->unsub = unsub; up->store = mfi->store_info->store; + up->path = g_strdup (mfi->path); camel_object_ref((CamelObject *)up->store); up->uri = g_strdup(mfi->uri); @@ -496,7 +501,7 @@ store_folder_unsubscribed(CamelObject *o, void *event_data, void *data) if (mfi) { g_hash_table_remove(si->folders, mfi->full_name); g_hash_table_remove(si->folders_uri, mfi->uri); - unset_folder_info(mfi, TRUE); + unset_folder_info(mfi, TRUE, TRUE); free_folder_info(mfi); } } @@ -639,7 +644,7 @@ struct _update_data { static void unset_folder_info_hash(char *path, struct _folder_info *mfi, void *data) { - unset_folder_info(mfi, FALSE); + unset_folder_info(mfi, FALSE, FALSE); } static void diff --git a/mail/subscribe-dialog.c b/mail/subscribe-dialog.c index 878d95eebc..e9c42855c0 100644 --- a/mail/subscribe-dialog.c +++ b/mail/subscribe-dialog.c @@ -843,7 +843,6 @@ fe_done_subscribing (const char *full_name, const char *name, gboolean subscribe closure->data->flags &= ~FTREE_NODE_SUBSCRIBED; /* FIXME: recursively remove folder as well? Possible? */ - evolution_storage_removed_folder (closure->ftree->e_storage, path); } g_free (path); |