aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog23
-rw-r--r--camel/providers/imap/camel-imap-store.c263
-rw-r--r--mail/ChangeLog14
-rw-r--r--mail/mail-folder-cache.c11
-rw-r--r--mail/subscribe-dialog.c1
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);