aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog31
-rw-r--r--camel/camel-disco-folder.c109
-rw-r--r--camel/camel-disco-folder.h12
-rw-r--r--camel/camel-disco-store.c83
-rw-r--r--camel/camel-disco-store.h11
-rw-r--r--camel/camel-session.c27
-rw-r--r--camel/camel-session.h6
-rw-r--r--camel/camel.h2
-rw-r--r--camel/providers/imap/camel-imap-folder.c14
-rw-r--r--camel/providers/imap/camel-imap-store.c23
10 files changed, 308 insertions, 10 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 374811a26b..259f226100 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,34 @@
+2001-05-09 Dan Winship <danw@ximian.com>
+
+ * camel-disco-store.c (camel_disco_set_status): Set the
+ disconnected status.
+ (camel_disco_store_can_work_offline): Return whether or not a
+ given CamelDiscoStore can work offline or not.
+
+ * camel-disco-folder.c (camel_disco_folder_cache_message):
+ Explicitly tell a folder to cache a message. (Better than using
+ get_message, because for IMAP that doesn't guarantee you'll get
+ all the message parts.)
+ (camel_disco_folder_prepare_for_offline): Prepare a folder for
+ offline use by caching all messages meeting given search criteria
+ (and doing anything else the particular folder implementation
+ needs).
+
+ * camel-session.c (camel_session_set_online,
+ camel_session_is_online): A session-wide online/offline toggle.
+ (camel_session_init): Set online to TRUE.
+
+ * providers/imap/camel-imap-store.c (can_work_offline):
+ Implementation of CamelDiscoStore::can_work_offline. (Checks that
+ the store has been used online at least once.)
+ (imap_get_folder_online, imap_get_folder_offline): Deal with
+ request for "inbox" properly. ("Don't you mean... 'INBOX'?").
+
+ * providers/imap/camel-imap-folder.c (imap_cache_message):
+ Implementation of CamelDiscoFolder::cache_message.
+
+ * camel.h: Add camel-disco-store.h and camel-disco-folder.h
+
2001-05-09 Jeffrey Stedfast <fejj@ximian.com>
* camel-mime-part.c (camel_mime_part_set_content_id): Wrap the
diff --git a/camel/camel-disco-folder.c b/camel/camel-disco-folder.c
index 91a12adece..b090bd6517 100644
--- a/camel/camel-disco-folder.c
+++ b/camel/camel-disco-folder.c
@@ -46,6 +46,11 @@ static void disco_copy_messages_to (CamelFolder *source, GPtrArray *uids,
static void disco_move_messages_to (CamelFolder *source, GPtrArray *uids,
CamelFolder *destination, CamelException *ex);
+static void disco_cache_message (CamelDiscoFolder *disco_folder,
+ const char *uid, CamelException *ex);
+static void disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex);
static void
camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
@@ -54,6 +59,10 @@ camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
+ /* virtual method definition */
+ camel_disco_folder_class->cache_message = disco_cache_message;
+ camel_disco_folder_class->prepare_for_offline = disco_prepare_for_offline;
+
/* virtual method overload */
camel_folder_class->refresh_info = disco_refresh_info;
camel_folder_class->sync = disco_sync;
@@ -126,8 +135,11 @@ disco_expunge_uids (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
case CAMEL_DISCO_STORE_OFFLINE:
CDF_CLASS (folder)->expunge_uids_offline (folder, uids, ex);
#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids);
+ if (!camel_exception_is_set (ex)) {
+ camel_disco_diary_log (disco->diary,
+ CAMEL_DISCO_DIARY_FOLDER_EXPUNGE,
+ folder, uids);
+ }
#endif
break;
}
@@ -171,8 +183,11 @@ disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
case CAMEL_DISCO_STORE_OFFLINE:
uid = CDF_CLASS (folder)->append_offline (folder, message, info, ex);
#ifdef NOTYET
- if (uid)
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_APPEND, folder, uid);
+ if (uid) {
+ camel_disco_diary_log (disco->diary,
+ CAMEL_DISCO_DIARY_FOLDER_APPEND,
+ folder, uid);
+ }
#endif
break;
}
@@ -193,8 +208,11 @@ disco_copy_messages_to (CamelFolder *source, GPtrArray *uids,
case CAMEL_DISCO_STORE_OFFLINE:
CDF_CLASS (source)->copy_offline (source, uids, destination, ex);
#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_COPY, source, destination, uids);
+ if (!camel_exception_is_set (ex)) {
+ camel_disco_diary_log (disco->diary,
+ CAMEL_DISCO_DIARY_FOLDER_COPY,
+ source, destination, uids);
+ }
#endif
break;
}
@@ -214,8 +232,11 @@ disco_move_messages_to (CamelFolder *source, GPtrArray *uids,
case CAMEL_DISCO_STORE_OFFLINE:
CDF_CLASS (source)->move_offline (source, uids, destination, ex);
#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_MOVE, source, destination, uids);
+ if (!camel_exception_is_set (ex)) {
+ camel_disco_diary_log (disco->diary,
+ CAMEL_DISCO_DIARY_FOLDER_MOVE,
+ source, destination, uids);
+ }
#endif
break;
}
@@ -240,3 +261,75 @@ camel_disco_folder_expunge_uids (CamelFolder *folder, GPtrArray *uids,
{
disco_expunge_uids (folder, uids, ex);
}
+
+
+static void
+disco_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
+ CamelException *ex)
+{
+ g_warning ("CamelDiscoFolder::cache_message not implemented for `%s'",
+ camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_folder)));
+}
+
+/**
+ * camel_disco_folder_cache_message:
+ * @disco_folder: the folder
+ * @uid: the UID of the message to cache
+ * @ex: a CamelException
+ *
+ * Requests that @disco_folder cache message @uid to disk.
+ **/
+void
+camel_disco_folder_cache_message (CamelDiscoFolder *disco_folder,
+ const char *uid, CamelException *ex)
+{
+ CDF_CLASS (disco_folder)->cache_message (disco_folder, uid, ex);
+}
+
+
+static void
+disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex)
+{
+ CamelFolder *folder = CAMEL_FOLDER (disco_folder);
+ GPtrArray *uids;
+ int i;
+
+ if (expression)
+ uids = camel_folder_search_by_expression (folder, expression, ex);
+ else
+ uids = camel_folder_get_uids (folder);
+ if (!uids)
+ return;
+ for (i = 0; i < uids->len; i++) {
+ camel_disco_folder_cache_message (disco_folder, uids->pdata[i], ex);
+ if (camel_exception_is_set (ex))
+ break;
+ }
+ if (expression)
+ camel_folder_search_free (folder, uids);
+ else
+ camel_folder_free_uids (folder, uids);
+}
+
+/**
+ * camel_disco_folder_prepare_for_offline:
+ * @disco_folder: the folder
+ * @expression: an expression describing messages to synchronize, or %NULL
+ * if all messages should be sync'ed.
+ * @ex: a CamelException
+ *
+ * This prepares @disco_folder for offline operation, by downloading
+ * the bodies of all messages described by @expression (using the
+ * same syntax as camel_folder_search_by_expression() ).
+ **/
+void
+camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex)
+{
+ g_return_if_fail (CAMEL_IS_DISCO_FOLDER (disco_folder));
+
+ CDF_CLASS (disco_folder)->prepare_for_offline (disco_folder, expression, ex);
+}
diff --git a/camel/camel-disco-folder.h b/camel/camel-disco-folder.h
index 23e9d24923..cdca5a3b52 100644
--- a/camel/camel-disco-folder.h
+++ b/camel/camel-disco-folder.h
@@ -74,6 +74,12 @@ typedef struct {
void (*move_offline) (CamelFolder *source, GPtrArray *uids,
CamelFolder *destination, CamelException *ex);
+ void (*cache_message) (CamelDiscoFolder *disco_folder,
+ const char *uid, CamelException *ex);
+ void (*prepare_for_offline) (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex);
+
void (*update_uid) (CamelFolder *folder, const char *old_uid,
const char *new_uid);
} CamelDiscoFolderClass;
@@ -83,6 +89,12 @@ typedef struct {
void camel_disco_folder_expunge_uids (CamelFolder *folder, GPtrArray *uids,
CamelException *ex);
+void camel_disco_folder_cache_message (CamelDiscoFolder *disco_folder,
+ const char *uid,
+ CamelException *ex);
+void camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex);
/* Standard Camel function */
CamelType camel_disco_folder_get_type (void);
diff --git a/camel/camel-disco-store.c b/camel/camel-disco-store.c
index 10d3ae78b3..ae51b54f0f 100644
--- a/camel/camel-disco-store.c
+++ b/camel/camel-disco-store.c
@@ -40,6 +40,10 @@ static CamelFolder *disco_get_folder (CamelStore *store, const char *name,
static CamelFolderInfo *disco_get_folder_info (CamelStore *store,
const char *top, guint32 flags,
CamelException *ex);
+static void set_status (CamelDiscoStore *disco_store,
+ CamelDiscoStoreStatus status,
+ CamelException *ex);
+static gboolean can_work_offline (CamelDiscoStore *disco_store);
static void
camel_disco_store_class_init (CamelDiscoStoreClass *camel_disco_store_class)
@@ -51,6 +55,10 @@ camel_disco_store_class_init (CamelDiscoStoreClass *camel_disco_store_class)
remote_store_class = CAMEL_REMOTE_STORE_CLASS (camel_type_get_global_classfuncs (camel_remote_store_get_type ()));
+ /* virtual method definition */
+ camel_disco_store_class->set_status = set_status;
+ camel_disco_store_class->can_work_offline = can_work_offline;
+
/* virtual method overload */
camel_service_class->connect = disco_connect;
camel_service_class->disconnect = disco_disconnect;
@@ -172,6 +180,12 @@ disco_get_folder_info (CamelStore *store, const char *top,
}
+/**
+ * camel_disco_store_status:
+ * @store: a disconnectable store
+ *
+ * Return value: the current online/offline status of @store.
+ **/
CamelDiscoStoreStatus
camel_disco_store_status (CamelDiscoStore *store)
{
@@ -180,6 +194,75 @@ camel_disco_store_status (CamelDiscoStore *store)
return store->status;
}
+
+static void
+set_status (CamelDiscoStore *disco_store, CamelDiscoStoreStatus status,
+ CamelException *ex)
+{
+ if (disco_store->status == status)
+ return;
+
+ camel_store_sync (CAMEL_STORE (disco_store), ex);
+ if (camel_exception_is_set (ex))
+ return;
+ if (!camel_service_disconnect (CAMEL_SERVICE (disco_store), TRUE, ex))
+ return;
+
+ disco_store->status = status;
+ camel_service_connect (CAMEL_SERVICE (disco_store), ex);
+}
+
+/**
+ * camel_disco_store_set_status:
+ * @store: a disconnectable store
+ * @status: the new status
+ * @ex: a CamelException
+ *
+ * Sets @store to @status. If an error occurrs and the status cannot
+ * be set to @status, @ex will be set.
+ **/
+void
+camel_disco_store_set_status (CamelDiscoStore *store,
+ CamelDiscoStoreStatus status,
+ CamelException *ex)
+{
+ CDS_CLASS (store)->set_status (store, status, ex);
+}
+
+
+static gboolean
+can_work_offline (CamelDiscoStore *disco_store)
+{
+ g_warning ("CamelDiscoStore::can_work_offline not implemented for `%s'",
+ camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_store)));
+ return FALSE;
+}
+
+/**
+ * camel_disco_store_can_work_offline:
+ * @store: a disconnectable store
+ *
+ * Return value: whether or not @store can be used offline. (Will be
+ * %FALSE if the store is not caching data to local disk, for example.)
+ **/
+gboolean
+camel_disco_store_can_work_offline (CamelDiscoStore *store)
+{
+ return CDS_CLASS (store)->can_work_offline (store);
+}
+
+
+/**
+ * camel_disco_store_check_online:
+ * @store: a disconnectable store
+ * @ex: a CamelException
+ *
+ * This checks that @store is online, and sets @ex if it is not. This
+ * can be used as a simple way to set a generic error message in @ex
+ * for operations that won't work offline.
+ *
+ * Return value: whether or not @store is online.
+ **/
gboolean
camel_disco_store_check_online (CamelDiscoStore *store, CamelException *ex)
{
diff --git a/camel/camel-disco-store.h b/camel/camel-disco-store.h
index abd2693f80..cb40cf4590 100644
--- a/camel/camel-disco-store.h
+++ b/camel/camel-disco-store.h
@@ -57,6 +57,11 @@ struct _CamelDiscoStore {
typedef struct {
CamelRemoteStoreClass parent_class;
+ void (*set_status) (CamelDiscoStore *,
+ CamelDiscoStoreStatus,
+ CamelException *);
+ gboolean (*can_work_offline) (CamelDiscoStore *);
+
gboolean (*connect_online) (CamelService *,
CamelException *);
gboolean (*connect_offline) (CamelService *,
@@ -92,7 +97,11 @@ typedef struct {
CamelType camel_disco_store_get_type (void);
/* Public methods */
-CamelDiscoStoreStatus camel_disco_store_status (CamelDiscoStore *store);
+CamelDiscoStoreStatus camel_disco_store_status (CamelDiscoStore *);
+void camel_disco_store_set_status (CamelDiscoStore *,
+ CamelDiscoStoreStatus,
+ CamelException *);
+gboolean camel_disco_store_can_work_offline (CamelDiscoStore *);
/* Convenience functions */
gboolean camel_disco_store_check_online (CamelDiscoStore *store, CamelException *ex);
diff --git a/camel/camel-session.c b/camel/camel-session.c
index a6e308693f..5dbd19d963 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -81,6 +81,7 @@ static CamelProvider vee_provider = {
static void
camel_session_init (CamelSession *session)
{
+ session->online = TRUE;
session->modules = camel_provider_init ();
session->providers = g_hash_table_new (g_strcase_hash, g_strcase_equal);
session->priv = g_malloc0(sizeof(*session->priv));
@@ -640,3 +641,29 @@ camel_session_remove_timeout (CamelSession *session, guint handle)
return CS_CLASS (session)->remove_timeout (session, handle);
}
+
+
+/**
+ * camel_session_is_online:
+ * @session: the session.
+ *
+ * Return value: whether or not @session is online.
+ **/
+gboolean
+camel_session_is_online (CamelSession *session)
+{
+ return session->online;
+}
+
+/**
+ * camel_session_set_online:
+ * @session: the session
+ * @online: whether or not the session should be online
+ *
+ * Sets the online status of @session to @online.
+ **/
+void
+camel_session_set_online (CamelSession *session, gboolean online)
+{
+ session->online = online;
+}
diff --git a/camel/camel-session.h b/camel/camel-session.h
index e777bdcb6c..ba4a06490c 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -57,6 +57,7 @@ struct _CamelSession
char *storage_path;
GHashTable *providers, *modules;
+ gboolean online;
};
typedef struct {
@@ -162,6 +163,11 @@ guint camel_session_register_timeout (CamelSession *session,
gboolean camel_session_remove_timeout (CamelSession *session,
guint handle);
+
+gboolean camel_session_is_online (CamelSession *session);
+void camel_session_set_online (CamelSession *session,
+ gboolean online);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/camel/camel.h b/camel/camel.h
index e775f67812..e8708a70c9 100644
--- a/camel/camel.h
+++ b/camel/camel.h
@@ -37,6 +37,8 @@ extern "C" {
#include <camel/camel-exception.h>
#include <camel/camel-folder.h>
#include <camel/camel-digest-folder.h>
+#include <camel/camel-disco-folder.h>
+#include <camel/camel-disco-store.h>
#include <camel/camel-vee-folder.h>
#include <camel/camel-medium.h>
#include <camel/camel-mime-filter-basic.h>
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index d0828ccac9..852280127a 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -73,6 +73,7 @@ static void imap_sync_offline (CamelFolder *folder, CamelException *ex);
static const char *imap_get_full_name (CamelFolder *folder);
static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
+static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex);
/* message manipulation */
static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid,
@@ -118,6 +119,7 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class)
camel_disco_folder_class->append_offline = imap_append_offline;
camel_disco_folder_class->copy_online = imap_copy_online;
camel_disco_folder_class->copy_offline = imap_copy_offline;
+ camel_disco_folder_class->cache_message = imap_cache_message;
}
static void
@@ -1081,6 +1083,18 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
}
static void
+imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
+ CamelException *ex)
+{
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (disco_folder);
+ CamelStream *stream;
+
+ stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, ex);
+ if (stream)
+ camel_object_unref (CAMEL_OBJECT (stream));
+}
+
+static void
imap_update_summary (CamelFolder *folder,
CamelFolderChangeInfo *changes,
CamelException *ex)
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 74f420fe41..bcdfc9f935 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -63,6 +63,7 @@ static char imap_tag_prefix = 'A';
static void construct (CamelService *service, CamelSession *session,
CamelProvider *provider, CamelURL *url,
CamelException *ex);
+static gboolean can_work_offline (CamelDiscoStore *disco_store);
static gboolean imap_connect_online (CamelService *service, CamelException *ex);
static gboolean imap_connect_offline (CamelService *service, CamelException *ex);
static gboolean imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex);
@@ -117,6 +118,7 @@ camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class)
camel_remote_store_class->keepalive = imap_keepalive;
+ camel_disco_store_class->can_work_offline = can_work_offline;
camel_disco_store_class->connect_online = imap_connect_online;
camel_disco_store_class->connect_offline = imap_connect_offline;
camel_disco_store_class->disconnect_online = imap_disconnect_online;
@@ -539,6 +541,19 @@ imap_auth_loop (CamelService *service, CamelException *ex)
#define IMAP_STOREINFO_VERSION 1
static gboolean
+can_work_offline (CamelDiscoStore *disco_store)
+{
+ CamelImapStore *store = CAMEL_IMAP_STORE (disco_store);
+ char *path;
+ gboolean can;
+
+ path = g_strdup_printf ("%s/storeinfo", store->storage_path);
+ can = access (path, F_OK) == 0;
+ g_free (path);
+ return can;
+}
+
+static gboolean
imap_connect_online (CamelService *service, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
@@ -751,11 +766,11 @@ imap_disconnect_online (CamelService *service, gboolean clean, CamelException *e
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelImapResponse *response;
- imap_disconnect_offline (service, clean, ex);
if (store->connected && clean) {
response = camel_imap_command (store, NULL, ex, "LOGOUT");
camel_imap_response_free (store, response);
}
+ imap_disconnect_offline (service, clean, ex);
return TRUE;
}
@@ -801,6 +816,9 @@ get_folder_online (CamelStore *store, const char *folder_name,
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
return NULL;
+ if (!g_strcasecmp (folder_name, "INBOX"))
+ folder_name = "INBOX";
+
/* Lock around the whole lot to check/create atomically */
CAMEL_IMAP_STORE_LOCK (imap_store, command_lock);
if (imap_store->current_folder) {
@@ -858,6 +876,9 @@ get_folder_offline (CamelStore *store, const char *folder_name,
!camel_service_connect (CAMEL_SERVICE (store), ex))
return NULL;
+ if (!g_strcasecmp (folder_name, "INBOX"))
+ folder_name = "INBOX";
+
folder_dir = e_path_to_physical (imap_store->storage_path, folder_name);
if (access (folder_dir, F_OK) != 0)
return no_such_folder (folder_name, ex);