diff options
Diffstat (limited to 'camel/providers/imap/camel-imap-store.c')
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index e3bd61af27..8774d783bd 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -47,6 +47,8 @@ #include "camel-url.h" #include "string-utils.h" +#include "camel-imap-private.h" + #define d(x) x /* Specified in RFC 2060 */ @@ -121,6 +123,10 @@ camel_imap_store_finalize (CamelObject *object) g_hash_table_foreach_remove (imap_store->subscribed_folders, free_sub, NULL); g_hash_table_destroy (imap_store->subscribed_folders); +#ifdef ENABLE_THREADS + e_mutex_destroy(imap_store->priv->command_lock); +#endif + g_free(imap_store->priv); } static void @@ -139,6 +145,11 @@ camel_imap_store_init (gpointer object, gpointer klass) imap_store->connected = FALSE; imap_store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal); + + imap_store->priv = g_malloc0(sizeof(*imap_store->priv)); +#ifdef ENABLE_THREADS + imap_store->priv->command_lock = e_mutex_new(E_MUTEX_REC); +#endif } CamelType @@ -175,6 +186,7 @@ static struct { { NULL, 0 } }; +/* we have remote-store:connect_lock by now */ static gboolean connect_to_server (CamelService *service, CamelException *ex) { @@ -351,10 +363,12 @@ imap_connect (CamelService *service, CamelException *ex) } } + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, NULL, ex, "LOGIN %S %S", service->url->user, service->url->passwd); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); if (!response) { errbuf = g_strdup_printf (_("Unable to authenticate " "to IMAP server.\n%s\n\n"), @@ -380,6 +394,8 @@ imap_connect (CamelService *service, CamelException *ex) namespace++; else namespace = ""; + + CAMEL_IMAP_STORE_LOCK(store, command_lock); if (store->server_level >= IMAP_LEVEL_IMAP4REV1) { /* This idiom means "tell me the hierarchy separator * for the given path, even if that path doesn't exist. @@ -396,6 +412,8 @@ imap_connect (CamelService *service, CamelException *ex) "LIST \"\" %S", namespace); } + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + if (!response) return FALSE; @@ -431,7 +449,11 @@ imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) if (store->connected && clean) { /* send the logout command */ + + /* NB: this lock probably isn't required */ + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, NULL, ex, "LOGOUT"); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); camel_imap_response_free (response); } @@ -440,6 +462,7 @@ imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) return CAMEL_SERVICE_CLASS (remote_store_class)->disconnect (service, clean, ex); } +/* NOTE: Must have imap_store::command_lock before calling this */ static gboolean imap_folder_exists (CamelImapStore *store, const char *folder_name, gboolean *selectable, char **short_name, @@ -481,6 +504,7 @@ imap_folder_exists (CamelImapStore *store, const char *folder_name, return TRUE; } +/* NOTE: Must have imap_store::command_lock before calling this */ static gboolean imap_create (CamelImapStore *store, const char *folder_name, CamelException *ex) @@ -503,18 +527,19 @@ get_folder (CamelStore *store, const char *folder_name, guint32 flags, char *short_name, *summary_file, *p; gboolean selectable; + /* lock around the whole lot to check/create atomically */ + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); if (!imap_folder_exists (imap_store, folder_name, &selectable, &short_name, ex)) { - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) - return NULL; - - if (!imap_create (imap_store, folder_name, ex)) - return NULL; - - if (!imap_folder_exists (imap_store, folder_name, - &selectable, &short_name, ex)) + if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0 + || (!imap_create (imap_store, folder_name, ex)) + || (!imap_folder_exists (imap_store, folder_name, + &selectable, &short_name, ex))) { + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); return NULL; + } } + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!selectable) { camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, @@ -621,8 +646,10 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, else name = ""; } + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!response) return FALSE; list = camel_imap_response_extract (response, "LIST", ex); @@ -642,10 +669,13 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, else pattern = g_strdup_printf ("%s%c", name, recursive ? '*' : '%'); + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "%s \"\" %S", subscribed_only ? "LSUB" : "LIST", pattern); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); + g_free (pattern); if (!response) return NULL; @@ -694,10 +724,12 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, if (!fi->url) continue; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command ( imap_store, NULL, NULL, "STATUS %S (MESSAGES UNSEEN)", fi->full_name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!response) continue; status = camel_imap_response_extract ( @@ -757,6 +789,7 @@ subscribe_folder (CamelStore *store, const char *folder_name, CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "SUBSCRIBE %S", folder_name); if (response) { @@ -774,9 +807,11 @@ unsubscribe_folder (CamelStore *store, const char *folder_name, CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; gpointer key, value; - + + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "UNSUBSCRIBE %S", folder_name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (response) { g_hash_table_lookup_extended (imap_store->subscribed_folders, folder_name, &key, &value); @@ -793,6 +828,8 @@ imap_keepalive (CamelRemoteStore *store) CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, NULL, "NOOP"); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); camel_imap_response_free (response); } |