(fix) EAS's GetItemEstimate/ItemOperations now support fetching mails and empty folders
parent
75206f1f2c
commit
ccbaea6999
|
@ -1084,6 +1084,8 @@ static BOOL debugOn = NO;
|
||||||
SOGoMailAccounts *accountsFolder;
|
SOGoMailAccounts *accountsFolder;
|
||||||
SOGoUserFolder *userFolder;
|
SOGoUserFolder *userFolder;
|
||||||
SOGoMailObject *mailObject;
|
SOGoMailObject *mailObject;
|
||||||
|
NSArray *partKeys;
|
||||||
|
int p;
|
||||||
|
|
||||||
NSRange r1, r2;
|
NSRange r1, r2;
|
||||||
|
|
||||||
|
@ -1103,7 +1105,14 @@ static BOOL debugOn = NO;
|
||||||
acquire: NO];
|
acquire: NO];
|
||||||
|
|
||||||
mailObject = [currentCollection lookupName: messageName inContext: context 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"]]
|
[theResponse setHeader: [NSString stringWithFormat: @"%@/%@", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]]
|
||||||
forKey: @"Content-Type"];
|
forKey: @"Content-Type"];
|
||||||
|
@ -1158,11 +1167,11 @@ static BOOL debugOn = NO;
|
||||||
{
|
{
|
||||||
collectionId = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"CollectionId"] lastObject] textValue];
|
collectionId = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"CollectionId"] lastObject] textValue];
|
||||||
realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType];
|
realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType];
|
||||||
|
|
||||||
if (folderType == ActiveSyncMailFolder)
|
if (folderType == ActiveSyncMailFolder)
|
||||||
nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId];
|
nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId];
|
||||||
else
|
else
|
||||||
nameInCache = collectionId;
|
nameInCache = collectionId;
|
||||||
|
|
||||||
realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType];
|
realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType];
|
||||||
|
|
||||||
|
@ -1234,10 +1243,11 @@ static BOOL debugOn = NO;
|
||||||
- (void) processItemOperations: (id <DOMElement>) theDocumentElement
|
- (void) processItemOperations: (id <DOMElement>) theDocumentElement
|
||||||
inResponse: (WOResponse *) theResponse
|
inResponse: (WOResponse *) theResponse
|
||||||
{
|
{
|
||||||
NSString *fileReference, *realCollectionId;
|
NSString *fileReference, *realCollectionId, *serverId, *bodyPreferenceType, *collectionId;
|
||||||
NSMutableString *s;
|
NSMutableString *s;
|
||||||
NSArray *fetchRequests;
|
NSArray *fetchRequests;
|
||||||
id aFetch;
|
id aFetch;
|
||||||
|
NSData *d;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
SOGoMicrosoftActiveSyncFolderType folderType;
|
SOGoMicrosoftActiveSyncFolderType folderType;
|
||||||
|
@ -1247,8 +1257,6 @@ static BOOL debugOn = NO;
|
||||||
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
|
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
|
||||||
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
|
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
|
||||||
[s appendString: @"<ItemOperations xmlns=\"ItemOperations:\">"];
|
[s appendString: @"<ItemOperations xmlns=\"ItemOperations:\">"];
|
||||||
[s appendString: @"<Status>1</Status>"];
|
|
||||||
[s appendString: @"<Response>"];
|
|
||||||
|
|
||||||
fetchRequests = (id)[theDocumentElement getElementsByTagName: @"Fetch"];
|
fetchRequests = (id)[theDocumentElement getElementsByTagName: @"Fetch"];
|
||||||
|
|
||||||
|
@ -1256,17 +1264,25 @@ static BOOL debugOn = NO;
|
||||||
{
|
{
|
||||||
NSMutableData *bytes, *parts;
|
NSMutableData *bytes, *parts;
|
||||||
NSMutableArray *partLength;
|
NSMutableArray *partLength;
|
||||||
NSData *d;
|
|
||||||
|
|
||||||
bytes = [NSMutableData data];
|
bytes = [NSMutableData data];
|
||||||
parts = [NSMutableData data];
|
parts = [NSMutableData data];
|
||||||
partLength = [NSMutableArray array];
|
partLength = [NSMutableArray array];
|
||||||
|
|
||||||
|
[s appendString: @"<Status>1</Status>"];
|
||||||
|
[s appendString: @"<Response>"];
|
||||||
|
|
||||||
for (i = 0; i < [fetchRequests count]; i++)
|
for (i = 0; i < [fetchRequests count]; i++)
|
||||||
{
|
{
|
||||||
aFetch = [fetchRequests objectAtIndex: i];
|
aFetch = [fetchRequests objectAtIndex: i];
|
||||||
fileReference = [[[(id)[aFetch getElementsByTagName: @"FileReference"] lastObject] textValue] stringByUnescapingURL];
|
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)
|
if (folderType == ActiveSyncMailFolder)
|
||||||
{
|
{
|
||||||
|
@ -1276,43 +1292,80 @@ static BOOL debugOn = NO;
|
||||||
SOGoUserFolder *userFolder;
|
SOGoUserFolder *userFolder;
|
||||||
SOGoMailObject *mailObject;
|
SOGoMailObject *mailObject;
|
||||||
|
|
||||||
NSRange r1, r2;
|
if ([fileReference length])
|
||||||
|
|
||||||
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: @"<Fetch>"];
|
|
||||||
[s appendString: @"<Status>1</Status>"];
|
|
||||||
[s appendFormat: @"<FileReference xmlns=\"AirSyncBase:\">%@</FileReference>", [fileReference stringByEscapingURL]];
|
|
||||||
[s appendString: @"<Properties>"];
|
|
||||||
|
|
||||||
[s appendFormat: @"<ContentType xmlns=\"AirSyncBase:\">%@/%@</ContentType>", [[currentBodyPart partInfo] objectForKey: @"type"], [[currentBodyPart partInfo] objectForKey: @"subtype"]];
|
|
||||||
|
|
||||||
if ([[theResponse headerForKey: @"Content-Type"] isEqualToString:@"application/vnd.ms-sync.multipart"])
|
|
||||||
{
|
{
|
||||||
[s appendFormat: @"<Part>%d</Part>", i+1];
|
// fetch attachment
|
||||||
[partLength addObject: [NSNumber numberWithInteger: [[currentBodyPart fetchBLOB] length]]];
|
NSRange r1, r2;
|
||||||
[parts appendData:[currentBodyPart fetchBLOB]];
|
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: @"<Fetch>"];
|
||||||
|
[s appendString: @"<Status>1</Status>"];
|
||||||
|
[s appendFormat: @"<FileReference xmlns=\"AirSyncBase:\">%@</FileReference>", [fileReference stringByEscapingURL]];
|
||||||
|
[s appendString: @"<Properties>"];
|
||||||
|
|
||||||
|
[s appendFormat: @"<ContentType xmlns=\"AirSyncBase:\">%@/%@</ContentType>", [[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: @"<Part>%d</Part>", i+1];
|
||||||
|
[partLength addObject: [NSNumber numberWithInteger: [d length]]];
|
||||||
|
[parts appendData: d];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString *a;
|
||||||
|
a = [[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context];
|
||||||
|
|
||||||
|
[s appendFormat: @"<Range>0-%d</Range>", [a length]-1];
|
||||||
|
[s appendFormat: @"<Data>%@</Data>", a];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[s appendFormat: @"<Range>0-%d</Range>", [[[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context] length]-1];
|
// fetch mail
|
||||||
[s appendFormat: @"<Data>%@</Data>", [[currentBodyPart fetchBLOB] activeSyncRepresentationInContext: context]];
|
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: @"<Fetch>"];
|
||||||
|
[s appendString: @"<Status>1</Status>"];
|
||||||
|
[s appendFormat: @"<CollectionId xmlns=\"AirSyncBase:\">%@</CollectionId>", collectionId];
|
||||||
|
[s appendFormat: @"<ServerId xmlns=\"AirSyncBase:\">%@</ServerId>", serverId];
|
||||||
|
[s appendString: @"<Properties>"];
|
||||||
|
[s appendString: [mailObject activeSyncRepresentationInContext: context]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[s appendString: @"</Properties>"];
|
[s appendString: @"</Properties>"];
|
||||||
|
@ -1366,6 +1419,62 @@ static BOOL debugOn = NO;
|
||||||
{
|
{
|
||||||
[theResponse setContent: d];
|
[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: @"<Status>1</Status>"];
|
||||||
|
[s appendString: @"</ItemOperations>"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
[s appendString: @"<Status>3</Status>"];
|
||||||
|
[s appendString: @"</ItemOperations>"];
|
||||||
|
}
|
||||||
|
|
||||||
|
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
|
||||||
|
[theResponse setContent: d];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[theResponse setStatus: 500];
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
NEWS
3
NEWS
|
@ -4,6 +4,9 @@
|
||||||
Enhancements
|
Enhancements
|
||||||
- improved EAS speed, especially when fetching big attachments
|
- 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)
|
2.3.0 (2015-06-01)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue