From c31f10dc76d7515690bfa4918ca9c9c0fa89cc46 Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Thu, 15 Sep 2011 00:59:36 +0000 Subject: [PATCH] See ChangeLog Monotone-Parent: 3d7f4c315141a708ca8e3535fb0792843e1b8f9a Monotone-Revision: 84da44fa0ad497e68382786d494389cd5f8872ce Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2011-09-15T00:59:36 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 8 +++ OpenChange/MAPIStoreMailFolder.m | 80 +++++++++++++++++++-------- SoObjects/Mailer/SOGoMailBaseObject.m | 15 ++++- 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8e11f8ff..f98583f30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,14 @@ * SoObject/Mailer/SOGoMailFolder.m (prefetchCoreInfosForMessageKeys:) Fixed a MAJOR issue regarding keys handling. We should NEVER assume the untagged IMAP response's order will be the same as the FETCH's one! + + * SoObjects/Mailer/SOGoMailBaseObject.m: (imap4Connection) We now + ensure the context is valid to properly get the user's login by + using the container's context if the current one is nil + + * OpenChange/MAPIStoreMailFolder.m: (moveCopy...) Cleaned up some + code and we now also correctly send notification updates for the + destination folder 2011-09-04 Ludovic Marcotte diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index 6621abb2c..236395433 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -674,10 +674,15 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) uint64_t target_mid; int rc; - mapping = [[self context] mapping]; - - messageURL = [mapping urlFromID: mid]; + // FIXME + // We only support IMAP-to-IMAP copy operations for now. + // Otherwise we silently fail (for now, at least!) + if (![targetFolder isKindOfClass: [MAPIStoreMailFolder class]]) + return MAPISTORE_SUCCESS; + mapping = [[self context] mapping]; + messageURL = [mapping urlFromID: mid]; + if (messageURL) { // We get the message UID from that folder by stripping the .eml @@ -689,15 +694,22 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) if (uid && [folderName length] > 0) { + MAPIStoreMessage *message; + NSArray *a, *activeTables; + NGImap4Client *client; + struct mapistore_object_notification_parameters *notif_parameters; struct mapistore_connection_info *connInfo; - NGImap4Client *client; - NSArray *a; + NSUInteger count, max; // We copy the message, get the new UID and set the old one as deleted client = [[[self sogoObject] imap4Connection] client]; [client select: [[self sogoObject] relativeImap4Name]]; result = [client copyUid: [uid intValue] toFolder: folderName]; + + // We check if the COPY operation succeeded + if (![[result objectForKey: @"result"] boolValue]) + return MAPISTORE_ERR_NOT_FOUND; if (!want_copy) [client storeUid: [uid intValue] add: [NSNumber numberWithBool: YES] flags: [NSArray arrayWithObject: @"Deleted"]]; @@ -745,23 +757,16 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) [mapping unregisterURLWithID: target_mid]; [mapping registerURL: url withID: target_mid]; - NSArray *activeTables; - NSUInteger count, max; - /* we ensure the table caches are loaded so that old and new state - can be compared */ - MAPIStoreMessage *message; - + + // For the "source folder, we ensure the table caches are loaded so + // that old and new state can be compared message = [self lookupMessageByURL: messageURL]; - activeTables = ([message isKindOfClass: [MAPIStoreFAIMessage class]] - ? [self activeFAIMessageTables] - : [self activeMessageTables]); + activeTables = [self activeMessageTables]; max = [activeTables count]; for (count = 0; count < max; count++) [[activeTables objectAtIndex: count] restrictedChildKeys]; - - - - // We notify the client + + // We notify the client. We start with the source folder. notif_parameters = talloc_zero(NULL, struct mapistore_object_notification_parameters); notif_parameters->object_id = [self objectId]; notif_parameters->tag_count = 5; @@ -772,7 +777,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) notif_parameters->tags[3] = PR_NORMAL_MESSAGE_SIZE; notif_parameters->tags[4] = PR_RECIPIENT_ON_NORMAL_MSG_COUNT; notif_parameters->new_message_count = true; - notif_parameters->message_count = [[self messageKeys] count]; + notif_parameters->message_count = [[self messageKeys] count] - 1; connInfo = [[self context] connectionInfo]; mapistore_push_notification (connInfo->mstore_ctx, MAPISTORE_FOLDER, @@ -780,7 +785,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) notif_parameters); talloc_free(notif_parameters); - /* move/copy notification */ + // move/copy notification of the copied/moved message notif_parameters = talloc_zero(NULL, struct mapistore_object_notification_parameters); notif_parameters->tag_count = 0; notif_parameters->new_message_count = true; @@ -796,12 +801,43 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) notif_parameters); talloc_free(notif_parameters); - /* table notification */ + // table notification for (count = 0; count < max; count++) [[activeTables objectAtIndex: count] notifyChangesForChild: message]; - // We cleanup cache of our source and destionation folders + // For the "destination folder, we ensure the table caches are loaded so + // that old and new state can be compared + message = targetMessage; + activeTables = [targetFolder activeMessageTables]; + max = [activeTables count]; + for (count = 0; count < max; count++) + [[activeTables objectAtIndex: count] restrictedChildKeys]; + + notif_parameters = talloc_zero(NULL, struct mapistore_object_notification_parameters); + notif_parameters->object_id = [targetFolder objectId]; + notif_parameters->tag_count = 5; + notif_parameters->tags = talloc_array (notif_parameters, enum MAPITAGS, 5); + notif_parameters->tags[0] = PR_CONTENT_COUNT; + notif_parameters->tags[1] = PR_DELETED_COUNT_TOTAL; + notif_parameters->tags[2] = PR_MESSAGE_SIZE; + notif_parameters->tags[3] = PR_NORMAL_MESSAGE_SIZE; + notif_parameters->tags[4] = PR_RECIPIENT_ON_NORMAL_MSG_COUNT; + notif_parameters->new_message_count = true; + notif_parameters->message_count = [[targetFolder messageKeys] count] + 1; + connInfo = [[self context] connectionInfo]; + mapistore_push_notification (connInfo->mstore_ctx, + MAPISTORE_FOLDER, + MAPISTORE_OBJECT_MODIFIED, + notif_parameters); + talloc_free(notif_parameters); + + // table notification + for (count = 0; count < max; count++) + [[activeTables objectAtIndex: count] + notifyChangesForChild: message]; + + // We cleanup cache of our source and destination folders [self cleanupCaches]; [targetFolder cleanupCaches]; rc = MAPISTORE_SUCCESS; diff --git a/SoObjects/Mailer/SOGoMailBaseObject.m b/SoObjects/Mailer/SOGoMailBaseObject.m index 9d41bfe9c..aa324fb6f 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.m +++ b/SoObjects/Mailer/SOGoMailBaseObject.m @@ -154,8 +154,10 @@ static BOOL debugOn = YES; - (NGImap4Connection *) imap4Connection { - NSString *cacheKey; + NSString *cacheKey, *login; + SOGoCache *sogoCache; + if (!imap4) { @@ -164,8 +166,17 @@ static BOOL debugOn = YES; // the cache is shared across OpenChange users and not necessarily // flushed between requests. This could lead us to using the wrong // IMAP connection. + // + // We also have a HACK in case self's context doesn't exist, we + // use the container's one. + // + login = [[[self context] activeUser] login]; + + if (!login) + login = [[[[self container] context] activeUser] login]; + cacheKey = [NSString stringWithFormat: @"%@+%@", - [[[self context] activeUser] login], + login, [[self mailAccountFolder] nameInContainer]]; imap4 = [sogoCache imap4ConnectionForKey: cacheKey]; if (!imap4)