Skip to content

Commit

Permalink
Use a more robust query string -> NSDictionary class that deals with …
Browse files Browse the repository at this point in the history
…escaping properly (thanks @protocool).
  • Loading branch information
lukeredpath committed May 14, 2010
1 parent 0cfb96b commit 14daa62
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 7 deletions.
16 changes: 16 additions & 0 deletions LROAuth2Client.xcodeproj/project.pbxproj
Expand Up @@ -32,6 +32,10 @@
A3F8C125119DEFD50035081C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C124119DEFD50035081C /* SystemConfiguration.framework */; }; A3F8C125119DEFD50035081C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C124119DEFD50035081C /* SystemConfiguration.framework */; };
A3F8C127119DEFDE0035081C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C126119DEFDE0035081C /* UIKit.framework */; }; A3F8C127119DEFDE0035081C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C126119DEFDE0035081C /* UIKit.framework */; };
A3F8C132119DF00D0035081C /* NSURL+QueryInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */; }; A3F8C132119DF00D0035081C /* NSURL+QueryInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */; };
A3F8C24D119DF7420035081C /* NSDictionary+PonyExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24B119DF7420035081C /* NSDictionary+PonyExtensions.m */; };
A3F8C24E119DF7420035081C /* NSString+PonyExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24C119DF7420035081C /* NSString+PonyExtensions.m */; };
A3F8C255119DF7790035081C /* NSDictionary+PonyExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8C254119DF7790035081C /* NSDictionary+PonyExtensions.h */; };
A3F8C259119DF79D0035081C /* NSString+PonyExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8C258119DF79D0035081C /* NSString+PonyExtensions.h */; };
AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; }; AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */


Expand Down Expand Up @@ -82,6 +86,10 @@
A3F8C126119DEFDE0035081C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; A3F8C126119DEFDE0035081C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+QueryInspector.h"; sourceTree = "<group>"; }; A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+QueryInspector.h"; sourceTree = "<group>"; };
A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+QueryInspector.m"; sourceTree = "<group>"; }; A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+QueryInspector.m"; sourceTree = "<group>"; };
A3F8C24B119DF7420035081C /* NSDictionary+PonyExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+PonyExtensions.m"; sourceTree = "<group>"; };
A3F8C24C119DF7420035081C /* NSString+PonyExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+PonyExtensions.m"; sourceTree = "<group>"; };
A3F8C254119DF7790035081C /* NSDictionary+PonyExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+PonyExtensions.h"; sourceTree = "<group>"; };
A3F8C258119DF79D0035081C /* NSString+PonyExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+PonyExtensions.h"; sourceTree = "<group>"; };
AA747D9E0F9514B9006C5449 /* LROAuth2Client_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2Client_Prefix.pch; sourceTree = "<group>"; }; AA747D9E0F9514B9006C5449 /* LROAuth2Client_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2Client_Prefix.pch; sourceTree = "<group>"; };
AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D2AAC07E0554694100DB518D /* libLROAuth2Client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLROAuth2Client.a; sourceTree = BUILT_PRODUCTS_DIR; }; D2AAC07E0554694100DB518D /* libLROAuth2Client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLROAuth2Client.a; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -253,6 +261,10 @@
A3F8C12D119DEFF80035081C /* Categories */ = { A3F8C12D119DEFF80035081C /* Categories */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A3F8C254119DF7790035081C /* NSDictionary+PonyExtensions.h */,
A3F8C24B119DF7420035081C /* NSDictionary+PonyExtensions.m */,
A3F8C258119DF79D0035081C /* NSString+PonyExtensions.h */,
A3F8C24C119DF7420035081C /* NSString+PonyExtensions.m */,
A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */, A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */,
A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */, A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */,
); );
Expand All @@ -270,6 +282,8 @@
A3F8BFBF119DEE450035081C /* LROAuth2Client.h in Headers */, A3F8BFBF119DEE450035081C /* LROAuth2Client.h in Headers */,
A3F8BFC1119DEE450035081C /* LROAuth2ClientDelegate.h in Headers */, A3F8BFC1119DEE450035081C /* LROAuth2ClientDelegate.h in Headers */,
A3F8BFC2119DEE450035081C /* LROAuth2AccessToken.h in Headers */, A3F8BFC2119DEE450035081C /* LROAuth2AccessToken.h in Headers */,
A3F8C255119DF7790035081C /* NSDictionary+PonyExtensions.h in Headers */,
A3F8C259119DF79D0035081C /* NSString+PonyExtensions.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
Expand Down Expand Up @@ -336,6 +350,8 @@
A3F8C11C119DEF930035081C /* CJSONSerializer.m in Sources */, A3F8C11C119DEF930035081C /* CJSONSerializer.m in Sources */,
A3F8C11E119DEF930035081C /* CSerializedJSONData.m in Sources */, A3F8C11E119DEF930035081C /* CSerializedJSONData.m in Sources */,
A3F8C132119DF00D0035081C /* NSURL+QueryInspector.m in Sources */, A3F8C132119DF00D0035081C /* NSURL+QueryInspector.m in Sources */,
A3F8C24D119DF7420035081C /* NSDictionary+PonyExtensions.m in Sources */,
A3F8C24E119DF7420035081C /* NSString+PonyExtensions.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
Expand Down
4 changes: 4 additions & 0 deletions NSDictionary+PonyExtensions.h
@@ -0,0 +1,4 @@
@interface NSDictionary (PonyExtensions)
+ (NSDictionary *)dictionaryWithFormEncodedString:(NSString *)encodedString
- (NSString *)stringWithFormEncodedComponents;
@end
49 changes: 49 additions & 0 deletions NSDictionary+PonyExtensions.m
@@ -0,0 +1,49 @@
@implementation NSDictionary (PonyExtensions)

+ (NSDictionary *)dictionaryWithFormEncodedString:(NSString *)encodedString
{
NSMutableDictionary* result = [NSMutableDictionary dictionary];
NSArray* pairs = [encodedString componentsSeparatedByString:@"&"];

for (NSString* kvp in pairs)
{
if ([kvp length] == 0)
continue;

NSRange pos = [kvp rangeOfString:@"="];
NSString *key;
NSString *val;

if (pos.location == NSNotFound)
{
key = [kvp stringByUnescapingFromURLQuery];
val = @"";
}
else
{
key = [[kvp substringToIndex:pos.location] stringByUnescapingFromURLQuery];
val = [[kvp substringFromIndex:pos.location + pos.length] stringByUnescapingFromURLQuery];
}

if (!key || !val)
continue; // I'm sure this will bite my arse one day

[result setObject:val forKey:key];
}
return result;
}

- (NSString *)stringWithFormEncodedComponents
{
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]];
for (NSString* key in self)
{
[arguments addObject:[NSString stringWithFormat:@"%@=%@",
[key stringByEscapingForURLQuery],
[[[self objectForKey:key] description] stringByEscapingForURLQuery]]];
}

return [arguments componentsJoinedByString:@"&"];
}

@end
4 changes: 4 additions & 0 deletions NSString+PonyExtensions.h
@@ -0,0 +1,4 @@
@interface NSString (PonyExtensions)
- (NSString*)stringByEscapingForURLQuery;
- (NSString*)stringByUnescapingFromURLQuery;
@end
31 changes: 31 additions & 0 deletions NSString+PonyExtensions.m
@@ -0,0 +1,31 @@
#import "NSString+PonyExtensions.h"

@implementation NSString (PonyExtensions)

- (NSString*)stringByEscapingForURLQuery
{
NSString *result = self;

CFStringRef originalAsCFString = (CFStringRef) self;
CFStringRef leaveAlone = CFSTR(" ");
CFStringRef toEscape = CFSTR("\n\r?[]()$,!'*;:@&=#%+/");

CFStringRef escapedStr;
escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalAsCFString, leaveAlone, toEscape, kCFStringEncodingUTF8);

if (escapedStr) {
NSMutableString *mutable = [NSMutableString stringWithString:(NSString *)escapedStr];
CFRelease(escapedStr);

[mutable replaceOccurrencesOfString:@" " withString:@"+" options:0 range:NSMakeRange(0, [mutable length])];
result = mutable;
}
return result;
}

- (NSString*)stringByUnescapingFromURLQuery
{
return [[self stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"+" withString:@" "];
}

@end
9 changes: 2 additions & 7 deletions NSURL+QueryInspector.m
Expand Up @@ -7,18 +7,13 @@
// //


#import "NSURL+QueryInspector.h" #import "NSURL+QueryInspector.h"

#import "NSDictionary+PonyExtensions.m"


@implementation NSURL (QueryInspector) @implementation NSURL (QueryInspector)


- (NSDictionary *)queryDictionary; - (NSDictionary *)queryDictionary;
{ {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; return [NSDictionary dictionaryWithFormEncodedString:self.query];
for (NSString *keyPair in [self.query componentsSeparatedByString:@"&"]) {
NSArray *components = [keyPair componentsSeparatedByString:@"="];
[dictionary setValue:[components objectAtIndex:1] forKey:[components objectAtIndex:0]];
}
return [[dictionary copy] autorelease];
} }


@end @end

0 comments on commit 14daa62

Please sign in to comment.