aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/providers/cache/camel-cache-folder.c137
-rw-r--r--camel/providers/cache/camel-cache-folder.h3
-rw-r--r--camel/providers/cache/camel-cache-store.c169
-rw-r--r--camel/providers/cache/camel-cache-store.h3
4 files changed, 266 insertions, 46 deletions
diff --git a/camel/providers/cache/camel-cache-folder.c b/camel/providers/cache/camel-cache-folder.c
index 0e91e02a8b..c4379f8135 100644
--- a/camel/providers/cache/camel-cache-folder.c
+++ b/camel/providers/cache/camel-cache-folder.c
@@ -68,12 +68,15 @@
#include <camel/camel-medium.h>
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
+static CamelFolderClass *folder_class = NULL;
static void init (CamelFolder *folder, CamelStore *parent_store,
CamelFolder *parent_folder, const gchar *name,
gchar *separator, gboolean path_begins_with_sep,
CamelException *ex);
+static void refresh_info (CamelFolder *folder, CamelException *ex);
+
static void cache_sync (CamelFolder *folder, gboolean expunge,
CamelException *ex);
@@ -91,6 +94,10 @@ static gboolean get_message_user_flag (CamelFolder *folder, const char *uid,
const char *name);
static void set_message_user_flag (CamelFolder *folder, const char *uid,
const char *name, gboolean value);
+static const char *get_message_user_tag (CamelFolder *folder, const char *uid,
+ const char *name);
+static void set_message_user_tag (CamelFolder *folder, const char *uid,
+ const char *name, const char *value);
static CamelMimeMessage *get_message (CamelFolder *folder,
const gchar *uid,
@@ -108,6 +115,12 @@ static GPtrArray *search_by_expression (CamelFolder *folder,
static const CamelMessageInfo *get_message_info (CamelFolder *folder,
const char *uid);
+static void copy_message_to (CamelFolder *source, const char *uid,
+ CamelFolder *destination, CamelException *ex);
+
+static void move_message_to (CamelFolder *source, const char *uid,
+ CamelFolder *destination, CamelException *ex);
+
static void finalize (CamelObject *object);
static void
@@ -116,8 +129,11 @@ camel_cache_folder_class_init (CamelCacheFolderClass *camel_cache_folder_class)
CamelFolderClass *camel_folder_class =
CAMEL_FOLDER_CLASS (camel_cache_folder_class);
+ folder_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
+
/* virtual method overload */
camel_folder_class->init = init;
+ camel_folder_class->refresh_info = refresh_info;
camel_folder_class->sync = cache_sync;
camel_folder_class->expunge = expunge;
camel_folder_class->get_message_count = get_message_count;
@@ -126,6 +142,8 @@ camel_cache_folder_class_init (CamelCacheFolderClass *camel_cache_folder_class)
camel_folder_class->set_message_flags = set_message_flags;
camel_folder_class->get_message_user_flag = get_message_user_flag;
camel_folder_class->set_message_user_flag = set_message_user_flag;
+ camel_folder_class->get_message_user_tag = get_message_user_tag;
+ camel_folder_class->set_message_user_tag = set_message_user_tag;
camel_folder_class->get_message = get_message;
camel_folder_class->get_uids = get_uids;
camel_folder_class->free_uids = camel_folder_free_nop;
@@ -135,6 +153,8 @@ camel_cache_folder_class_init (CamelCacheFolderClass *camel_cache_folder_class)
camel_folder_class->free_subfolder_names = free_subfolder_names;
camel_folder_class->search_by_expression = search_by_expression;
camel_folder_class->get_message_info = get_message_info;
+ camel_folder_class->copy_message_to = copy_message_to;
+ camel_folder_class->move_message_to = move_message_to;
}
CamelType
@@ -360,6 +380,15 @@ local_folder_changed (CamelObject *local, gpointer type, gpointer data)
/* DONE */
static void
+refresh_info (CamelFolder *folder, CamelException *ex)
+{
+ CamelCacheFolder *cache_folder = (CamelCacheFolder *)folder;
+
+ camel_folder_refresh_info (cache_folder->remote, ex);
+}
+
+/* DONE */
+static void
cache_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
CamelCacheFolder *cache_folder = (CamelCacheFolder *)folder;
@@ -463,6 +492,35 @@ set_message_user_flag (CamelFolder *folder, const char *uid,
/* DONE */
+static const char *
+get_message_user_tag (CamelFolder *folder, const char *uid, const char *name)
+{
+ const CamelMessageInfo *mi;
+
+ mi = get_message_info (folder, uid);
+ g_return_val_if_fail (mi != NULL, NULL);
+ return camel_tag_get ((CamelTag **)&mi->user_tags, name);
+}
+
+/* DONE */
+static void
+set_message_user_tag (CamelFolder *folder, const char *uid,
+ const char *name, const char *value)
+{
+ CamelCacheFolder *cache_folder = (CamelCacheFolder *)folder;
+ const char *luid;
+
+ luid = camel_cache_map_get_local (cache_folder->uidmap, uid);
+ if (luid) {
+ camel_folder_set_message_user_tag (cache_folder->local, luid,
+ name, value);
+ }
+ camel_folder_set_message_user_tag (cache_folder->remote, uid,
+ name, value);
+}
+
+
+/* DONE */
static CamelMimeMessage *
get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
{
@@ -588,10 +646,87 @@ get_message_info (CamelFolder *folder, const char *uid)
return g_hash_table_lookup (cache_folder->summary_uids, uid);
}
+/* DONE */
+static void
+copy_message_to (CamelFolder *source, const char *uid,
+ CamelFolder *destination, CamelException *ex)
+{
+ CamelCacheFolder *source_cache_folder = (CamelCacheFolder *)source;
+ CamelCacheFolder *dest_cache_folder = (CamelCacheFolder *)destination;
+
+ /* If we are here, we know that the folders have the same parent
+ * store, which implies their remote and local folders have the
+ * same parent store as well.
+ */
+
+ if (CF_CLASS (source_cache_folder->remote)->copy_message_to !=
+ folder_class->copy_message_to) {
+ /* The remote store has a non-default copy method, so
+ * use it to avoid unnecessary network traffic.
+ */
+ CF_CLASS (source_cache_folder->remote)->copy_message_to (
+ source_cache_folder->remote, uid,
+ dest_cache_folder->remote, ex);
+ } else {
+ /* The remote store uses the default copy method,
+ * meaning if we proxy the copy_message_to over to it,
+ * it will suck the message over the network. We may
+ * already have a local copy, and if we don't, we want
+ * to, and if we're going to have the message in
+ * memory, then we should get it into the destination
+ * cache too. So do this by hand.
+ */
+ CamelMimeMessage *msg;
+ const CamelMessageInfo *info;
+
+ msg = get_message (source, uid, ex);
+ if (camel_exception_is_set (ex))
+ return;
+ info = camel_folder_get_message_info (source, uid);
+
+ camel_medium_remove_header (CAMEL_MEDIUM (msg),
+ "X-Evolution-Remote-UID");
+ append_message (destination, msg, info, ex);
+ }
+}
+
+/* DONE */
+static void
+move_message_to (CamelFolder *source, const char *uid,
+ CamelFolder *destination, CamelException *ex)
+{
+ CamelCacheFolder *source_cache_folder = (CamelCacheFolder *)source;
+ CamelCacheFolder *dest_cache_folder = (CamelCacheFolder *)destination;
+
+ /* See comments in copy_message_to. */
+
+ if (CF_CLASS (source_cache_folder)->move_message_to !=
+ folder_class->move_message_to) {
+ CF_CLASS (source_cache_folder)->move_message_to (
+ source_cache_folder->remote, uid,
+ dest_cache_folder->remote, ex);
+ } else {
+ CamelMimeMessage *msg;
+ const CamelMessageInfo *info;
+
+ msg = get_message (source, uid, ex);
+ if (camel_exception_is_set (ex))
+ return;
+ info = camel_folder_get_message_info (source, uid);
+
+ camel_medium_remove_header (CAMEL_MEDIUM (msg),
+ "X-Evolution-Remote-UID");
+ append_message (destination, msg, info, ex);
+ if (!camel_exception_is_set (ex))
+ camel_folder_delete_message (source, uid);
+ }
+}
+
CamelFolder *
camel_cache_folder_new (CamelStore *store, CamelFolder *parent,
- CamelFolder *remote, CamelFolder *local)
+ CamelFolder *remote, CamelFolder *local,
+ CamelException *ex)
{
CamelCacheFolder *cache_folder;
CamelFolder *folder;
diff --git a/camel/providers/cache/camel-cache-folder.h b/camel/providers/cache/camel-cache-folder.h
index c4eadd56b7..3609de4d67 100644
--- a/camel/providers/cache/camel-cache-folder.h
+++ b/camel/providers/cache/camel-cache-folder.h
@@ -72,7 +72,8 @@ typedef struct {
CamelFolder *camel_cache_folder_new (CamelStore *store, CamelFolder *parent,
- CamelFolder *remote, CamelFolder *local);
+ CamelFolder *remote, CamelFolder *local,
+ CamelException *ex);
void camel_cache_folder_sync (CamelCacheFolder *cache_folder,
CamelException *ex);
diff --git a/camel/providers/cache/camel-cache-store.c b/camel/providers/cache/camel-cache-store.c
index b779b4ca55..544cca69a1 100644
--- a/camel/providers/cache/camel-cache-store.c
+++ b/camel/providers/cache/camel-cache-store.c
@@ -45,16 +45,21 @@
#include "md5-utils.h"
static CamelServiceClass *service_class = NULL;
+#define CS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
static void finalize (CamelObject *object);
static gboolean cache_connect (CamelService *service, CamelException *ex);
static gboolean cache_disconnect (CamelService *service, CamelException *ex);
+static char *get_path (CamelService *service);
+static char *get_name (CamelService *service, gboolean brief);
static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
gboolean create, CamelException *ex);
static void delete_folder (CamelStore *store, const char *folder_name,
CamelException *ex);
+static void rename_folder (CamelStore *store, const char *old_name,
+ const char *new_name, CamelException *ex);
static char *get_folder_name (CamelStore *store, const char *folder_name,
CamelException *ex);
static char *get_root_folder_name (CamelStore *store, CamelException *ex);
@@ -74,24 +79,18 @@ camel_cache_store_class_init (CamelCacheStoreClass *camel_cache_store_class)
/* virtual method overload */
camel_service_class->connect = cache_connect;
camel_service_class->disconnect = cache_disconnect;
+ camel_service_class->get_path = get_path;
+ camel_service_class->get_name = get_name;
camel_store_class->get_folder = get_folder;
camel_store_class->delete_folder = delete_folder;
+ camel_store_class->rename_folder = rename_folder;
camel_store_class->get_folder_name = get_folder_name;
camel_store_class->get_root_folder_name = get_root_folder_name;
camel_store_class->get_default_folder_name = get_default_folder_name;
}
-static void
-camel_cache_store_init (gpointer object, gpointer klass)
-{
- CamelService *service = CAMEL_SERVICE (object);
-
- service->url_flags = CAMEL_SERVICE_URL_NEED_PATH;
-}
-
-
CamelType
camel_cache_store_get_type (void)
{
@@ -104,7 +103,7 @@ camel_cache_store_get_type (void)
sizeof (CamelCacheStoreClass),
(CamelObjectClassInitFunc) camel_cache_store_class_init,
NULL,
- (CamelObjectInitFunc) camel_cache_store_init,
+ NULL,
(CamelObjectFinalizeFunc) finalize);
}
@@ -118,6 +117,7 @@ finalize (CamelObject *object)
camel_object_unref (CAMEL_OBJECT (cache_store->local));
camel_object_unref (CAMEL_OBJECT (cache_store->remote));
+ g_free (cache_store->local_base);
}
@@ -126,40 +126,38 @@ cache_connect (CamelService *service, CamelException *ex)
{
CamelCacheStore *cache_store = CAMEL_CACHE_STORE (service);
- if (!cache_store->remote) {
- cache_store->remote =
- camel_session_get_store (service->session,
- service->url->path,
- ex);
- if (camel_exception_is_set (ex))
- return FALSE;
-
- cache_store->local = XXX;
- if (camel_exception_is_set (ex))
- return FALSE;
- }
-
- if (!camel_service_connect (CAMEL_SERVICE (cache_store->remote), ex))
- return FALSE;
- if (!camel_service_connect (CAMEL_SERVICE (cache_store->local), ex)) {
- camel_service_disconnect (CAMEL_SERVICE (cache_store->remote),
- NULL);
- return FALSE;
- }
-
- return service_class->connect (service, ex);
+ return camel_service_connect (CAMEL_SERVICE (cache_store->remote), ex) &&
+ camel_service_connect (CAMEL_SERVICE (cache_store->local), ex);
}
static gboolean
cache_disconnect (CamelService *service, CamelException *ex)
{
- CamelCacheStore *store = CAMEL_CACHE_STORE (service);
+ CamelCacheStore *cache_store = CAMEL_CACHE_STORE (service);
+
+ return camel_service_disconnect (CAMEL_SERVICE (cache_store->local), ex) &&
+ camel_service_disconnect (CAMEL_SERVICE (cache_store->remote), ex);
+}
+
+static char *
+get_path (CamelService *service)
+{
+ CamelCacheStore *cache_store = CAMEL_CACHE_STORE (service);
+ char *path, *subpath;
- if (!service_class->disconnect (service, ex))
- return FALSE;
+ subpath = camel_service_get_path (CAMEL_SERVICE (cache_store->remote));
+ path = g_strdup_printf ("cache/%s", subpath);
+ g_free (subpath);
+ return path;
+}
+
+static char *
+get_name (CamelService *service, gboolean brief)
+{
+ CamelCacheStore *cache_store = CAMEL_CACHE_STORE (service);
- return camel_service_disconnect (CAMEL_SERVICE (store->local), ex) &&
- camel_service_disconnect (CAMEL_SERVICE (store->remote), ex);
+ return camel_service_get_name (CAMEL_SERVICE (cache_store->remote),
+ brief);
}
static CamelFolder *
@@ -167,7 +165,7 @@ get_folder (CamelStore *store, const char *folder_name,
gboolean create, CamelException *ex)
{
CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
- CamelFolder *rf, *lf;
+ CamelFolder *parent, *rf, *lf;
rf = camel_store_get_folder (cache_store->remote, folder_name,
create, ex);
@@ -184,7 +182,34 @@ get_folder (CamelStore *store, const char *folder_name,
return NULL;
}
- return camel_cache_folder_new (cache_store, rf, lf, ex);
+ return camel_cache_folder_new (store, parent, rf, lf, ex);
+}
+
+/* XXX these two need to be better about failure recovery. */
+static void
+delete_folder (CamelStore *store, const char *folder_name,
+ CamelException *ex)
+{
+ CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
+
+ camel_store_delete_folder (cache_store->remote, folder_name, ex);
+ if (camel_exception_is_set (ex))
+ return;
+ camel_store_delete_folder (cache_store->local, folder_name, NULL);
+}
+
+static void
+rename_folder (CamelStore *store, const char *old_name,
+ const char *new_name, CamelException *ex)
+{
+ CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
+
+ camel_store_rename_folder (cache_store->remote, old_name,
+ new_name, ex);
+ if (camel_exception_is_set (ex))
+ return;
+ camel_store_rename_folder (cache_store->local, old_name,
+ new_name, NULL);
}
static char *
@@ -193,8 +218,8 @@ get_folder_name (CamelStore *store, const char *folder_name,
{
CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
- return camel_store_get_folder_name (cache_store->remote,
- folder_name, ex);
+ return CS_CLASS (cache_store->remote)->get_folder_name (
+ cache_store->remote, folder_name, ex);
}
static char *
@@ -202,7 +227,8 @@ get_root_folder_name (CamelStore *store, CamelException *ex)
{
CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
- return camel_store_get_root_folder_name (cache_store->remote, ex);
+ return CS_CLASS (cache_store->remote)->get_root_folder_name (
+ cache_store->remote, ex);
}
static char *
@@ -210,5 +236,62 @@ get_default_folder_name (CamelStore *store, CamelException *ex)
{
CamelCacheStore *cache_store = CAMEL_CACHE_STORE (store);
- return camel_store_get_default_folder_name (cache_store->remote, ex);
+ return CS_CLASS (cache_store->remote)->get_default_folder_name (
+ cache_store->remote, ex);
+}
+
+
+/**
+ * camel_cache_store_new:
+ * @remote: a remote store
+ * @ex: a CamelException
+ *
+ * Return value: a CamelCacheStore for the given remote store.
+ **/
+CamelStore *
+camel_cache_store_new (CamelStore *remote, CamelException *ex)
+{
+ CamelCacheStore *cache_store;
+ CamelService *remote_service = (CamelService *)remote;
+ CamelSession *session;
+ char *url_string;
+ CamelURL *url;
+
+ session = camel_service_get_session (remote_service);
+
+ url_string = camel_service_get_url (remote_service);
+ url = camel_url_new (url_string, ex);
+ g_free (url_string);
+
+ if (!url)
+ return NULL;
+
+ cache_store = (CamelCacheStore *)
+ camel_service_new (CAMEL_CACHE_STORE_TYPE, session,
+ camel_service_get_provider (remote_service),
+ url, ex);
+ if (camel_exception_is_set (ex)) {
+ camel_url_free (url);
+ return NULL;
+ }
+
+ cache_store->remote = remote;
+ camel_object_ref (CAMEL_OBJECT (remote));
+
+ cache_store->local_base = camel_session_get_storage_path (
+ session, (CamelService *)cache_store, ex);
+ if (camel_exception_is_set (ex)) {
+ camel_object_unref (CAMEL_OBJECT (cache_store));
+ return NULL;
+ }
+
+ url_string = g_strdup_printf ("mbox:%s", cache_store->local_base);
+ cache_store->local = camel_session_get_store (session, url_string, ex);
+ g_free (url_string);
+ if (camel_exception_is_set (ex)) {
+ camel_object_unref (CAMEL_OBJECT (cache_store));
+ return NULL;
+ }
+
+ return (CamelStore *)cache_store;
}
diff --git a/camel/providers/cache/camel-cache-store.h b/camel/providers/cache/camel-cache-store.h
index f02c987c47..7339d8a9f3 100644
--- a/camel/providers/cache/camel-cache-store.h
+++ b/camel/providers/cache/camel-cache-store.h
@@ -41,6 +41,7 @@ extern "C" {
typedef struct {
CamelStore parent_object;
+ char *local_base;
CamelStore *remote, *local;
} CamelCacheStore;
@@ -53,7 +54,7 @@ typedef struct {
/* support functions */
-void camel_cache_store_sync (CamelCacheStore *store);
+CamelStore *camel_cache_store_new (CamelStore *remote, CamelException *ex);
/* Standard Camel function */
CamelType camel_cache_store_get_type (void);