From fb95d84a3a4eb1c3f329a02a4496cc7528f17c2a Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Thu, 16 Oct 2014 09:35:15 -0400 Subject: [PATCH] Handle base64 encoded query strings, popular on Windows devices --- ActiveSync/NSString+ActiveSync.m | 46 ++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/ActiveSync/NSString+ActiveSync.m b/ActiveSync/NSString+ActiveSync.m index 1007c4bde..2d6826b7f 100644 --- a/ActiveSync/NSString+ActiveSync.m +++ b/ActiveSync/NSString+ActiveSync.m @@ -35,9 +35,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include +#include #include +static NSArray *easCommandCodes = nil; + @implementation NSString (ActiveSync) - (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType @@ -134,11 +138,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (NSString *) _valueForParameter: (NSString *) theParameter { - NSArray *components; + NSMutableArray *components; NSString *s; int i; - components = [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"]; + components = [NSMutableArray arrayWithArray: [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"]]; + + // We handle BASE64 encoded queryStrings. See http://msdn.microsoft.com/en-us/library/ee160227%28v=exchg.80%29.aspx for details. + if ([components count] == 1) + { + NSString *deviceType; + NSData *queryString; + + int cmd_code, deviceid_length, policy_length, devicetype_length; + const char* qs_bytes; + + queryString = [[components objectAtIndex: 0] dataByDecodingBase64]; + qs_bytes = (const char*)[queryString bytes]; + + if (!easCommandCodes) + { + easCommandCodes = [NSArray arrayWithObjects:@"Sync", @"SendMail", @"SmartForward", @"SmartReply", @"GetAttachment", @"na", @"na", @"na", @"na", + @"FolderSync", @"FolderCreate", @"FolderDelete", @"FolderUpdate", @"MoveItems", @"GetItemEstimate", @"MeetingResponse", + @"Search", @"Settings", @"Ping", @"ItemOperations", @"Provision", @"ResolveRecipients", @"ValidateCert", nil]; + RETAIN(easCommandCodes); + } + + // Command code, 1 byte, ie.: cmd= + cmd_code = qs_bytes[1]; + [components addObject:[NSString stringWithFormat: @"cmd=%@", [easCommandCodes objectAtIndex: cmd_code]]]; + + // Device ID length and Device ID (variable) + deviceid_length = qs_bytes[4]; + [components addObject:[NSString stringWithFormat: @"deviceId=%@", [[NSData encodeDataAsHexString:[queryString subdataWithRange:NSMakeRange(5, deviceid_length)]] uppercaseString]]]; + + // Device type length and type (variable) + policy_length = qs_bytes[5+deviceid_length]; + devicetype_length = qs_bytes[5+deviceid_length+1+policy_length]; + deviceType = [[NSString alloc] initWithData:[queryString subdataWithRange: NSMakeRange(5+deviceid_length+1+policy_length+1, devicetype_length)] + encoding:NSASCIIStringEncoding]; + AUTORELEASE(deviceType); + + [components addObject:[NSString stringWithFormat: @"deviceType=%@", deviceType]]; + } for (i = 0; i < [components count]; i++) {