From ccbaea69995aaf17b15e55312dd398636de9ead2 Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Tue, 2 Jun 2015 13:05:37 -0400 Subject: [PATCH] (fix) EAS's GetItemEstimate/ItemOperations now support fetching mails and empty folders --- ActiveSync/SOGoActiveSyncDispatcher.m | 193 ++++++++++++++++++++------ NEWS | 3 + 2 files changed, 154 insertions(+), 42 deletions(-) diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index 7cd0e5c53..2ed420f13 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -1084,6 +1084,8 @@ static BOOL debugOn = NO; SOGoMailAccounts *accountsFolder; SOGoUserFolder *userFolder; SOGoMailObject *mailObject; + NSArray *partKeys; + int p; NSRange r1, r2; @@ -1103,7 +1105,14 @@ static BOOL debugOn = NO; acquire: NO]; mailObject = [currentCollection lookupName: messageName inContext: context acquire: NO]; - currentBodyPart = [mailObject lookupImap4BodyPartKey: pathToPart inContext: context]; + + partKeys = [pathToPart componentsSeparatedByString: @"."]; + + currentBodyPart = [mailObject lookupImap4BodyPartKey: [partKeys objectAtIndex:0] inContext: context]; + for (p = 1; p < [partKeys count]; p++) + { + currentBodyPart = [currentBodyPart lookupImap4BodyPartKey: [partKeys objectAtIndex:p] inContext: context]; + } [theResponse setHeader: [NSString stringWithFormat: @"%@/%@", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]] forKey: @"Content-Type"]; @@ -1158,11 +1167,11 @@ static BOOL debugOn = NO; { collectionId = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"CollectionId"] lastObject] textValue]; realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType]; - + if (folderType == ActiveSyncMailFolder) - nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId]; + nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId]; else - nameInCache = collectionId; + nameInCache = collectionId; realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType]; @@ -1234,10 +1243,11 @@ static BOOL debugOn = NO; - (void) processItemOperations: (id ) theDocumentElement inResponse: (WOResponse *) theResponse { - NSString *fileReference, *realCollectionId; + NSString *fileReference, *realCollectionId, *serverId, *bodyPreferenceType, *collectionId; NSMutableString *s; NSArray *fetchRequests; id aFetch; + NSData *d; int i; SOGoMicrosoftActiveSyncFolderType folderType; @@ -1247,8 +1257,6 @@ static BOOL debugOn = NO; [s appendString: @""]; [s appendString: @""]; [s appendString: @""]; - [s appendString: @"1"]; - [s appendString: @""]; fetchRequests = (id)[theDocumentElement getElementsByTagName: @"Fetch"]; @@ -1256,17 +1264,25 @@ static BOOL debugOn = NO; { NSMutableData *bytes, *parts; NSMutableArray *partLength; - NSData *d; bytes = [NSMutableData data]; parts = [NSMutableData data]; partLength = [NSMutableArray array]; + [s appendString: @"1"]; + [s appendString: @""]; + for (i = 0; i < [fetchRequests count]; i++) { aFetch = [fetchRequests objectAtIndex: i]; fileReference = [[[(id)[aFetch getElementsByTagName: @"FileReference"] lastObject] textValue] stringByUnescapingURL]; - realCollectionId = [fileReference realCollectionIdWithFolderType: &folderType]; + collectionId = [[(id)[theDocumentElement getElementsByTagName: @"CollectionId"] lastObject] textValue]; + + // its either a itemOperation to fetch an attachment or an email + if ([fileReference length]) + realCollectionId = [fileReference realCollectionIdWithFolderType: &folderType]; + else + realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType]; if (folderType == ActiveSyncMailFolder) { @@ -1276,43 +1292,80 @@ static BOOL debugOn = NO; SOGoUserFolder *userFolder; SOGoMailObject *mailObject; - NSRange r1, r2; - - r1 = [realCollectionId rangeOfString: @"/"]; - r2 = [realCollectionId rangeOfString: @"/" options: 0 range: NSMakeRange(NSMaxRange(r1)+1, [realCollectionId length]-NSMaxRange(r1)-1)]; - - folderName = [realCollectionId substringToIndex: r1.location]; - messageName = [realCollectionId substringWithRange: NSMakeRange(NSMaxRange(r1), r2.location-r1.location-1)]; - pathToPart = [realCollectionId substringFromIndex: r2.location+1]; - - userFolder = [[context activeUser] homeFolderInContext: context]; - accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO]; - currentFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO]; - - currentCollection = [currentFolder lookupName: [NSString stringWithFormat: @"folder%@", folderName] - inContext: context - acquire: NO]; - - mailObject = [currentCollection lookupName: messageName inContext: context acquire: NO]; - currentBodyPart = [mailObject lookupImap4BodyPartKey: pathToPart inContext: context]; - - [s appendString: @""]; - [s appendString: @"1"]; - [s appendFormat: @"%@", [fileReference stringByEscapingURL]]; - [s appendString: @""]; - - [s appendFormat: @"%@/%@", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]]; - - if ([[theResponse headerForKey: @"Content-Type"] isEqualToString:@"application/vnd.ms-sync.multipart"]) + if ([fileReference length]) { - [s appendFormat: @"%d", i+1]; - [partLength addObject: [NSNumber numberWithInteger: [[currentBodyPart fetchBLOB] length]]]; - [parts appendData:[currentBodyPart fetchBLOB]]; + // fetch attachment + NSRange r1, r2; + NSArray *partKeys; + int p; + + r1 = [realCollectionId rangeOfString: @"/"]; + r2 = [realCollectionId rangeOfString: @"/" options: 0 range: NSMakeRange(NSMaxRange(r1)+1, [realCollectionId length]-NSMaxRange(r1)-1)]; + + folderName = [realCollectionId substringToIndex: r1.location]; + messageName = [realCollectionId substringWithRange: NSMakeRange(NSMaxRange(r1), r2.location-r1.location-1)]; + pathToPart = [realCollectionId substringFromIndex: r2.location+1]; + + userFolder = [[context activeUser] homeFolderInContext: context]; + accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO]; + currentFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO]; + + currentCollection = [currentFolder lookupName: [NSString stringWithFormat: @"folder%@", folderName] + inContext: context + acquire: NO]; + + mailObject = [currentCollection lookupName: messageName inContext: context acquire: NO]; + + partKeys = [pathToPart componentsSeparatedByString: @"."]; + + currentBodyPart = [mailObject lookupImap4BodyPartKey: [partKeys objectAtIndex:0] inContext: context]; + for (p = 1; p < [partKeys count]; p++) + { + currentBodyPart = [currentBodyPart lookupImap4BodyPartKey: [partKeys objectAtIndex:p] inContext: context]; + } + + [s appendString: @""]; + [s appendString: @"1"]; + [s appendFormat: @"%@", [fileReference stringByEscapingURL]]; + [s appendString: @""]; + + [s appendFormat: @"%@/%@", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]]; + + if ([[theResponse headerForKey: @"Content-Type"] isEqualToString:@"application/vnd.ms-sync.multipart"]) + { + NSData *d; + d = [currentBodyPart fetchBLOB]; + + [s appendFormat: @"%d", i+1]; + [partLength addObject: [NSNumber numberWithInteger: [d length]]]; + [parts appendData: d]; + } + else + { + NSString *a; + a = [[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context]; + + [s appendFormat: @"0-%d", [a length]-1]; + [s appendFormat: @"%@", a]; + } } else { - [s appendFormat: @"0-%d", [[[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context] length]-1]; - [s appendFormat: @"%@", [[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context]]; + // fetch mail + realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType]; + serverId = [[(id)[theDocumentElement getElementsByTagName: @"ServerId"] lastObject] textValue]; + bodyPreferenceType = [[(id)[[(id)[theDocumentElement getElementsByTagName: @"BodyPreference"] lastObject] getElementsByTagName: @"Type"] lastObject] textValue]; + [context setObject: bodyPreferenceType forKey: @"BodyPreferenceType"]; + + currentCollection = [self collectionFromId: realCollectionId type: folderType]; + + mailObject = [currentCollection lookupName: serverId inContext: context acquire: NO]; + [s appendString: @""]; + [s appendString: @"1"]; + [s appendFormat: @"%@", collectionId]; + [s appendFormat: @"%@", serverId]; + [s appendString: @""]; + [s appendString: [mailObject activeSyncRepresentationInContext: context]]; } [s appendString: @""]; @@ -1366,6 +1419,62 @@ static BOOL debugOn = NO; { [theResponse setContent: d]; } + } + else if ([theDocumentElement getElementsByTagName: @"EmptyFolderContents"]) + { + NGImap4Connection *connection; + NSEnumerator *subfolders; + NSException *error; + NSURL *currentURL; + id co; + + collectionId = [[(id)[theDocumentElement getElementsByTagName: @"CollectionId"] lastObject] textValue]; + realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType]; + realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType]; + + if (folderType == ActiveSyncMailFolder) + { + co = [self collectionFromId: realCollectionId type: folderType]; + error = [co addFlagsToAllMessages: @"deleted"]; + + if (!error) + error = [(SOGoMailFolder *)co expunge]; + + if (!error) + { + [co flushMailCaches]; + + if ([theDocumentElement getElementsByTagName: @"DeleteSubFolders"]) + { + // Delete sub-folders + connection = [co imap4Connection]; + subfolders = [[co allFolderURLs] objectEnumerator]; + + while ((currentURL = [subfolders nextObject])) + { + [[connection client] unsubscribe: [currentURL path]]; + [connection deleteMailboxAtURL: currentURL]; + } + } + + [s appendString: @"1"]; + [s appendString: @""]; + } + + if (error) + { + [s appendString: @"3"]; + [s appendString: @""]; + } + + d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; + [theResponse setContent: d]; + } + else + { + [theResponse setStatus: 500]; + return; + } } } diff --git a/NEWS b/NEWS index 62ded5385..d220b304e 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ Enhancements - improved EAS speed, especially when fetching big attachments +Bug fixes + - EAS's GetItemEstimate/ItemOperations now support fetching mails and empty folders + 2.3.0 (2015-06-01) -------------------