From 2623aaa726a7e0d827c2c60d5c44974fa509a6f6 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 22 Sep 2011 15:54:47 +0000 Subject: [PATCH] Monotone-Parent: 0a9a28e3c7ef305257a698ada6ebda67b4cfa9b7 Monotone-Revision: f5575460df29b5335d935f8e6d766b8aa5efda6a Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2011-09-22T15:54:47 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 3 + OpenChange/MAPIStoreFolder.h | 8 ++ OpenChange/MAPIStoreFolder.m | 136 ++++++++++++++++++++++++++++++- OpenChange/MAPIStoreMailFolder.m | 102 ++--------------------- 4 files changed, 151 insertions(+), 98 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8dfbeb5c2..16ebe1f01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ Implemented generic version for specialized folders lacking an implementation and for copying/moving items across folders of different types. + (-postNotificationsForMoveCopyMessagesWithMIDs:andMessageURLs:andCount:fromFolder:withMIDs:wantCopy:): + new helper method that performs the whole notification magic for + message moves. * OpenChange/MAPIStoreSOGo.m (sogo_folder_move_copy_messages): adapted to last backend changes. diff --git a/OpenChange/MAPIStoreFolder.h b/OpenChange/MAPIStoreFolder.h index 844697781..a7009e127 100644 --- a/OpenChange/MAPIStoreFolder.h +++ b/OpenChange/MAPIStoreFolder.h @@ -155,6 +155,14 @@ - (NSCalendarDate *) lastMessageModificationTime; +/* subclass helpers */ +- (void) postNotificationsForMoveCopyMessagesWithMIDs: (uint64_t *) srcMids + andMessageURLs: (NSArray *) oldMessageURLs + andCount: (uint32_t) midCount + fromFolder: (MAPIStoreFolder *) sourceFolder + withMIDs: (uint64_t *) targetMids + wantCopy: (uint8_t) wantCopy; + @end #endif /* MAPISTOREFOLDER_H */ diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index 493f6d5e3..005cbf926 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -636,20 +636,148 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe { int rc = MAPISTORE_SUCCESS; NSUInteger count; + NSMutableArray *oldMessageURLs; + MAPIStoreMapping *mapping; if ([sourceFolder isKindOfClass: isa] || [self isKindOfClass: [sourceFolder class]]) [self logWithFormat: @"%s: this class could probably implement" @" a specialized/optimized version", __FUNCTION__]; + oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount]; + mapping = [[self context] mapping]; for (count = 0; rc == MAPISTORE_SUCCESS && count < midCount; count++) - rc = [self moveCopyMessagesWithMID: srcMids[count] - fromFolder: sourceFolder - withMID: targetMids[count] - wantCopy: wantCopy]; + { + [oldMessageURLs addObject: [mapping urlFromID: srcMids[count]]]; + rc = [self moveCopyMessagesWithMID: srcMids[count] + fromFolder: sourceFolder + withMID: targetMids[count] + wantCopy: wantCopy]; + } + + /* Notifications */ + if (rc == MAPISTORE_SUCCESS) + { + [self postNotificationsForMoveCopyMessagesWithMIDs: srcMids + andMessageURLs: oldMessageURLs + andCount: midCount + fromFolder: sourceFolder + withMIDs: targetMids + wantCopy: wantCopy]; + + // We cleanup cache of our source and destination folders + [self cleanupCaches]; + [sourceFolder cleanupCaches]; + } return rc; } +- (void) postNotificationsForMoveCopyMessagesWithMIDs: (uint64_t *) srcMids + andMessageURLs: (NSArray *) oldMessageURLs + andCount: (uint32_t) midCount + fromFolder: (MAPIStoreFolder *) sourceFolder + withMIDs: (uint64_t *) targetMids + wantCopy: (uint8_t) wantCopy +{ + NSArray *activeTables; + NSUInteger count, tableCount, max; + MAPIStoreMessage *message; + NSString *messageURL; + MAPIStoreMapping *mapping; + struct mapistore_object_notification_parameters *notif_parameters; + struct mapistore_connection_info *connInfo; + + // For the "source folder, we ensure the table caches are loaded so + // that old and new state can be compared + activeTables = [sourceFolder activeMessageTables]; + max = [activeTables count]; + for (count = 0; count < max; count++) + [[activeTables objectAtIndex: count] restrictedChildKeys]; + + if (!wantCopy) + { + // We notify the client. We start with the source folder. + notif_parameters = talloc_zero(NULL, struct mapistore_object_notification_parameters); + notif_parameters->object_id = [sourceFolder 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 = [[sourceFolder messageKeys] count] - midCount; + connInfo = [[self context] connectionInfo]; + mapistore_push_notification (connInfo->mstore_ctx, + MAPISTORE_FOLDER, + MAPISTORE_OBJECT_MODIFIED, + notif_parameters); + talloc_free(notif_parameters); + } + + // move/copy notification of the copied/moved message + for (count = 0; count < midCount; count++) + { + notif_parameters = talloc_zero (NULL, struct mapistore_object_notification_parameters); + notif_parameters->tag_count = 0; + notif_parameters->new_message_count = true; + notif_parameters->message_count = 0; + notif_parameters->object_id = targetMids[count]; + notif_parameters->folder_id = [self objectId]; + notif_parameters->old_object_id = srcMids[count]; + notif_parameters->old_folder_id = [sourceFolder objectId]; + + mapistore_push_notification (connInfo->mstore_ctx, + MAPISTORE_MESSAGE, + (wantCopy ? MAPISTORE_OBJECT_COPIED : MAPISTORE_OBJECT_MOVED), + notif_parameters); + talloc_free (notif_parameters); + + message = [sourceFolder lookupMessageByURL: [oldMessageURLs objectAtIndex: count]]; + // table notification + for (tableCount = 0; tableCount < max; tableCount++) + [[activeTables objectAtIndex: tableCount] + notifyChangesForChild: message]; + } + + // For the "destination folder, we ensure the table caches are loaded so + // that old and new state can be compared + activeTables = [self 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 = [self 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 = [[self messageKeys] count] + midCount; + connInfo = [[self context] connectionInfo]; + mapistore_push_notification (connInfo->mstore_ctx, + MAPISTORE_FOLDER, + MAPISTORE_OBJECT_MODIFIED, + notif_parameters); + talloc_free(notif_parameters); + + // table notification + mapping = [[self context] mapping]; + for (count = 0; count < midCount; count++) + { + messageURL = [mapping urlFromID: targetMids[count]]; + message = [self lookupMessageByURL: messageURL]; + for (tableCount = 0; tableCount < max; tableCount++) + [[activeTables objectAtIndex: tableCount] + notifyChangesForChild: message]; + } +} + - (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr andCN: (uint64_t *) cnPtr fromChangeNumber: (uint64_t) changeNum diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index ade7686f4..a4b3982e5 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -872,12 +872,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP) NSArray *destUIDs; MAPIStoreMapping *mapping; NSDictionary *result; - NSUInteger count, tableCount, max; - // uint64_t target_mid; - MAPIStoreMessage *message; - NSArray *a, *activeTables; - struct mapistore_object_notification_parameters *notif_parameters; - struct mapistore_connection_info *connInfo; + NSUInteger count; + NSArray *a; // FIXME // We only support IMAP-to-IMAP copy operations for now. @@ -956,94 +952,12 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP) [mapping registerURL: messageURL withID: targetMids[count]]; } - // For the "source folder, we ensure the table caches are loaded so - // that old and new state can be compared - activeTables = [sourceFolder activeMessageTables]; - max = [activeTables count]; - for (count = 0; count < max; count++) - [[activeTables objectAtIndex: count] restrictedChildKeys]; - - if (!wantCopy) - { - // We notify the client. We start with the source folder. - notif_parameters = talloc_zero(NULL, struct mapistore_object_notification_parameters); - notif_parameters->object_id = [sourceFolder 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 = [[sourceFolder messageKeys] count] - midCount; - connInfo = [[self context] connectionInfo]; - mapistore_push_notification (connInfo->mstore_ctx, - MAPISTORE_FOLDER, - MAPISTORE_OBJECT_MODIFIED, - notif_parameters); - talloc_free(notif_parameters); - } - - // move/copy notification of the copied/moved message - for (count = 0; count < midCount; count++) - { - notif_parameters = talloc_zero (NULL, struct mapistore_object_notification_parameters); - notif_parameters->tag_count = 0; - notif_parameters->new_message_count = true; - notif_parameters->message_count = 0; - notif_parameters->object_id = targetMids[count]; - notif_parameters->folder_id = [self objectId]; - notif_parameters->old_object_id = srcMids[count]; - notif_parameters->old_folder_id = [sourceFolder objectId]; - - mapistore_push_notification (connInfo->mstore_ctx, - MAPISTORE_MESSAGE, - (wantCopy ? MAPISTORE_OBJECT_COPIED : MAPISTORE_OBJECT_MOVED), - notif_parameters); - talloc_free (notif_parameters); - - message = [sourceFolder lookupMessageByURL: [oldMessageURLs objectAtIndex: count]]; - // table notification - for (tableCount = 0; tableCount < max; tableCount++) - [[activeTables objectAtIndex: tableCount] - notifyChangesForChild: message]; - } - - // For the "destination folder, we ensure the table caches are loaded so - // that old and new state can be compared - activeTables = [self 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 = [self 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 = [[self messageKeys] count] + midCount; - 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 < midCount; count++) - { - messageURL = [mapping urlFromID: targetMids[count]]; - message = [self lookupMessageByURL: messageURL]; - for (tableCount = 0; tableCount < max; tableCount++) - [[activeTables objectAtIndex: tableCount] - notifyChangesForChild: message]; - } + [self postNotificationsForMoveCopyMessagesWithMIDs: srcMids + andMessageURLs: oldMessageURLs + andCount: midCount + fromFolder: sourceFolder + withMIDs: targetMids + wantCopy: wantCopy]; // We cleanup cache of our source and destination folders [self cleanupCaches];