[evolution-data-server] Bug #656473 - Store server folder cache in user's cache directory



commit baabf6b7ba8553dae027e5eab181a72c3658217b
Author: Milan Crha <mcrha redhat com>
Date:   Mon Sep 26 12:11:54 2011 +0200

    Bug #656473 - Store server folder cache in user's cache directory

 camel/camel-enums.h                        |    3 +-
 camel/camel-service.c                      |   33 +++++++++-
 camel/camel-service.h                      |    2 +
 camel/camel-session.c                      |   55 +++++++++++++++++
 camel/camel-session.h                      |    2 +
 camel/camel-store.c                        |   11 ++-
 camel/providers/imap/camel-imap-folder.c   |   16 +++---
 camel/providers/imap/camel-imap-store.c    |   83 ++++++++++++++++++--------
 camel/providers/imapx/camel-imapx-folder.c |    4 +-
 camel/providers/imapx/camel-imapx-store.c  |   87 +++++++++++++++++++---------
 camel/providers/nntp/camel-nntp-folder.c   |    6 +-
 camel/providers/nntp/camel-nntp-store.c    |   83 +++++++++++++++++++++++---
 12 files changed, 301 insertions(+), 84 deletions(-)
---
diff --git a/camel/camel-enums.h b/camel/camel-enums.h
index 064d45a..b0dd07e 100644
--- a/camel/camel-enums.h
+++ b/camel/camel-enums.h
@@ -318,7 +318,8 @@ typedef enum { /*< flags >*/
 	CAMEL_STORE_PROXY            = 1 << 2,
 	CAMEL_STORE_IS_MIGRATING     = 1 << 3,
 	CAMEL_STORE_REAL_JUNK_FOLDER = 1 << 4,
-	CAMEL_STORE_CAN_EDIT_FOLDERS = 1 << 5
+	CAMEL_STORE_CAN_EDIT_FOLDERS = 1 << 5,
+	CAMEL_STORE_USE_CACHE_DIR    = 1 << 6
 } CamelStoreFlags;
 
 /**
diff --git a/camel/camel-service.c b/camel/camel-service.c
index 76a3cf6..a366ee9 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -58,6 +58,7 @@ struct _CamelServicePrivate {
 
 	gchar *display_name;
 	gchar *user_data_dir;
+	gchar *user_cache_dir;
 	gchar *uid;
 
 	GCancellable *connect_op;
@@ -354,6 +355,7 @@ service_finalize (GObject *object)
 
 	g_free (priv->display_name);
 	g_free (priv->user_data_dir);
+	g_free (priv->user_cache_dir);
 	g_free (priv->uid);
 
 	g_static_rec_mutex_free (&priv->connect_lock);
@@ -368,7 +370,7 @@ service_constructed (GObject *object)
 {
 	CamelService *service;
 	CamelSession *session;
-	const gchar *base_data_dir;
+	const gchar *base_dir;
 	const gchar *uid;
 
 	/* Chain up to parent's constructed() method. */
@@ -378,10 +380,12 @@ service_constructed (GObject *object)
 	session = camel_service_get_session (service);
 
 	uid = camel_service_get_uid (service);
-	base_data_dir = camel_session_get_user_data_dir (session);
 
-	service->priv->user_data_dir =
-		g_build_filename (base_data_dir, uid, NULL);
+	base_dir = camel_session_get_user_data_dir (session);
+	service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
+
+	base_dir = camel_session_get_user_cache_dir (session);
+	service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
 }
 
 static gchar *
@@ -791,6 +795,27 @@ camel_service_get_user_data_dir (CamelService *service)
 }
 
 /**
+ * camel_service_get_user_cache_dir:
+ * @service: a #CamelService
+ *
+ * Returns the base directory under which to store cache data
+ * for @service.  The directory is formed by appending the directory
+ * returned by camel_session_get_user_cache_dir() with the service's
+ * #CamelService:uid value.
+ *
+ * Returns: the base cache directory for @service
+ *
+ * Since: 3.4
+ **/
+const gchar *
+camel_service_get_user_cache_dir (CamelService *service)
+{
+	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
+
+	return service->priv->user_cache_dir;
+}
+
+/**
  * camel_service_get_name:
  * @service: a #CamelService
  * @brief: whether or not to use a briefer form
diff --git a/camel/camel-service.h b/camel/camel-service.h
index a9843e3..0784dde 100644
--- a/camel/camel-service.h
+++ b/camel/camel-service.h
@@ -149,6 +149,8 @@ const gchar *	camel_service_get_display_name	(CamelService *service);
 void		camel_service_set_display_name	(CamelService *service,
 						 const gchar *display_name);
 const gchar *	camel_service_get_user_data_dir	(CamelService *service);
+const gchar *	camel_service_get_user_cache_dir
+						(CamelService *service);
 gchar *		camel_service_get_name		(CamelService *service,
 						 gboolean brief);
 CamelProvider *	camel_service_get_provider	(CamelService *service);
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 260ccee..e98bae83 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -63,6 +63,7 @@ struct _CamelSessionPrivate {
 	GMutex *thread_lock;	/* locking threads */
 
 	gchar *user_data_dir;
+	gchar *user_cache_dir;
 
 	GHashTable *services;
 	GHashTable *junk_headers;
@@ -93,6 +94,7 @@ enum {
 	PROP_NETWORK_AVAILABLE,
 	PROP_ONLINE,
 	PROP_USER_DATA_DIR,
+	PROP_USER_CACHE_DIR
 };
 
 enum {
@@ -194,6 +196,16 @@ session_set_user_data_dir (CamelSession *session,
 }
 
 static void
+session_set_user_cache_dir (CamelSession *session,
+			    const gchar *user_cache_dir)
+{
+	g_return_if_fail (user_cache_dir != NULL);
+	g_return_if_fail (session->priv->user_cache_dir == NULL);
+
+	session->priv->user_cache_dir = g_strdup (user_cache_dir);
+}
+
+static void
 session_set_property (GObject *object,
                       guint property_id,
                       const GValue *value,
@@ -229,6 +241,12 @@ session_set_property (GObject *object,
 				CAMEL_SESSION (object),
 				g_value_get_string (value));
 			return;
+
+		case PROP_USER_CACHE_DIR:
+			session_set_user_cache_dir (
+				CAMEL_SESSION (object),
+				g_value_get_string (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -270,6 +288,12 @@ session_get_property (GObject *object,
 				value, camel_session_get_user_data_dir (
 				CAMEL_SESSION (object)));
 			return;
+
+		case PROP_USER_CACHE_DIR:
+			g_value_set_string (
+				value, camel_session_get_user_cache_dir (
+				CAMEL_SESSION (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -301,6 +325,7 @@ session_finalize (GObject *object)
 	priv = CAMEL_SESSION_GET_PRIVATE (object);
 
 	g_free (priv->user_data_dir);
+	g_free (priv->user_cache_dir);
 
 	g_hash_table_destroy (priv->services);
 
@@ -464,6 +489,18 @@ camel_session_class_init (CamelSessionClass *class)
 			G_PARAM_CONSTRUCT |
 			G_PARAM_STATIC_STRINGS));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_USER_CACHE_DIR,
+		g_param_spec_string (
+			"user-cache-dir",
+			"User Cache Directory",
+			"User-specific base directory for mail cache",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
 	signals[JOB_STARTED] = g_signal_new (
 		"job-started",
 		G_OBJECT_CLASS_TYPE (class),
@@ -528,6 +565,24 @@ camel_session_get_user_data_dir (CamelSession *session)
 }
 
 /**
+ * camel_session_get_user_cache_dir:
+ * @session: a #CamelSession
+ *
+ * Returns the base directory under which to store user-specific mail cache.
+ *
+ * Returns: the base directory for mail cache
+ *
+ * Since: 3.4
+ **/
+const gchar *
+camel_session_get_user_cache_dir (CamelSession *session)
+{
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+
+	return session->priv->user_cache_dir;
+}
+
+/**
  * camel_session_add_service:
  * @session: a #CamelSession
  * @uid: a unique identifier string
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 89b99fd..984097b 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -146,6 +146,8 @@ struct _CamelSessionClass {
 
 GType		camel_session_get_type		(void);
 const gchar *	camel_session_get_user_data_dir	(CamelSession *session);
+const gchar *	camel_session_get_user_cache_dir
+						(CamelSession *session);
 void            camel_session_set_socks_proxy   (CamelSession *session,
 						 const gchar *socks_host,
 						 gint socks_port);
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 6c6e757..bf9a22a 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -1078,7 +1078,7 @@ store_initable_init (GInitable *initable,
 {
 	CamelStore *store;
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_dir;
 	gchar *filename;
 
 	store = CAMEL_STORE (initable);
@@ -1088,9 +1088,12 @@ store_initable_init (GInitable *initable,
 		return FALSE;
 
 	service = CAMEL_SERVICE (initable);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	if ((store->flags & CAMEL_STORE_USE_CACHE_DIR) != 0)
+		user_dir = camel_service_get_user_cache_dir (service);
+	else
+		user_dir = camel_service_get_user_data_dir (service);
 
-	if (g_mkdir_with_parents (user_data_dir, S_IRWXU) == -1) {
+	if (g_mkdir_with_parents (user_dir, S_IRWXU) == -1) {
 		g_set_error_literal (
 			error, G_FILE_ERROR,
 			g_file_error_from_errno (errno),
@@ -1099,7 +1102,7 @@ store_initable_init (GInitable *initable,
 	}
 
 	/* This is for reading from the store */
-	filename = g_build_filename (user_data_dir, CAMEL_DB_FILE, NULL);
+	filename = g_build_filename (user_dir, CAMEL_DB_FILE, NULL);
 	store->cdb_r = camel_db_open (filename, error);
 	g_free (filename);
 
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 6ac168e..5aceb35 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -385,7 +385,7 @@ camel_imap_folder_new (CamelStore *parent,
 		"display-name", short_name,
 		"parent-store", parent, NULL);
 
-	summary_file = g_strdup_printf ("%s/summary", folder_dir);
+	summary_file = g_build_filename (folder_dir, "summary", NULL);
 	folder->summary = camel_imap_summary_new (folder, summary_file);
 	g_free (summary_file);
 	if (!folder->summary) {
@@ -397,12 +397,12 @@ camel_imap_folder_new (CamelStore *parent,
 	}
 
 	imap_folder = CAMEL_IMAP_FOLDER (folder);
-	path = g_strdup_printf ("%s/journal", folder_dir);
+	path = g_build_filename (folder_dir, "journal", NULL);
 	imap_folder->journal = camel_imap_journal_new (imap_folder, path);
 	g_free (path);
 
 	/* set/load persistent state */
-	state_file = g_strdup_printf ("%s/cmeta", folder_dir);
+	state_file = g_build_filename (folder_dir, "cmeta", NULL);
 	camel_object_set_state_filename (CAMEL_OBJECT (folder), state_file);
 	g_free (state_file);
 	camel_object_state_read (CAMEL_OBJECT (folder));
@@ -688,20 +688,20 @@ imap_rename (CamelFolder *folder,
 	CamelService *service;
 	CamelStore *parent_store;
 	CamelImapFolder *imap_folder = (CamelImapFolder *) folder;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *folder_dir, *summary_path, *state_file;
 	gchar *folders;
 
 	parent_store = camel_folder_get_parent_store (folder);
 
 	service = CAMEL_SERVICE (parent_store);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
-	folders = g_strconcat (user_data_dir, "/folders", NULL);
+	folders = g_build_filename (user_cache_dir, "folders", NULL);
 	folder_dir = imap_path_to_physical (folders, new);
 	g_free (folders);
 
-	summary_path = g_strdup_printf("%s/summary", folder_dir);
+	summary_path = g_build_filename (folder_dir, "summary", NULL);
 
 	CAMEL_IMAP_FOLDER_REC_LOCK (folder, cache_lock);
 	camel_imap_message_cache_set_path (imap_folder->cache, folder_dir);
@@ -709,7 +709,7 @@ imap_rename (CamelFolder *folder,
 
 	camel_folder_summary_set_filename (folder->summary, summary_path);
 
-	state_file = g_strdup_printf ("%s/cmeta", folder_dir);
+	state_file = g_build_filename (folder_dir, "cmeta", NULL);
 	camel_object_set_state_filename (CAMEL_OBJECT (folder), state_file);
 	g_free (state_file);
 
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index f8291bb..c17655c 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -1181,30 +1181,63 @@ imap_store_query_auth_types_sync (CamelService *service,
 	return g_list_prepend (sasl_types, &camel_imap_password_authtype);
 }
 
+static void
+imap_migrate_to_user_cache_dir (CamelService *service)
+{
+	const gchar *user_data_dir, *user_cache_dir;
+
+	g_return_if_fail (service != NULL);
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
+
+	g_return_if_fail (user_data_dir != NULL);
+	g_return_if_fail (user_cache_dir != NULL);
+
+	/* migrate only if the source directory exists and the destination doesn't */
+	if (g_file_test (user_data_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) &&
+	    !g_file_test (user_cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
+		gchar *parent_dir;
+
+		parent_dir = g_path_get_dirname (user_cache_dir);
+		g_mkdir_with_parents (parent_dir, S_IRWXU);
+		g_free (parent_dir);
+
+		if (g_rename (user_data_dir, user_cache_dir) == -1)
+			g_debug ("%s: Failed to migrate '%s' to '%s': %s", G_STRFUNC, user_data_dir, user_cache_dir, g_strerror (errno));
+	}
+}
+
 static gboolean
 imap_store_initable_init (GInitable *initable,
                           GCancellable *cancellable,
                           GError **error)
 {
 	CamelImapStore *imap_store;
+	CamelStore *store;
 	CamelService *service;
 	CamelSettings *settings;
 	CamelURL *url;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	const gchar *real_path;
 	gboolean use_real_path;
-	gchar *tmp;
+	gchar *tmp_path;
 
 	imap_store = CAMEL_IMAP_STORE (initable);
+	store = CAMEL_STORE (initable);
+	service = CAMEL_SERVICE (initable);
+
+	store->flags |= CAMEL_STORE_USE_CACHE_DIR;
+	imap_migrate_to_user_cache_dir (service);
 
 	/* Chain up to parent interface's init() method. */
 	if (!parent_initable_interface->init (initable, cancellable, error))
 		return FALSE;
 
-	service = CAMEL_SERVICE (initable);
 	url = camel_service_get_camel_url (service);
 	settings = camel_service_get_settings (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	/* FIXME */
 	imap_store->base_url = camel_url_to_string (
@@ -1240,10 +1273,10 @@ imap_store_initable_init (GInitable *initable,
 		CAMEL_STORE (service)->flags |= CAMEL_STORE_VTRASH;
 
 	/* setup/load the store summary */
-	tmp = alloca (strlen (user_data_dir) + 32);
-	sprintf(tmp, "%s/.ev-store-summary", user_data_dir);
+	tmp_path = g_build_filename (user_cache_dir, ".ev-store-summary", NULL);
 	imap_store->summary = camel_imap_store_summary_new ();
-	camel_store_summary_set_filename ((CamelStoreSummary *) imap_store->summary, tmp);
+	camel_store_summary_set_filename ((CamelStoreSummary *) imap_store->summary, tmp_path);
+	g_free (tmp_path);
 	if (camel_store_summary_load ((CamelStoreSummary *) imap_store->summary) == 0) {
 		CamelImapStoreSummary *is = imap_store->summary;
 
@@ -1545,7 +1578,7 @@ imap_forget_folder (CamelImapStore *imap_store,
                     GError **error)
 {
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *state_file;
 	gchar *journal_file;
 	gchar *folder_dir, *storage_path;
@@ -1559,9 +1592,9 @@ imap_forget_folder (CamelImapStore *imap_store,
 		name = folder_name;
 
 	service = CAMEL_SERVICE (imap_store);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
-	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
+	storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 	folder_dir = imap_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	if (g_access (folder_dir, F_OK) != 0) {
@@ -1684,11 +1717,11 @@ imap_store_get_trash_folder_sync (CamelStore *store,
 	CamelSettings *settings;
 	CamelFolder *folder = NULL;
 	const gchar *trash_path;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 
 	service = CAMEL_SERVICE (store);
 	settings = camel_service_get_settings (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	trash_path = camel_imap_settings_get_real_trash_path (
 		CAMEL_IMAP_SETTINGS (settings));
@@ -1711,7 +1744,7 @@ imap_store_get_trash_folder_sync (CamelStore *store,
 		gchar *state;
 
 		state = g_build_filename (
-			user_data_dir, "system", "Trash.cmeta", NULL);
+			user_cache_dir, "system", "Trash.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1731,11 +1764,11 @@ imap_store_get_junk_folder_sync (CamelStore *store,
 	CamelSettings *settings;
 	CamelFolder *folder = NULL;
 	const gchar *junk_path;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 
 	service = CAMEL_SERVICE (store);
 	settings = camel_service_get_settings (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	junk_path = camel_imap_settings_get_real_junk_path (
 		CAMEL_IMAP_SETTINGS (settings));
@@ -1758,7 +1791,7 @@ imap_store_get_junk_folder_sync (CamelStore *store,
 		gchar *state;
 
 		state = g_build_filename (
-			user_data_dir, "system", "Junk.cmeta", NULL);
+			user_cache_dir, "system", "Junk.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1909,12 +1942,12 @@ imap_store_get_folder_sync (CamelStore *store,
 	CamelImapResponse *response;
 	CamelFolder *new_folder;
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *folder_dir, *storage_path;
 	GError *local_error = NULL;
 
 	service = CAMEL_SERVICE (store);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	/* Try to get it locally first, if it is, then the client will
 	 * force a select when necessary */
@@ -2106,7 +2139,7 @@ imap_store_get_folder_sync (CamelStore *store,
 		return NULL;
 	}
 
-	storage_path = g_strdup_printf("%s/folders", user_data_dir);
+	storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 	folder_dir = imap_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	new_folder = camel_imap_folder_new (store, folder_name, folder_dir, error);
@@ -2139,10 +2172,10 @@ get_folder_offline (CamelStore *store,
 	CamelFolder *new_folder = NULL;
 	CamelStoreInfo *si;
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 
 	service = CAMEL_SERVICE (store);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	si = camel_store_summary_path ((CamelStoreSummary *) imap_store->summary, folder_name);
 	if (si) {
@@ -2158,7 +2191,7 @@ get_folder_offline (CamelStore *store,
 		if (!g_ascii_strcasecmp (folder_name, "INBOX"))
 			folder_name = "INBOX";
 
-		storage_path = g_strdup_printf("%s/folders", user_data_dir);
+		storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 		folder_dir = imap_path_to_physical (storage_path, folder_name);
 		g_free (storage_path);
 		new_folder = camel_imap_folder_new (store, folder_name, folder_dir, error);
@@ -2306,14 +2339,14 @@ imap_store_rename_folder_sync (CamelStore *store,
 	CamelImapResponse *response;
 	CamelService *service;
 	CamelSettings *settings;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *oldpath, *newpath, *storage_path;
 	gboolean use_subscriptions;
 	gboolean success = TRUE;
 
 	service = CAMEL_SERVICE (store);
 	settings = camel_service_get_settings (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	use_subscriptions = camel_imap_settings_get_use_subscriptions (
 		CAMEL_IMAP_SETTINGS (settings));
@@ -2363,7 +2396,7 @@ imap_store_rename_folder_sync (CamelStore *store,
 		manage_subscriptions (
 			store, new_name_in, TRUE, cancellable);
 
-	storage_path = g_strdup_printf("%s/folders", user_data_dir);
+	storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 	oldpath = imap_path_to_physical (storage_path, old_name);
 	newpath = imap_path_to_physical (storage_path, new_name_in);
 
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index a125261..11c3cec 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -83,7 +83,7 @@ camel_imapx_folder_new (CamelStore *store,
 
 	((CamelIMAPXFolder *) folder)->raw_name = g_strdup (folder_name);
 
-	summary_file = g_strdup_printf ("%s/summary", folder_dir);
+	summary_file = g_build_filename (folder_dir, "summary", NULL);
 	folder->summary = camel_imapx_summary_new (folder, summary_file);
 	if (!folder->summary) {
 		g_set_error (
@@ -101,7 +101,7 @@ camel_imapx_folder_new (CamelStore *store,
 		return NULL;
 	}
 
-	state_file = g_strdup_printf ("%s/cmeta", folder_dir);
+	state_file = g_build_filename (folder_dir, "cmeta", NULL);
 	camel_object_set_state_filename (CAMEL_OBJECT (folder), state_file);
 	g_free (state_file);
 	camel_object_state_read (CAMEL_OBJECT (folder));
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 75faab0..a9293b3 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -281,10 +281,10 @@ get_folder_offline (CamelStore *store,
 	CamelFolder *new_folder = NULL;
 	CamelStoreInfo *si;
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 
 	service = CAMEL_SERVICE (store);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	si = camel_store_summary_path ((CamelStoreSummary *) imapx_store->summary, folder_name);
 	if (si) {
@@ -300,7 +300,7 @@ get_folder_offline (CamelStore *store,
 		if (!g_ascii_strcasecmp (folder_name, "INBOX"))
 			folder_name = "INBOX";
 
-		storage_path = g_strdup_printf("%s/folders", user_data_dir);
+		storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 		folder_dir = imapx_path_to_physical (storage_path, folder_name);
 		g_free (storage_path);
 		/* FIXME */
@@ -556,12 +556,12 @@ imapx_delete_folder_from_cache (CamelIMAPXStore *istore,
 	gchar *folder_dir, *storage_path;
 	CamelFolderInfo *fi;
 	CamelService *service;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 
 	service = CAMEL_SERVICE (istore);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
-	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
+	storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 	folder_dir = imapx_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	if (g_access (folder_dir, F_OK) != 0) {
@@ -570,14 +570,14 @@ imapx_delete_folder_from_cache (CamelIMAPXStore *istore,
 	}
 
 	/* Delete summary and all the data */
-	state_file = g_strdup_printf ("%s/cmeta", folder_dir);
+	state_file = g_build_filename (folder_dir, "cmeta", NULL);
 	g_unlink (state_file);
 	g_free (state_file);
 
 	camel_db_delete_folder (((CamelStore *) istore)->cdb_w, folder_name, NULL);
 	g_rmdir (folder_dir);
 
-	state_file = g_strdup_printf("%s/subfolders", folder_dir);
+	state_file = g_build_filename (folder_dir, "subfolders", NULL);
 	g_rmdir (state_file);
 	g_free (state_file);
 
@@ -1233,14 +1233,14 @@ imapx_store_get_junk_folder_sync (CamelStore *store,
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
 		CamelService *service;
-		const gchar *user_data_dir;
+		const gchar *user_cache_dir;
 		gchar *state;
 
 		service = CAMEL_SERVICE (store);
-		user_data_dir = camel_service_get_user_data_dir (service);
+		user_cache_dir = camel_service_get_user_cache_dir (service);
 
 		state = g_build_filename (
-			user_data_dir, "system", "Junk.cmeta", NULL);
+			user_cache_dir, "system", "Junk.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1265,14 +1265,14 @@ imapx_store_get_trash_folder_sync (CamelStore *store,
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
 		CamelService *service;
-		const gchar *user_data_dir;
+		const gchar *user_cache_dir;
 		gchar *state;
 
 		service = CAMEL_SERVICE (store);
-		user_data_dir = camel_service_get_user_data_dir (service);
+		user_cache_dir = camel_service_get_user_cache_dir (service);
 
 		state = g_build_filename (
-			user_data_dir, "system", "Trash.cmeta", NULL);
+			user_cache_dir, "system", "Trash.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1421,14 +1421,14 @@ imapx_store_rename_folder_sync (CamelStore *store,
 	CamelIMAPXServer *server;
 	CamelService *service;
 	CamelSettings *settings;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *oldpath, *newpath, *storage_path;
 	gboolean use_subscriptions;
 	gboolean success = FALSE;
 
 	service = CAMEL_SERVICE (store);
 	settings = camel_service_get_settings (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	use_subscriptions = camel_imapx_settings_get_use_subscriptions (
 		CAMEL_IMAPX_SETTINGS (settings));
@@ -1465,7 +1465,7 @@ imapx_store_rename_folder_sync (CamelStore *store,
 		success = imapx_subscribe_folder (
 			store, new, FALSE, cancellable, error);
 
-	storage_path = g_strdup_printf("%s/folders", user_data_dir);
+	storage_path = g_build_filename (user_cache_dir, "folders", NULL);
 	oldpath = imapx_path_to_physical (storage_path, old);
 	newpath = imapx_path_to_physical (storage_path, new);
 	g_free (storage_path);
@@ -1509,36 +1509,69 @@ imapx_store_noop_sync (CamelStore *store,
 	return success;
 }
 
+static void
+imapx_migrate_to_user_cache_dir (CamelService *service)
+{
+	const gchar *user_data_dir, *user_cache_dir;
+
+	g_return_if_fail (service != NULL);
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
+
+	g_return_if_fail (user_data_dir != NULL);
+	g_return_if_fail (user_cache_dir != NULL);
+
+	/* migrate only if the source directory exists and the destination doesn't */
+	if (g_file_test (user_data_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) &&
+	    !g_file_test (user_cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
+		gchar *parent_dir;
+
+		parent_dir = g_path_get_dirname (user_cache_dir);
+		g_mkdir_with_parents (parent_dir, S_IRWXU);
+		g_free (parent_dir);
+
+		if (g_rename (user_data_dir, user_cache_dir) == -1)
+			g_debug ("%s: Failed to migrate '%s' to '%s': %s", G_STRFUNC, user_data_dir, user_cache_dir, g_strerror (errno));
+	}
+}
+
 static gboolean
 imapx_store_initable_init (GInitable *initable,
                            GCancellable *cancellable,
                            GError **error)
 {
-	CamelIMAPXStore *store;
+	CamelIMAPXStore *imapx_store;
+	CamelStore *store;
 	CamelService *service;
 	CamelURL *url;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *summary;
 
-	store = CAMEL_IMAPX_STORE (initable);
+	imapx_store = CAMEL_IMAPX_STORE (initable);
+	store = CAMEL_STORE (initable);
+	service = CAMEL_SERVICE (initable);
+
+	store->flags |= CAMEL_STORE_USE_CACHE_DIR;
+	imapx_migrate_to_user_cache_dir (service);
 
 	/* Chain up to parent interface's init() method. */
 	if (!parent_initable_interface->init (initable, cancellable, error))
 		return FALSE;
 
-	service = CAMEL_SERVICE (initable);
 	url = camel_service_get_camel_url (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
-	store->base_url = camel_url_to_string (
+	imapx_store->base_url = camel_url_to_string (
 		url, CAMEL_URL_HIDE_PASSWORD |
 		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
 
-	store->summary = camel_imapx_store_summary_new ();
+	imapx_store->summary = camel_imapx_store_summary_new ();
 
-	summary = g_build_filename (user_data_dir, ".ev-store-summary", NULL);
-	camel_store_summary_set_filename ((CamelStoreSummary *) store->summary, summary);
-	camel_store_summary_load ((CamelStoreSummary *) store->summary);
+	summary = g_build_filename (user_cache_dir, ".ev-store-summary", NULL);
+	camel_store_summary_set_filename ((CamelStoreSummary *) imapx_store->summary, summary);
+	camel_store_summary_load ((CamelStoreSummary *) imapx_store->summary);
 
 	g_free (summary);
 
diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c
index 76dc0d1..37bebfd 100644
--- a/camel/providers/nntp/camel-nntp-folder.c
+++ b/camel/providers/nntp/camel-nntp-folder.c
@@ -695,11 +695,11 @@ camel_nntp_folder_new (CamelStore *parent,
 	gchar *root;
 	CamelService *service;
 	CamelStoreInfo *si;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gboolean subscribed = TRUE;
 
 	service = CAMEL_SERVICE (parent);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	folder = g_object_new (
 		CAMEL_TYPE_NNTP_FOLDER,
@@ -713,7 +713,7 @@ camel_nntp_folder_new (CamelStore *parent,
 		CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
 
 	nntp_folder->storage_path =
-		g_build_filename (user_data_dir, folder_name, NULL);
+		g_build_filename (user_cache_dir, folder_name, NULL);
 
 	root = g_strdup_printf ("%s.cmeta", nntp_folder->storage_path);
 	camel_object_set_state_filename (CAMEL_OBJECT (nntp_folder), root);
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c
index 444e5d0..1ed5045 100644
--- a/camel/providers/nntp/camel-nntp-store.c
+++ b/camel/providers/nntp/camel-nntp-store.c
@@ -25,12 +25,14 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 
+#include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
 
 #include "camel-nntp-folder.h"
@@ -331,14 +333,14 @@ connect_to_server (CamelService *service,
 	CamelDiscoStore *disco_store = (CamelDiscoStore *) service;
 	CamelURL *url;
 	CamelStream *tcp_stream;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gboolean retval = FALSE;
 	guchar *buf;
 	guint len;
 	gchar *path;
 
 	url = camel_service_get_camel_url (service);
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
@@ -390,7 +392,7 @@ connect_to_server (CamelService *service,
 		goto fail;
 
 	if (!disco_store->diary) {
-		path = g_build_filename (user_data_dir, ".ev-journal", NULL);
+		path = g_build_filename (user_cache_dir, ".ev-journal", NULL);
 		disco_store->diary = camel_disco_diary_new (disco_store, path, error);
 		g_free (path);
 	}
@@ -445,14 +447,14 @@ nntp_connect_offline (CamelService *service,
 {
 	CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (service);
 	CamelDiscoStore *disco_store = (CamelDiscoStore *) nntp_store;
-	const gchar *user_data_dir;
+	const gchar *user_cache_dir;
 	gchar *path;
 
-	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
 
 	/* setup store-wide cache */
 	if (nntp_store->cache == NULL) {
-		nntp_store->cache = camel_data_cache_new (user_data_dir, error);
+		nntp_store->cache = camel_data_cache_new (user_cache_dir, error);
 		if (nntp_store->cache == NULL)
 			return FALSE;
 
@@ -464,7 +466,7 @@ nntp_connect_offline (CamelService *service,
 	if (disco_store->diary)
 		return TRUE;
 
-	path = g_build_filename (user_data_dir, ".ev-journal", NULL);
+	path = g_build_filename (user_cache_dir, ".ev-journal", NULL);
 	disco_store->diary = camel_disco_diary_new (disco_store, path, error);
 	g_free (path);
 
@@ -1197,26 +1199,87 @@ nntp_can_refresh_folder (CamelStore *store,
 	return TRUE;
 }
 
+/* nntp stores part of its data in user_data_dir and part in user_cache_dir,
+   thus check whether to migrate based on folders.db file */
+static void
+nntp_migrate_to_user_cache_dir (CamelService *service)
+{
+	const gchar *user_data_dir, *user_cache_dir;
+	gchar *udd_folders_db, *ucd_folders_db;
+
+	g_return_if_fail (service != NULL);
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
+
+	g_return_if_fail (user_data_dir != NULL);
+	g_return_if_fail (user_cache_dir != NULL);
+
+	udd_folders_db = g_build_filename (user_data_dir, "folders.db", NULL);
+	ucd_folders_db = g_build_filename (user_cache_dir, "folders.db", NULL);
+
+	/* migrate only if the source directory exists and the destination doesn't */
+	if (g_file_test (udd_folders_db, G_FILE_TEST_EXISTS) &&
+	    !g_file_test (ucd_folders_db, G_FILE_TEST_EXISTS)) {
+		gchar *parent_dir;
+
+		parent_dir = g_path_get_dirname (user_cache_dir);
+		g_mkdir_with_parents (parent_dir, S_IRWXU);
+		g_free (parent_dir);
+
+		if (g_rename (user_data_dir, user_cache_dir) == -1) {
+			g_debug ("%s: Failed to migrate '%s' to '%s': %s", G_STRFUNC, user_data_dir, user_cache_dir, g_strerror (errno));
+		} else if (g_mkdir_with_parents (user_data_dir, S_IRWXU) != -1) {
+			gchar *udd_ev_store_summary, *ucd_ev_store_summary;
+
+			udd_ev_store_summary = g_build_filename (user_data_dir, ".ev-store-summary", NULL);
+			ucd_ev_store_summary = g_build_filename (user_cache_dir, ".ev-store-summary", NULL);
+
+			/* return back the .ev-store-summary file, it's saved in user_data_dir */
+			if (g_rename (ucd_ev_store_summary, udd_ev_store_summary) == -1)
+				g_debug ("%s: Failed to return back '%s' to '%s': %s", G_STRFUNC, ucd_ev_store_summary, udd_ev_store_summary, g_strerror (errno));
+		}
+	}
+
+	g_free (udd_folders_db);
+	g_free (ucd_folders_db);
+}
+
 static gboolean
 nntp_store_initable_init (GInitable *initable,
                           GCancellable *cancellable,
                           GError **error)
 {
 	CamelNNTPStore *nntp_store;
+	CamelStore *store;
 	CamelService *service;
 	CamelURL *url;
-	const gchar *user_data_dir;
+	const gchar *user_data_dir, *user_cache_dir;
 	gchar *tmp;
 
 	nntp_store = CAMEL_NNTP_STORE (initable);
+	store = CAMEL_STORE (initable);
+	service = CAMEL_SERVICE (initable);
+
+	store->flags |= CAMEL_STORE_USE_CACHE_DIR;
+	nntp_migrate_to_user_cache_dir (service);
 
 	/* Chain up to parent interface's init() method. */
 	if (!parent_initable_interface->init (initable, cancellable, error))
 		return FALSE;
 
-	service = CAMEL_SERVICE (initable);
 	url = camel_service_get_camel_url (service);
 	user_data_dir = camel_service_get_user_data_dir (service);
+	user_cache_dir = camel_service_get_user_cache_dir (service);
+
+	if (g_mkdir_with_parents (user_data_dir, S_IRWXU) == -1) {
+		g_set_error_literal (
+			error, G_FILE_ERROR,
+			g_file_error_from_errno (errno),
+			g_strerror (errno));
+		return FALSE;
+	}
 
 	/* FIXME */
 	nntp_store->base_url = camel_url_to_string (
@@ -1231,7 +1294,7 @@ nntp_store_initable_init (GInitable *initable,
 	camel_store_summary_load ((CamelStoreSummary *) nntp_store->summary);
 
 	/* setup store-wide cache */
-	nntp_store->cache = camel_data_cache_new (user_data_dir, error);
+	nntp_store->cache = camel_data_cache_new (user_cache_dir, error);
 	if (nntp_store->cache == NULL)
 		return FALSE;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]