diff options
author | Dan Winship <danw@src.gnome.org> | 2001-05-04 04:52:59 +0800 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2001-05-04 04:52:59 +0800 |
commit | 7c553e6e5bb47c7b4b26f9bed147e7b7df234f96 (patch) | |
tree | 75b27df033aa84aa60eeea841fd8341ff6c415e4 /camel/providers/imap/camel-imap-folder.c | |
parent | 57546880c8e3470834bb7012aee9d892e3ac6708 (diff) | |
download | gsoc2013-evolution-7c553e6e5bb47c7b4b26f9bed147e7b7df234f96.tar.gz gsoc2013-evolution-7c553e6e5bb47c7b4b26f9bed147e7b7df234f96.tar.zst gsoc2013-evolution-7c553e6e5bb47c7b4b26f9bed147e7b7df234f96.zip |
new abstract class for disconnectable remote stores
* camel-disco-store.c: new abstract class for disconnectable
remote stores
* camel-disco-folder.c: new abstract class for folders on
disconnectable stores.
* Makefile.am: Add camel-disco-folder.[ch] and
camel-disco-store.[ch].
* providers/imap/camel-imap-store.c: Make this a subclass of
CamelDiscoStore, and fix up the offline interfaces for the changes
since they were first written (particularly the fact that some
IMAP stores don't just use subscribed folders).
* providers/imap/camel-imap-folder.c: Make this a subclass of
CamelDiscoFolder, although most ops still fail in disconnected
mode.
* camel-store.c (camel_store_get_folder_info): Change gboolean,
gboolean, gboolean to guint32 in the prototype for this function.
* providers/local/camel-local-store.c (get_folder_info): Update
for prototype change.
svn path=/trunk/; revision=9659
Diffstat (limited to 'camel/providers/imap/camel-imap-folder.c')
-rw-r--r-- | camel/providers/imap/camel-imap-folder.c | 240 |
1 files changed, 133 insertions, 107 deletions
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 4ee65371fd..d0828ccac9 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -2,9 +2,11 @@ /* camel-imap-folder.c: class for an imap folder */ /* - * Authors: Jeffrey Stedfast <fejj@helixcode.com> + * Authors: + * Dan Winship <danw@ximian.com> + * Jeffrey Stedfast <fejj@ximian.com> * - * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000, 2001 Ximian, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -60,26 +62,29 @@ #include "camel-multipart.h" #include "camel-operation.h" -#define d(x) x - #define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) - -static CamelFolderClass *parent_class = NULL; +static CamelDiscoFolderClass *disco_folder_class = NULL; static void imap_finalize (CamelObject *object); static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); +static void imap_sync_online (CamelFolder *folder, CamelException *ex); +static void imap_sync_offline (CamelFolder *folder, CamelException *ex); static const char *imap_get_full_name (CamelFolder *folder); -static void imap_expunge (CamelFolder *folder, CamelException *ex); +static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex); +static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex); /* message manipulation */ static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static void imap_append_message (CamelFolder *folder, CamelMimeMessage *message, +static char *imap_append_online (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex); -static void imap_copy_messages_to (CamelFolder *source, GPtrArray *uids, - CamelFolder *destination, CamelException *ex); +static char *imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, + const CamelMessageInfo *info, CamelException *ex); +static void imap_copy_online (CamelFolder *source, GPtrArray *uids, + CamelFolder *destination, CamelException *ex); +static void imap_copy_offline (CamelFolder *source, GPtrArray *uids, + CamelFolder *destination, CamelException *ex); static void imap_move_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *destination, CamelException *ex); @@ -93,24 +98,26 @@ static void camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) { CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_imap_folder_class); + CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_imap_folder_class); + + disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ())); - parent_class = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); - - /* virtual method definition */ - /* virtual method overload */ - camel_folder_class->refresh_info = imap_refresh_info; - camel_folder_class->sync = imap_sync; - camel_folder_class->expunge = imap_expunge; camel_folder_class->get_full_name = imap_get_full_name; - camel_folder_class->get_message = imap_get_message; - camel_folder_class->append_message = imap_append_message; - camel_folder_class->copy_messages_to = imap_copy_messages_to; camel_folder_class->move_messages_to = imap_move_messages_to; - camel_folder_class->search_by_expression = imap_search_by_expression; camel_folder_class->search_free = imap_search_free; + + camel_disco_folder_class->refresh_info_online = imap_refresh_info; + camel_disco_folder_class->sync_online = imap_sync_online; + camel_disco_folder_class->sync_offline = imap_sync_offline; + camel_disco_folder_class->expunge_uids_online = imap_expunge_uids_online; + camel_disco_folder_class->expunge_uids_offline = imap_expunge_uids_offline; + camel_disco_folder_class->append_online = imap_append_online; + 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; } static void @@ -136,7 +143,7 @@ camel_imap_folder_get_type (void) if (camel_imap_folder_type == CAMEL_INVALID_TYPE) { camel_imap_folder_type = - camel_type_register (CAMEL_FOLDER_TYPE, "CamelImapFolder", + camel_type_register (CAMEL_DISCO_FOLDER_TYPE, "CamelImapFolder", sizeof (CamelImapFolder), sizeof (CamelImapFolderClass), (CamelObjectClassInitFunc) camel_imap_folder_class_init, @@ -150,15 +157,27 @@ camel_imap_folder_get_type (void) CamelFolder * camel_imap_folder_new (CamelStore *parent, const char *folder_name, - const char *short_name, const char *folder_dir, - CamelException *ex) + const char *folder_dir, CamelException *ex) { CamelImapStore *imap_store = CAMEL_IMAP_STORE (parent); - CamelFolder *folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapResponse *response; + CamelFolder *folder; + CamelImapFolder *imap_folder; + const char *short_name; char *summary_file; + if (camel_mkdir_hier (folder_dir, S_IRWXU) != 0) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Could not create directory %s: %s"), + folder_dir, g_strerror (errno)); + return NULL; + } + + folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); + short_name = strrchr (folder_name, imap_store->dir_sep); + if (short_name) + short_name++; + else + short_name = folder_name; camel_folder_construct (folder, parent, folder_name, short_name); summary_file = g_strdup_printf ("%s/summary", folder_dir); @@ -172,22 +191,13 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name, return NULL; } + imap_folder = CAMEL_IMAP_FOLDER (folder); imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex); if (!imap_folder->cache) { camel_object_unref (CAMEL_OBJECT (folder)); return NULL; } - if (camel_imap_store_check_online (imap_store, NULL)) { - response = camel_imap_command (imap_store, folder, ex, NULL); - if (response) - camel_imap_response_free (imap_store, response); - else { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - } - return folder; } @@ -321,7 +331,7 @@ imap_finalize (CamelObject *object) static void imap_refresh_info (CamelFolder *folder, CamelException *ex) { - if (!camel_imap_store_check_online (CAMEL_IMAP_STORE (folder->parent_store), NULL)) + if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_OFFLINE) return; CAMEL_IMAP_STORE_LOCK (folder->parent_store, command_lock); @@ -499,7 +509,13 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) } static void -imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) +imap_sync_offline (CamelFolder *folder, CamelException *ex) +{ + camel_folder_summary_save (folder->summary); +} + +static void +imap_sync_online (CamelFolder *folder, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); CamelImapResponse *response = NULL; @@ -508,43 +524,13 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) char *set, *flaglist; int i, j, max; - if (!camel_imap_store_check_online (store, NULL)) - return; - - max = camel_folder_summary_count (folder->summary); - CAMEL_IMAP_STORE_LOCK (store, command_lock); - /* If we're expunging then we don't need to be precise about the - * flags of deleted messages. Just add \Deleted to anything that - * should have it. - */ - if (expunge && (matches = get_matching (folder, CAMEL_MESSAGE_DELETED, - CAMEL_MESSAGE_DELETED, &set))) { - for (i = 0; i < matches->len; i++) { - info = matches->pdata[i]; - info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_folder_summary_info_free (folder->summary, info); - } - g_ptr_array_free (matches, TRUE); - camel_folder_summary_touch (folder->summary); - - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT \\Deleted", - set); - g_free (set); - if (response) - camel_imap_response_free (store, response); - if (camel_exception_is_set (ex)) { - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - return; - } - } - - /* OK, now, find a message with changed flags, find all of the - * other messages like it, sync them as a group, mark them as + /* Find a message with changed flags, find all of the other + * messages like it, sync them as a group, mark them as * updated, and continue. */ + max = camel_folder_summary_count (folder->summary); for (i = 0; i < max; i++) { info = camel_folder_summary_index (folder->summary, i); if (!info) @@ -587,32 +573,55 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) } } - if (expunge) { - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - camel_imap_response_free (store, response); - } - if (!response) { - /* We didn't sync or expunge anything... Do a noop so - * the server gets a chance to tell us any news it has. + /* We didn't sync anything... Do a noop so the server + * gets a chance to tell us any news it has. */ response = camel_imap_command (store, folder, ex, "NOOP"); camel_imap_response_free (store, response); } - camel_folder_summary_save (folder->summary); + /* Save the summary */ + imap_sync_offline (folder, ex); + CAMEL_IMAP_STORE_UNLOCK (store, command_lock); +} - camel_operation_end(NULL); +static void +imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex) +{ + /* Fail */ + camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex); } static void -imap_expunge (CamelFolder *folder, CamelException *ex) +imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex) { - if (!camel_imap_store_check_online (CAMEL_IMAP_STORE (folder->parent_store), ex)) + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + CamelImapResponse *response; + char *set; + + set = imap_uid_array_to_set (folder->summary, uids); + CAMEL_IMAP_STORE_LOCK (store, command_lock); + response = camel_imap_command (store, folder, ex, + "UID STORE %s +FLAGS.SILENT \\Deleted", + set); + if (response) + camel_imap_response_free (store, response); + if (camel_exception_is_set (ex)) { + CAMEL_IMAP_STORE_UNLOCK (store, command_lock); + g_free (set); return; + } - imap_sync (folder, TRUE, ex); + if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { + response = camel_imap_command (store, folder, ex, + "UID EXPUNGE %s", set); + } else + response = camel_imap_command (store, folder, ex, "EXPUNGE"); + if (response) + camel_imap_response_free (store, response); + CAMEL_IMAP_STORE_UNLOCK (store, command_lock); } static const char * @@ -634,20 +643,26 @@ imap_get_full_name (CamelFolder *folder) return name; } -static void -imap_append_message (CamelFolder *folder, CamelMimeMessage *message, +static char * +imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex) { + /* Fail */ + camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex); + return NULL; +} + +static char * +imap_append_online (CamelFolder *folder, CamelMimeMessage *message, + const CamelMessageInfo *info, CamelException *ex) +{ CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); CamelImapResponse *response; CamelStream *memstream; CamelMimeFilter *crlf_filter; CamelStreamFilter *streamfilter; GByteArray *ba; - char *flagstr, *result, *uid; - - if (!camel_imap_store_check_online (store, ex)) - return; + char *flagstr, *result, *uid = NULL; /* create flag string param */ if (info && info->flags) @@ -678,12 +693,12 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, if (!response) { g_byte_array_free (ba, TRUE); - return; + return NULL; } result = camel_imap_response_extract_continuation (store, response, ex); if (!result) { g_byte_array_free (ba, TRUE); - return; + return NULL; } g_free (result); @@ -692,7 +707,7 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, response = camel_imap_command_continuation (store, ex, ba->data); g_byte_array_free (ba, TRUE); if (!response) - return; + return NULL; if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { uid = strstrcase (response->status, "[APPENDUID "); @@ -707,15 +722,26 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, camel_imap_message_cache_insert_wrapper ( CAMEL_IMAP_FOLDER (folder)->cache, uid, "", CAMEL_DATA_WRAPPER (message)); + } else { + g_free (uid); + uid = NULL; } - g_free (uid); } } camel_imap_response_free (store, response); + return uid; } static void +imap_copy_offline (CamelFolder *source, GPtrArray *uids, + CamelFolder *destination, CamelException *ex) +{ + /* Fail */ + camel_disco_store_check_online (CAMEL_DISCO_STORE (source->parent_store), ex); +} + +static void handle_copyuid (CamelImapResponse *response, CamelFolder *source, CamelFolder *destination) { @@ -769,18 +795,15 @@ handle_copyuid (CamelImapResponse *response, CamelFolder *source, } static void -imap_copy_messages_to (CamelFolder *source, GPtrArray *uids, - CamelFolder *destination, CamelException *ex) +imap_copy_online (CamelFolder *source, GPtrArray *uids, + CamelFolder *destination, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); CamelImapResponse *response; char *set; - if (!camel_imap_store_check_online (store, ex)) - return; - /* Sync message flags if needed. */ - imap_sync (source, FALSE, ex); + imap_sync_online (source, ex); if (camel_exception_is_set (ex)) return; @@ -807,11 +830,11 @@ imap_move_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *destination, CamelException *ex) { int i; - - imap_copy_messages_to (source, uids, destination, ex); + + CF_CLASS (disco_folder_class)->copy_messages_to (source, uids, destination, ex); if (camel_exception_is_set (ex)) return; - + for (i = 0; i < uids->len; i++) camel_folder_delete_message (source, uids->pdata[i]); } @@ -822,7 +845,7 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); GPtrArray *matches, *summary; - if (!camel_imap_store_check_online (CAMEL_IMAP_STORE (folder->parent_store), ex)) + if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex)) return NULL; /* we could get around this by creating a new search object each time, @@ -1015,7 +1038,7 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) char *body, *found_uid; int i; - if (!camel_imap_store_check_online (store, NULL)) { + if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("This message is not currently available")); return NULL; @@ -1212,6 +1235,8 @@ camel_imap_folder_changed (CamelFolder *folder, int exists, "folder_changed", changes); } camel_folder_change_info_free (changes); + + camel_folder_summary_save (folder->summary); } @@ -1235,9 +1260,10 @@ camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid, return stream; } - if (!camel_imap_store_check_online (store, NULL)) { + if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("This message is not currently available")); + CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); return NULL; } |