diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index 67fdc7e37..7d99cebc5 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -868,105 +868,116 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { NSString *srcMessageId, *srcFolderId, *dstFolderId, *dstMessageId; SOGoMicrosoftActiveSyncFolderType srcFolderType, dstFolderType; + id aMoveOperation; + NSArray *moveOperations; + NSMutableString *s; + NSData *d; + int i; - srcMessageId = [[(id)[theDocumentElement getElementsByTagName: @"SrcMsgId"] lastObject] textValue]; - srcFolderId = [[[(id)[theDocumentElement getElementsByTagName: @"SrcFldId"] lastObject] textValue] realCollectionIdWithFolderType: &srcFolderType]; - dstFolderId = [[[(id)[theDocumentElement getElementsByTagName: @"DstFldId"] lastObject] textValue] realCollectionIdWithFolderType: &dstFolderType]; + moveOperations = (id)[theDocumentElement getElementsByTagName: @"Move"]; + + s = [NSMutableString string]; - // FIXME - if (srcFolderType == ActiveSyncMailFolder && dstFolderType == ActiveSyncMailFolder) + [s appendString: @""]; + [s appendString: @""]; + [s appendString: @""]; + + for (i = 0; i < [moveOperations count]; i++) { - NGImap4Client *client; - id currentCollection; - - NSDictionary *response; - NSString *v; + aMoveOperation = [moveOperations objectAtIndex: i]; - currentCollection = [self collectionFromId: srcFolderId type: srcFolderType]; + srcMessageId = [[(id)[aMoveOperation getElementsByTagName: @"SrcMsgId"] lastObject] textValue]; + srcFolderId = [[[(id)[aMoveOperation getElementsByTagName: @"SrcFldId"] lastObject] textValue] realCollectionIdWithFolderType: &srcFolderType]; + dstFolderId = [[[(id)[aMoveOperation getElementsByTagName: @"DstFldId"] lastObject] textValue] realCollectionIdWithFolderType: &dstFolderType]; + + [s appendString: @""]; - // [currentFolder lookupName: [NSString stringWithFormat: @"folder%@", srcFolderId] - // inContext: context - // acquire: NO]; - - client = [[currentCollection imap4Connection] client]; - [client select: srcFolderId]; - response = [client copyUid: [srcMessageId intValue] - toFolder: [NSString stringWithFormat: @"/%@", dstFolderId]]; - - // We extract the destionation message id - dstMessageId = nil; - - if ([[response objectForKey: @"result"] boolValue] - && (v = [[[response objectForKey: @"RawResponse"] objectForKey: @"ResponseResult"] objectForKey: @"flag"]) - && [v hasPrefix: @"COPYUID "]) + // FIXME - we should support moving events between calendars, for example, or + // or contacts between address books. + if (srcFolderType == ActiveSyncMailFolder && dstFolderType == ActiveSyncMailFolder) { - dstMessageId = [[v componentsSeparatedByString: @" "] lastObject]; + NGImap4Client *client; + id currentCollection; + + NSDictionary *response; + NSString *v; + + currentCollection = [self collectionFromId: srcFolderId type: srcFolderType]; + + client = [[currentCollection imap4Connection] client]; + [client select: srcFolderId]; + response = [client copyUid: [srcMessageId intValue] + toFolder: [NSString stringWithFormat: @"/%@", dstFolderId]]; + + // We extract the destionation message id + dstMessageId = nil; + + if ([[response objectForKey: @"result"] boolValue] + && (v = [[[response objectForKey: @"RawResponse"] objectForKey: @"ResponseResult"] objectForKey: @"flag"]) + && [v hasPrefix: @"COPYUID "]) + { + dstMessageId = [[v componentsSeparatedByString: @" "] lastObject]; + + // We mark the original message as deleted + response = [client storeFlags: [NSArray arrayWithObject: @"Deleted"] + forUIDs: [NSArray arrayWithObject: srcMessageId] + addOrRemove: YES]; + + if ([[response valueForKey: @"result"] boolValue]) + [(SOGoMailFolder *)currentCollection expunge]; + + } + + if (!dstMessageId) + { + // FIXME: should we return 1 or 2 here? + [s appendFormat: @"%d", 2]; + } + else + { + // + // If the MoveItems operation is initiated by an Outlook client, we save the "deviceType+dstMessageId" to use it later in order to + // modify the Sync command from "add" to "change" (see SOGoActiveSyncDispatcher+Sync.m: -processSyncGetChanges: ...). + // This is to avoid Outlook creating dupes when moving messages across folfers. + // + if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"]) + { + NSString *key; + + // The key must be pretty verbose. We use the +++ + key = [NSString stringWithFormat: @"%@+%@+%@+%@", + [[context activeUser] login], + [context objectForKey: @"DeviceType"], + dstFolderId, + dstMessageId]; + + + [[SOGoCache sharedCache] setValue: @"MovedItem" + forKey: key]; + } + + // Everything is alright, lets return the proper response. "Status == 3" means success. + [s appendFormat: @"%@", srcMessageId]; + [s appendFormat: @"%@", dstMessageId]; + [s appendFormat: @"%d", 3]; + } - // We mark the original message as deleted - response = [client storeFlags: [NSArray arrayWithObject: @"Deleted"] - forUIDs: [NSArray arrayWithObject: srcMessageId] - addOrRemove: YES]; - - if ([[response valueForKey: @"result"] boolValue]) - [(SOGoMailFolder *)currentCollection expunge]; - - } - - if (!dstMessageId) - { - [theResponse setStatus: 500]; - [theResponse appendContentString: @"Unable to move message"]; } else { - NSMutableString *s; - NSData *d; - - // - // If the MoveItems operation is initiated by an Outlook client, we save the "deviceType+dstMessageId" to use it later in order to - // modify the Sync command from "add" to "change" (see SOGoActiveSyncDispatcher+Sync.m: -processSyncGetChanges: ...). - // This is to avoid Outlook creating dupes when moving messages across folfers. - // - if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"]) - { - NSString *key; - - // The key must be pretty verbose. We use the +++ - key = [NSString stringWithFormat: @"%@+%@+%@+%@", - [[context activeUser] login], - [context objectForKey: @"DeviceType"], - dstFolderId, - dstMessageId]; - - - [[SOGoCache sharedCache] setValue: @"MovedItem" - forKey: key]; - } - - - // Everything is alright, lets return the proper response. "Status == 3" means success. - s = [NSMutableString string]; - - [s appendString: @""]; - [s appendString: @""]; - [s appendString: @""]; - [s appendString: @""]; - [s appendFormat: @"%@", srcMessageId]; - [s appendFormat: @"%@", dstMessageId]; - [s appendFormat: @"%d", 3]; - [s appendString: @""]; - [s appendString: @""]; - - d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; - - [theResponse setContent: d]; + // Non-mail move operations - unsupported for now. + [s appendFormat: @"%d", 1]; } + + [s appendString: @""]; } - else - { - [theResponse setStatus: 500]; - [theResponse appendContentString: @"Unsupported move operation"]; - } + + + [s appendString: @""]; + + d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; + + [theResponse setContent: d]; } // diff --git a/NEWS b/NEWS index 9dc0f70a9..e03dcf948 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ Bug fixes - fixed calling unescapeHTML on null variables to avoid JavaScript exceptions in Contacts module - fixed detection of IMAP flags support on the client side (#2664) - fixed the ActiveSync issue marking all mails as read when downloading them + - fixed ActiveSync's move operations not working for multiple selections (#2691) 2.2.2 (2014-03-21) ------------------