diff options
Diffstat (limited to 'camel')
-rw-r--r-- | camel/ChangeLog | 21 | ||||
-rw-r--r-- | camel/camel-vee-folder.c | 187 | ||||
-rw-r--r-- | camel/camel-vee-folder.h | 14 | ||||
-rw-r--r-- | camel/camel-vtrash-folder.c | 22 |
4 files changed, 139 insertions, 105 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 2f80e15653..01d7af9d42 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,24 @@ +2001-03-29 Not Zed <NotZed@Ximian.com> + + * camel-vtrash-folder.c (vtrash_move_messages_to): Access the + folder directly from the message info. + (vtrash_move_messages_to): I think we also need to call the real + move_messages_to, and not try and bypass the lock, since we dont + have the lock for that folder. + + * camel-vee-folder.h: Move CamelVeeMessageInfo to public, so + subclasses can get to it. + + * camel-vee-folder.c (camel_vee_folder_add_folder): Dont let you + add a vfolder to itself. + (folder_changed): + (vee_folder_remove_folder): + (vee_folder_build_folder): Copy changes before triggering changed + events, so we can do them outside of locks. + (camel_vee_folder_get_message_folder): Removed function. + (camel_vee_folder_hash_folder): Made public (renamed from + hash_folder), simply for subclasses (probably not needed). + 2001-03-27 Jeffrey Stedfast <fejj@ximian.com> * camel-service.c (get_path): Add the port (if user defined) to diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index b6dba402f1..a4585eec17 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -42,16 +42,8 @@ #define d(x) -/* our message info includes the parent folder */ -typedef struct _CamelVeeMessageInfo { - CamelMessageInfo info; - CamelFolder *folder; -} CamelVeeMessageInfo; - #define _PRIVATE(o) (((CamelVeeFolder *)(o))->priv) -static void hash_folder(CamelFolder *folder, char buffer[8]); - static void vee_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); static void vee_expunge (CamelFolder *folder, CamelException *ex); @@ -319,6 +311,11 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) { struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); + if (vf == (CamelVeeFolder *)sub) { + g_warning("Adding a virtual folder to itself as source, ignored"); + return; + } + CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); /* for normal vfolders we want only unique ones, for unmatched we want them all recorded */ @@ -372,6 +369,39 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_object_unref((CamelObject *)sub); } +/** + * camel_vee_folder_hash_folder: + * @folder: + * @: + * + * Create a hash string representing the folder name, which should be + * unique, and remain static for a given folder. + **/ +void +camel_vee_folder_hash_folder(CamelFolder *folder, char buffer[8]) +{ + MD5Context ctx; + unsigned char digest[16]; + unsigned int state = 0, save = 0; + char *tmp; + int i; + + md5_init(&ctx); + tmp = camel_service_get_url((CamelService *)folder->parent_store); + md5_update(&ctx, tmp, strlen(tmp)); + g_free(tmp); + md5_update(&ctx, folder->full_name, strlen(folder->full_name)); + md5_final(&ctx, digest); + base64_encode_close(digest, 6, FALSE, buffer, &state, &save); + + for (i=0;i<8;i++) { + if (buffer[i] == '+') + buffer[i] = '.'; + if (buffer[i] == '/') + buffer[i] = '_'; + } +} + static void vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) { @@ -444,7 +474,7 @@ vee_search_by_expression(CamelFolder *folder, const char *expression, CamelExcep /* make sure we only search each folder once - for unmatched folder to work right */ if (g_hash_table_lookup(searched, f) == NULL) { - hash_folder(f, hash); + camel_vee_folder_hash_folder(f, hash); matches = camel_folder_search_by_expression(f, expression, ex); for (i = 0; i < matches->len; i++) { char *uid = matches->pdata[i]; @@ -518,32 +548,6 @@ vee_move_messages_to (CamelFolder *folder, GPtrArray *uids, CamelFolder *dest, C /* ********************************************************************** * utility functions */ -/* convert a folder name (full path) into a 8 character identifier that should be static */ -static void -hash_folder(CamelFolder *folder, char buffer[8]) -{ - MD5Context ctx; - unsigned char digest[16]; - unsigned int state = 0, save = 0; - char *tmp; - int i; - - md5_init(&ctx); - tmp = camel_service_get_url((CamelService *)folder->parent_store); - md5_update(&ctx, tmp, strlen(tmp)); - g_free(tmp); - md5_update(&ctx, folder->full_name, strlen(folder->full_name)); - md5_final(&ctx, digest); - base64_encode_close(digest, 6, FALSE, buffer, &state, &save); - - for (i=0;i<8;i++) { - if (buffer[i] == '+') - buffer[i] = '.'; - if (buffer[i] == '/') - buffer[i] = '_'; - } -} - /* must be called with summary_lock held */ static CamelVeeMessageInfo * vee_folder_add_info(CamelVeeFolder *vf, CamelFolder *f, CamelMessageInfo *info, const char hash[8]) @@ -602,6 +606,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) CamelFolder *folder = (CamelFolder *)vf; char hash[8]; struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; if (vf == folder_unmatched) return; @@ -611,7 +616,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); still = g_list_find(p->folders, source) != NULL; CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); - hash_folder(source, hash); + camel_vee_folder_hash_folder(source, hash); } else { still = FALSE; } @@ -654,19 +659,28 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) } } - if (camel_folder_change_info_changed(vf->changes)) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf->changes); - camel_folder_change_info_clear(vf->changes); + if (camel_folder_change_info_changed(folder_unmatched->changes)) { + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); } - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", folder_unmatched->changes); - camel_folder_change_info_clear(folder_unmatched->changes); + if (camel_folder_change_info_changed(vf->changes)) { + vf_changes = vf->changes; + vf->changes = camel_folder_change_info_new(); } CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); + if (unmatched_changes) { + camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); + camel_folder_change_info_free(unmatched_changes); + } + + if (vf_changes) { + camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); + } } struct _update_data { @@ -725,6 +739,7 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException CamelFolder *folder = (CamelFolder *)vf; int i, n, count; struct _update_data u; + CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; if (vf == folder_unmatched) return 0; @@ -735,7 +750,7 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException u.source = source; u.vf = vf; - hash_folder(source, u.hash); + camel_vee_folder_hash_folder(source, u.hash); CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); @@ -810,26 +825,35 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException /* now allhash contains all potentially new uid's for the unmatched folder, process */ g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u); + /* copy any changes so we can raise them outside the lock */ + if (camel_folder_change_info_changed(folder_unmatched->changes)) { + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); + } + + if (camel_folder_change_info_changed(vf->changes)) { + vf_changes = vf->changes; + vf->changes = camel_folder_change_info_new(); + } + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); + CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); g_hash_table_destroy(matchhash); g_hash_table_destroy(allhash); camel_folder_search_free(f, match); camel_folder_free_uids(f, all); - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", folder_unmatched->changes); - camel_folder_change_info_clear(folder_unmatched->changes); + if (unmatched_changes) { + camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); + camel_folder_change_info_free(unmatched_changes); } - - if (camel_folder_change_info_changed(vf->changes)) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf->changes); - camel_folder_change_info_clear(vf->changes); + if (vf_changes) { + camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); } - CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); - return 0; } @@ -875,8 +899,9 @@ folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder CamelMessageInfo *info; char *oldkey; int n; + CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; - hash_folder(sub, hash); + camel_vee_folder_hash_folder(sub, hash); /* if not auto-updating, only propagate changed/removed events, not added items */ if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0) { @@ -916,19 +941,29 @@ folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder g_free(vuid); } - if (camel_folder_change_info_changed(vf->changes)) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf->changes); - camel_folder_change_info_clear(vf->changes); - } - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", folder_unmatched->changes); - camel_folder_change_info_clear(folder_unmatched->changes); + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); + } + + if (camel_folder_change_info_changed(vf->changes)) { + vf_changes = vf->changes; + vf->changes = camel_folder_change_info_new(); } CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); + if (unmatched_changes) { + camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); + camel_folder_change_info_free(unmatched_changes); + } + + if (vf_changes) { + camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); + camel_folder_change_info_free(vf_changes); + } + return; } @@ -1013,35 +1048,3 @@ message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *vf) folder_changed(f, changes, vf); camel_folder_change_info_free(changes); } - - -/** - * camel_vee_folder_get_message_folder: - * @vf: Virtual Folder object - * @uid: message uid - * - * Returns the parent folder of @uid if it exists, otherwise NULL. - * Note: You must unref the folder when finished with it. - **/ -CamelFolder * -camel_vee_folder_get_message_folder (CamelVeeFolder *vf, const gchar *uid) -{ - CamelVeeMessageInfo *mi; - CamelFolder *folder; - - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - - mi = (CamelVeeMessageInfo *)camel_folder_summary_uid (CAMEL_FOLDER (vf)->summary, uid); - if (mi) { - camel_object_ref (CAMEL_OBJECT (mi->folder)); - folder = mi->folder; - } else { - folder = NULL; - } - - CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); - - return folder; -} - - diff --git a/camel/camel-vee-folder.h b/camel/camel-vee-folder.h index b410bc26dc..6cd75aaf20 100644 --- a/camel/camel-vee-folder.h +++ b/camel/camel-vee-folder.h @@ -31,6 +31,12 @@ typedef struct _CamelVeeFolder CamelVeeFolder; typedef struct _CamelVeeFolderClass CamelVeeFolderClass; +/* our message info includes the parent folder */ +typedef struct _CamelVeeMessageInfo { + CamelMessageInfo info; + CamelFolder *folder; +} CamelVeeMessageInfo; + struct _CamelVeeFolder { CamelFolder parent; @@ -53,10 +59,10 @@ guint camel_vee_folder_get_type (void); CamelFolder *camel_vee_folder_new (CamelStore *parent_store, const char *name, guint32 flags); void camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags); -void camel_vee_folder_add_folder (CamelVeeFolder *vf, CamelFolder *sub); -void camel_vee_folder_remove_folder (CamelVeeFolder *vf, CamelFolder *sub); -void camel_vee_folder_set_expression (CamelVeeFolder *vf, const char *expr); +void camel_vee_folder_add_folder (CamelVeeFolder *vf, CamelFolder *sub); +void camel_vee_folder_remove_folder (CamelVeeFolder *vf, CamelFolder *sub); +void camel_vee_folder_set_expression (CamelVeeFolder *vf, const char *expr); -CamelFolder *camel_vee_folder_get_message_folder (CamelVeeFolder *vf, const char *uid); +void camel_vee_folder_hash_folder (CamelFolder *folder, char buffer[8]); #endif /* ! _CAMEL_VEE_FOLDER_H */ diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c index acaa9c5b34..ed8e9f0765 100644 --- a/camel/camel-vtrash-folder.c +++ b/camel/camel-vtrash-folder.c @@ -112,27 +112,31 @@ vtrash_copy_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *dest static void vtrash_move_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, CamelException *ex) { - CamelFolder *original; + CamelVeeMessageInfo *mi; int i; for (i = 0; i < uids->len; i++) { - original = camel_vee_folder_get_message_folder (CAMEL_VEE_FOLDER (source), uids->pdata[i]); - - if (dest == original) { + mi = (CamelVeeMessageInfo *)camel_folder_get_message_info(source, uids->pdata[i]); + if (mi == NULL) { + g_warning("Cannot find uid %s in source folder during move_to", (char *)uids->pdata[i]); + continue; + } + + if (dest == mi->folder) { /* Just undelete the original message */ CAMEL_FOLDER_CLASS (dest)->set_message_flags (dest, uids->pdata[i], CAMEL_MESSAGE_DELETED, 0); - } else if (original) { + } else { /* This means that the user is trying to move the message from the vTrash to a folder other than the original. */ GPtrArray *tuids; tuids = g_ptr_array_new (); g_ptr_array_add (tuids, uids->pdata[i]); - CAMEL_FOLDER_CLASS (original)->move_messages_to (original, tuids, dest, ex); + /*CAMEL_FOLDER_CLASS (mi->folder)->move_messages_to (mi->folder, tuids, dest, ex);*/ + camel_folder_move_messages_to(mi->folder, tuids, dest, ex); g_ptr_array_free (tuids, TRUE); } - - if (original) - camel_object_unref (CAMEL_OBJECT (original)); + + camel_folder_free_message_info(source, (CamelMessageInfo *)mi); } } |