aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-store.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap/camel-imap-store.c')
-rw-r--r--camel/providers/imap/camel-imap-store.c263
1 files changed, 171 insertions, 92 deletions
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