diff options
Diffstat (limited to 'camel')
-rw-r--r-- | camel/providers/cache/camel-cache-folder.c | 137 | ||||
-rw-r--r-- | camel/providers/cache/camel-cache-folder.h | 3 | ||||
-rw-r--r-- | camel/providers/cache/camel-cache-store.c | 169 | ||||
-rw-r--r-- | camel/providers/cache/camel-cache-store.h | 3 |
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); |