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.c55
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);
}