@@ -21,10 +21,11 @@ #include #import "OFDictionary.h" #import "OFDictionary_hashtable.h" #import "OFArray.h" +#import "OFCharacterSet.h" #import "OFString.h" #import "OFXMLElement.h" #import "OFData.h" #import "OFInvalidArgumentException.h" @@ -33,17 +34,23 @@ static struct { Class isa; } placeholder; +static OFCharacterSet *URLQueryPartAllowedCharacterSet = nil; + @interface OFDictionary () - (OFString *)of_JSONRepresentationWithOptions: (int)options depth: (size_t)depth; @end @interface OFDictionary_placeholder: OFDictionary @end + +@interface OFCharacterSet_URLQueryPartAllowed: OFCharacterSet ++ (OFCharacterSet *)URLQueryPartAllowedCharacterSet; +@end @implementation OFDictionary_placeholder - (instancetype)init { return (id)[[OFDictionary_hashtable alloc] init]; @@ -119,10 +126,70 @@ } - (void)dealloc { OF_DEALLOC_UNSUPPORTED +} +@end + +@implementation OFCharacterSet_URLQueryPartAllowed ++ (void)initialize +{ + if (self != [OFCharacterSet_URLQueryPartAllowed class]) + return; + + URLQueryPartAllowedCharacterSet = + [[OFCharacterSet_URLQueryPartAllowed alloc] init]; +} + ++ (OFCharacterSet *)URLQueryPartAllowedCharacterSet +{ + return URLQueryPartAllowedCharacterSet; +} + +- (instancetype)autorelease +{ + return self; +} + +- (instancetype)retain +{ + return self; +} + +- (void)release +{ +} + +- (unsigned int)retainCount +{ + return OF_RETAIN_COUNT_MAX; +} + +- (bool)characterIsMember: (of_unichar_t)character +{ + if (character < CHAR_MAX && of_ascii_isalnum(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + return true; + default: + return false; + } } @end @implementation OFDictionary + (void)initialize @@ -574,10 +641,12 @@ { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); OFEnumerator *keyEnumerator = [self keyEnumerator]; OFEnumerator *objectEnumerator = [self objectEnumerator]; + OFCharacterSet *allowed = [OFCharacterSet_URLQueryPartAllowed + URLQueryPartAllowedCharacterSet]; bool first = true; id key, object; while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) { @@ -585,14 +654,14 @@ first = false; else [ret appendString: @"&"]; [ret appendString: [[key description] - stringByURLEncodingWithAllowedCharacters: "-._~!$'()*+,;"]]; + stringByURLEncodingWithAllowedCharacters: allowed]]; [ret appendString: @"="]; [ret appendString: [[object description] - stringByURLEncodingWithAllowedCharacters: "-._~!$'()*+,;"]]; + stringByURLEncodingWithAllowedCharacters: allowed]]; } [ret makeImmutable]; objc_autoreleasePoolPop(pool);