[Issue #243] Fixing AFQueryStringFromParametersWithEncoding to encode nested array values correctly
This commit is contained in:
parent
34b7d01af8
commit
acd6e49294
1 changed files with 82 additions and 50 deletions
|
|
@ -96,7 +96,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
||||||
static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\|~ ";
|
static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+=,:;'\"`<>()[]{}/\\|~ ";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The documentation for `CFURLCreateStringByAddingPercentEscapes` suggests that one should "pre-process" URL strings with unpredictable sequences that may already contain percent escapes. However, if the string contains an unescaped sequence with '%' appearing without an escape code (such as when representing percentages like "42%"), `stringByReplacingPercentEscapesUsingEncoding` will return `nil`. Thus, the string is only unescaped if there are no invalid percent-escaped sequences.
|
The documentation for `CFURLCreateStringByAddingPercentEscapes` suggests that one should "pre-process" URL strings with unpredictable sequences that may already contain percent escapes. However, if the string contains an unescaped sequence with '%' appearing without an escape code (such as when representing percentages like "42%"), `stringByReplacingPercentEscapesUsingEncoding` will return `nil`. Thus, the string is only unescaped if there are no invalid percent-escaped sequences.
|
||||||
|
|
@ -109,61 +109,101 @@ NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEn
|
||||||
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
|
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
extern NSDictionary * AFQueryParametersFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey);
|
#pragma mark -
|
||||||
extern NSDictionary * AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey);
|
|
||||||
extern NSDictionary * AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey);
|
|
||||||
extern NSDictionary * AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(id parameter, NSString *key);
|
|
||||||
|
|
||||||
NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding encoding) {
|
@interface AFQueryStringComponent : NSObject {
|
||||||
NSMutableArray *queryStringArray = [NSMutableArray array];
|
@private
|
||||||
|
NSString *_key;
|
||||||
[AFQueryParametersFromParametersAtBaseKeyWithEncoding(parameters, nil) enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
NSString *_value;
|
||||||
[queryStringArray addObject:[NSString stringWithFormat:@"%@=%@", AFURLEncodedStringFromStringWithEncoding([key description], encoding), AFURLEncodedStringFromStringWithEncoding([obj description], encoding)]];
|
|
||||||
}];
|
|
||||||
|
|
||||||
return [queryStringArray componentsJoinedByString:@"&"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary * AFQueryParametersFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey) {
|
@property (readwrite, nonatomic, retain) id key;
|
||||||
NSMutableDictionary *mutableParameterComponents = [NSMutableDictionary dictionary];
|
@property (readwrite, nonatomic, retain) id value;
|
||||||
|
|
||||||
|
- (id)initWithKey:(NSString *)key value:(NSString *)value;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AFQueryStringComponent
|
||||||
|
@synthesize key = _key;
|
||||||
|
@synthesize value = _value;
|
||||||
|
|
||||||
|
- (id)initWithKey:(NSString *)key value:(NSString *)value {
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.key = key;
|
||||||
|
self.value = value;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[_key release];
|
||||||
|
[_value release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)description {
|
||||||
|
return [NSString stringWithFormat:@"%@=%@", self.key, self.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
extern NSArray * AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey, NSStringEncoding stringEncoding);
|
||||||
|
extern NSArray * AFQueryStringComponentsFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey, NSStringEncoding stringEncoding);
|
||||||
|
extern NSArray * AFQueryStringComponentsFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey, NSStringEncoding stringEncoding);
|
||||||
|
|
||||||
|
NSString * AFQueryStringFromParametersWithEncoding(id parameters, NSStringEncoding stringEncoding) {
|
||||||
|
return [[AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(parameters, nil, stringEncoding) valueForKeyPath:@"description"] componentsJoinedByString:@"&"];
|
||||||
|
}
|
||||||
|
|
||||||
|
AFQueryStringComponent * AFQueryStringComponentFromKeyAndValueWithEncoding(id key, id value, NSStringEncoding stringEncoding) {
|
||||||
|
return [[[AFQueryStringComponent alloc] initWithKey:AFURLEncodedStringFromStringWithEncoding([key description], stringEncoding) value:AFURLEncodedStringFromStringWithEncoding([value description], stringEncoding)] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSArray * AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey, NSStringEncoding stringEncoding) {
|
||||||
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||||
|
|
||||||
if([parameters isKindOfClass:[NSDictionary class]]) {
|
if([parameters isKindOfClass:[NSDictionary class]]) {
|
||||||
[mutableParameterComponents addEntriesFromDictionary:AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(parameters, baseKey)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromParametersDictionaryAtBaseKeyWithEncoding(parameters, baseKey, stringEncoding)];
|
||||||
} else if([parameters isKindOfClass:[NSArray class]]) {
|
} else if([parameters isKindOfClass:[NSArray class]]) {
|
||||||
[mutableParameterComponents addEntriesFromDictionary:AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(parameters, baseKey)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromParametersArrayAtBaseKeyWithEncoding(parameters, baseKey, stringEncoding)];
|
||||||
} else {
|
} else {
|
||||||
[mutableParameterComponents addEntriesFromDictionary:AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(parameters, baseKey)];
|
[mutableQueryStringComponents addObject:AFQueryStringComponentFromKeyAndValueWithEncoding(baseKey, parameters, stringEncoding)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return mutableParameterComponents;
|
return mutableQueryStringComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary * AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey){
|
NSArray * AFQueryStringComponentsFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey, NSStringEncoding stringEncoding){
|
||||||
NSMutableDictionary *mutableParameterComponents = [NSMutableDictionary dictionary];
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||||
|
|
||||||
id key = nil;
|
[parameters enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
|
||||||
NSEnumerator *enumerator = [parameters keyEnumerator];
|
|
||||||
while ((key = [enumerator nextObject])) {
|
|
||||||
NSString *nextKey = baseKey ? [NSString stringWithFormat:@"%@[%@]", baseKey, key] : key;
|
NSString *nextKey = baseKey ? [NSString stringWithFormat:@"%@[%@]", baseKey, key] : key;
|
||||||
[mutableParameterComponents addEntriesFromDictionary:AFQueryParametersFromParametersAtBaseKeyWithEncoding([parameters valueForKey:key], nextKey)];
|
if (nextKey && value) {
|
||||||
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(value, nextKey, stringEncoding)];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
return mutableQueryStringComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mutableParameterComponents;
|
NSArray * AFQueryStringComponentsFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey, NSStringEncoding stringEncoding) {
|
||||||
}
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||||
|
|
||||||
NSDictionary * AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey) {
|
[parameters enumerateObjectsUsingBlock:^(id value, NSUInteger idx, BOOL *stop) {
|
||||||
NSMutableDictionary *mutableParameterComponents = [NSMutableDictionary dictionary];
|
|
||||||
|
|
||||||
for (id value in parameters) {
|
|
||||||
NSString *nextKey = [NSString stringWithFormat:@"%@[]", baseKey];
|
NSString *nextKey = [NSString stringWithFormat:@"%@[]", baseKey];
|
||||||
[mutableParameterComponents addEntriesFromDictionary:AFQueryParametersFromParametersAtBaseKeyWithEncoding(value, nextKey)];
|
if (nextKey && value) {
|
||||||
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(value, nextKey, stringEncoding)];
|
||||||
}
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
return mutableParameterComponents;
|
return mutableQueryStringComponents;
|
||||||
}
|
|
||||||
|
|
||||||
NSDictionary * AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(id parameter, NSString *key) {
|
|
||||||
return [NSDictionary dictionaryWithObject:parameter forKey:key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString * AFJSONStringFromParameters(NSDictionary *parameters) {
|
static NSString * AFJSONStringFromParameters(NSDictionary *parameters) {
|
||||||
|
|
@ -398,18 +438,10 @@ static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCN
|
||||||
NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil];
|
NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil];
|
||||||
__block AFMultipartFormData *formData = [[AFMultipartFormData alloc] initWithStringEncoding:self.stringEncoding];
|
__block AFMultipartFormData *formData = [[AFMultipartFormData alloc] initWithStringEncoding:self.stringEncoding];
|
||||||
|
|
||||||
[AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(parameters, nil) enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
|
for (AFQueryStringComponent *component in AFQueryStringComponentsFromParametersAtBaseKeyWithEncoding(parameters, nil, self.stringEncoding)) {
|
||||||
NSData *data = nil;
|
[formData appendPartWithFormData:[component.value dataUsingEncoding:self.stringEncoding] name:component.key];
|
||||||
|
|
||||||
if ([value isKindOfClass:[NSData class]]) {
|
|
||||||
data = value;
|
|
||||||
} else {
|
|
||||||
data = [[value description] dataUsingEncoding:self.stringEncoding];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[formData appendPartWithFormData:data name:[key description]];
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
block(formData);
|
block(formData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue