|
@@ -24,7 +24,6 @@
|
|
|
|
|
|
#import "AFHTTPClient.h"
|
|
|
#import "AFHTTPRequestOperation.h"
|
|
|
-#import "AFJSONUtilities.h"
|
|
|
|
|
|
#import <Availability.h>
|
|
|
|
|
@@ -43,10 +42,13 @@
|
|
|
#import <netdb.h>
|
|
|
#endif
|
|
|
|
|
|
+// Workaround for management of dispatch_retain() / dispatch_release() by ARC with iOS 6 / Mac OS X 10.8
|
|
|
+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && (!defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0)) || \
|
|
|
+ (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && (!defined(__MAC_10_8) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8))
|
|
|
+#define AF_DISPATCH_RETAIN_RELEASE 1
|
|
|
+#endif
|
|
|
|
|
|
-NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
|
|
-
|
|
|
-@interface AFStreamingMultipartFormData : NSObject <AFStreamingMultipartFormData>
|
|
|
+@interface AFStreamingMultipartFormData : NSObject <AFMultipartFormData>
|
|
|
|
|
|
- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
|
|
stringEncoding:(NSStringEncoding)encoding;
|
|
@@ -58,6 +60,9 @@ NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire
|
|
|
#pragma mark -
|
|
|
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
|
+NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
|
|
+NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
|
|
|
+
|
|
|
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef;
|
|
|
typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
|
|
|
#else
|
|
@@ -92,114 +97,92 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
|
|
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
|
|
|
}
|
|
|
|
|
|
- return [[[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding] autorelease];
|
|
|
+ return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
|
|
|
}
|
|
|
|
|
|
-NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
|
|
- static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+=,:;'\"`<>()[]{}/\\|~ ";
|
|
|
+static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
|
|
+ // Escape characters that are legal in URIs, but have unintentional semantic significance when used in a query string parameter
|
|
|
+ static NSString * const kAFLegalCharactersToBeEscaped = @":/.?&=;+!@$()~";
|
|
|
|
|
|
- return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
|
|
|
+ return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-@interface AFQueryStringComponent : NSObject {
|
|
|
-@private
|
|
|
- NSString *_key;
|
|
|
- NSString *_value;
|
|
|
-}
|
|
|
-
|
|
|
-@property (readwrite, nonatomic, retain) id key;
|
|
|
+@interface AFQueryStringPair : NSObject
|
|
|
+@property (readwrite, nonatomic, retain) id field;
|
|
|
@property (readwrite, nonatomic, retain) id value;
|
|
|
|
|
|
-- (id)initWithKey:(id)key value:(id)value;
|
|
|
+- (id)initWithField:(id)field value:(id)value;
|
|
|
+
|
|
|
- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding;
|
|
|
|
|
|
@end
|
|
|
|
|
|
-@implementation AFQueryStringComponent
|
|
|
-@synthesize key = _key;
|
|
|
+@implementation AFQueryStringPair
|
|
|
+@synthesize field = _field;
|
|
|
@synthesize value = _value;
|
|
|
|
|
|
-- (id)initWithKey:(id)key value:(id)value {
|
|
|
+- (id)initWithField:(id)field value:(id)value {
|
|
|
self = [super init];
|
|
|
if (!self) {
|
|
|
return nil;
|
|
|
}
|
|
|
-
|
|
|
- self.key = key;
|
|
|
+
|
|
|
+ self.field = field;
|
|
|
self.value = value;
|
|
|
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
-- (void)dealloc {
|
|
|
- [_key release];
|
|
|
- [_value release];
|
|
|
- [super dealloc];
|
|
|
-}
|
|
|
-
|
|
|
- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding {
|
|
|
- return [NSString stringWithFormat:@"%@=%@", self.key, AFURLEncodedStringFromStringWithEncoding([self.value description], stringEncoding)];
|
|
|
+ return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(self.field, stringEncoding), AFPercentEscapedQueryStringPairMemberFromStringWithEncoding([self.value description], stringEncoding)];
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndValue(NSString *key, id value);
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndDictionaryValue(NSString *key, NSDictionary *value);
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndArrayValue(NSString *key, NSArray *value);
|
|
|
+extern NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
|
|
|
+extern NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value);
|
|
|
|
|
|
NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) {
|
|
|
- NSMutableArray *mutableComponents = [NSMutableArray array];
|
|
|
- for (AFQueryStringComponent *component in AFQueryStringComponentsFromKeyAndValue(nil, parameters)) {
|
|
|
- [mutableComponents addObject:[component URLEncodedStringValueWithEncoding:stringEncoding]];
|
|
|
+ NSMutableArray *mutablePairs = [NSMutableArray array];
|
|
|
+ for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
|
|
|
+ [mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]];
|
|
|
}
|
|
|
|
|
|
- return [mutableComponents componentsJoinedByString:@"&"];
|
|
|
+ return [mutablePairs componentsJoinedByString:@"&"];
|
|
|
+}
|
|
|
+
|
|
|
+NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
|
|
|
+ return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
|
|
|
}
|
|
|
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndValue(NSString *key, id value) {
|
|
|
+NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
|
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
|
|
|
if([value isKindOfClass:[NSDictionary class]]) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndDictionaryValue(key, value)];
|
|
|
+ [value enumerateKeysAndObjectsUsingBlock:^(id nestedKey, id nestedValue, BOOL *stop) {
|
|
|
+ [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
|
|
+ }];
|
|
|
} else if([value isKindOfClass:[NSArray class]]) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndArrayValue(key, value)];
|
|
|
+ [value enumerateObjectsUsingBlock:^(id nestedValue, NSUInteger idx, BOOL *stop) {
|
|
|
+ [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
|
|
+ }];
|
|
|
} else {
|
|
|
- [mutableQueryStringComponents addObject:[[[AFQueryStringComponent alloc] initWithKey:key value:value] autorelease]];
|
|
|
+ [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
|
|
}
|
|
|
|
|
|
return mutableQueryStringComponents;
|
|
|
}
|
|
|
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndDictionaryValue(NSString *key, NSDictionary *value){
|
|
|
- NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
-
|
|
|
- [value enumerateKeysAndObjectsUsingBlock:^(id nestedKey, id nestedValue, BOOL *stop) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
|
|
- }];
|
|
|
-
|
|
|
- return mutableQueryStringComponents;
|
|
|
-}
|
|
|
-
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndArrayValue(NSString *key, NSArray *value) {
|
|
|
- NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
-
|
|
|
- [value enumerateObjectsUsingBlock:^(id nestedValue, NSUInteger idx, BOOL *stop) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
|
|
- }];
|
|
|
-
|
|
|
- return mutableQueryStringComponents;
|
|
|
-}
|
|
|
-
|
|
|
static NSString * AFJSONStringFromParameters(NSDictionary *parameters) {
|
|
|
NSError *error = nil;
|
|
|
- NSData *JSONData = AFJSONEncode(parameters, &error);
|
|
|
+ NSData *JSONData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error];;
|
|
|
|
|
|
if (!error) {
|
|
|
- return [[[NSString alloc] initWithData:JSONData encoding:NSUTF8StringEncoding] autorelease];
|
|
|
+ return [[NSString alloc] initWithData:JSONData encoding:NSUTF8StringEncoding];
|
|
|
} else {
|
|
|
return nil;
|
|
|
}
|
|
@@ -211,17 +194,17 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
|
|
|
NSData *propertyListData = [NSPropertyListSerialization dataWithPropertyList:parameters format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
|
|
|
if (!error) {
|
|
|
- propertyListString = [[[NSString alloc] initWithData:propertyListData encoding:NSUTF8StringEncoding] autorelease];
|
|
|
+ propertyListString = [[NSString alloc] initWithData:propertyListData encoding:NSUTF8StringEncoding] ;
|
|
|
}
|
|
|
|
|
|
return propertyListString;
|
|
|
}
|
|
|
|
|
|
@interface AFHTTPClient ()
|
|
|
-@property (readwrite, nonatomic, retain) NSURL *baseURL;
|
|
|
-@property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames;
|
|
|
-@property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders;
|
|
|
-@property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
|
|
|
+@property (readwrite, nonatomic) NSURL *baseURL;
|
|
|
+@property (readwrite, nonatomic) NSMutableArray *registeredHTTPOperationClassNames;
|
|
|
+@property (readwrite, nonatomic) NSMutableDictionary *defaultHeaders;
|
|
|
+@property (readwrite, nonatomic) NSOperationQueue *operationQueue;
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
|
@property (readwrite, nonatomic, assign) AFNetworkReachabilityRef networkReachability;
|
|
|
@property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
|
@@ -248,7 +231,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
#endif
|
|
|
|
|
|
+ (AFHTTPClient *)clientWithBaseURL:(NSURL *)url {
|
|
|
- return [[[self alloc] initWithBaseURL:url] autorelease];
|
|
|
+ return [[self alloc] initWithBaseURL:url];
|
|
|
}
|
|
|
|
|
|
- (id)initWithBaseURL:(NSURL *)url {
|
|
@@ -270,19 +253,16 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
self.registeredHTTPOperationClassNames = [NSMutableArray array];
|
|
|
|
|
|
self.defaultHeaders = [NSMutableDictionary dictionary];
|
|
|
-
|
|
|
- // Accept-Encoding HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
|
|
|
- [self setDefaultHeader:@"Accept-Encoding" value:@"gzip"];
|
|
|
|
|
|
- // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
|
|
- NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
|
|
- [self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
|
|
+ // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
|
|
+ NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
|
|
+ [self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
|
|
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
|
|
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
|
|
|
- [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@, %@ %@, %@, Scale/%f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], @"unknown", [[UIDevice currentDevice] systemName], [[UIDevice currentDevice] systemVersion], [[UIDevice currentDevice] model], ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0)]];
|
|
|
+ [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], (__bridge id)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), kCFBundleVersionKey) ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0f)]];
|
|
|
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
|
|
|
- [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], @"unknown"]];
|
|
|
+ [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]];
|
|
|
#endif
|
|
|
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
@@ -290,7 +270,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
[self startMonitoringNetworkReachability];
|
|
|
#endif
|
|
|
|
|
|
- self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
|
|
|
+ self.operationQueue = [[NSOperationQueue alloc] init];
|
|
|
[self.operationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
|
|
|
|
|
|
return self;
|
|
@@ -299,15 +279,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
- (void)dealloc {
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
|
[self stopMonitoringNetworkReachability];
|
|
|
- [_networkReachabilityStatusBlock release];
|
|
|
#endif
|
|
|
-
|
|
|
- [_baseURL release];
|
|
|
- [_registeredHTTPOperationClassNames release];
|
|
|
- [_defaultHeaders release];
|
|
|
- [_operationQueue release];
|
|
|
-
|
|
|
- [super dealloc];
|
|
|
}
|
|
|
|
|
|
- (NSString *)description {
|
|
@@ -347,21 +319,19 @@ static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetwork
|
|
|
|
|
|
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
|
|
|
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
|
|
|
- AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
|
|
|
+ AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info;
|
|
|
if (block) {
|
|
|
block(status);
|
|
|
}
|
|
|
|
|
|
- [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInt:status]];
|
|
|
+ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
|
|
}
|
|
|
|
|
|
static const void * AFNetworkReachabilityRetainCallback(const void *info) {
|
|
|
- return [(AFNetworkReachabilityStatusBlock)info copy];
|
|
|
+ return (__bridge_retained const void *)([(__bridge AFNetworkReachabilityStatusBlock)info copy]);
|
|
|
}
|
|
|
|
|
|
-static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
- [(AFNetworkReachabilityStatusBlock)info release];
|
|
|
-}
|
|
|
+static void AFNetworkReachabilityReleaseCallback(const void *info) {}
|
|
|
|
|
|
- (void)startMonitoringNetworkReachability {
|
|
|
[self stopMonitoringNetworkReachability];
|
|
@@ -379,7 +349,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- SCNetworkReachabilityContext context = {0, callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
|
|
|
+ SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
|
|
|
SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
|
|
|
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
|
|
|
|
|
@@ -399,6 +369,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
if (_networkReachability) {
|
|
|
SCNetworkReachabilityUnscheduleFromRunLoop(_networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
|
|
|
CFRelease(_networkReachability);
|
|
|
+ _networkReachability = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -456,7 +427,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
parameters:(NSDictionary *)parameters
|
|
|
{
|
|
|
NSURL *url = [NSURL URLWithString:path relativeToURL:self.baseURL];
|
|
|
- NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:url] autorelease];
|
|
|
+ NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
|
|
|
[request setHTTPMethod:method];
|
|
|
[request setAllHTTPHeaderFields:self.defaultHeaders];
|
|
|
|
|
@@ -465,7 +436,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
url = [NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding)]];
|
|
|
[request setURL:url];
|
|
|
} else {
|
|
|
- NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
|
|
|
+ NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
|
|
|
switch (self.parameterEncoding) {
|
|
|
case AFFormURLParameterEncoding:;
|
|
|
[request setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
|
|
@@ -489,22 +460,24 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
|
|
|
path:(NSString *)path
|
|
|
parameters:(NSDictionary *)parameters
|
|
|
- constructingBodyWithBlock:(void (^)(id <AFStreamingMultipartFormData>formData))block
|
|
|
+ constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
|
|
|
{
|
|
|
NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil];
|
|
|
+
|
|
|
+ __block AFStreamingMultipartFormData *formData = [[AFStreamingMultipartFormData alloc] initWithURLRequest:request stringEncoding:self.stringEncoding];
|
|
|
|
|
|
- __block AFStreamingMultipartFormData *formData = [[[AFStreamingMultipartFormData alloc] initWithURLRequest:request stringEncoding:self.stringEncoding] autorelease];
|
|
|
-
|
|
|
- for (AFQueryStringComponent *component in AFQueryStringComponentsFromKeyAndValue(nil, parameters)) {
|
|
|
- NSData *data = nil;
|
|
|
- if ([component.value isKindOfClass:[NSData class]]) {
|
|
|
- data = component.value;
|
|
|
- } else {
|
|
|
- data = [[component.value description] dataUsingEncoding:self.stringEncoding];
|
|
|
- }
|
|
|
-
|
|
|
- if (data) {
|
|
|
- [formData appendPartWithFormData:data name:[component.key description]];
|
|
|
+ if (parameters) {
|
|
|
+ for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
|
|
|
+ NSData *data = nil;
|
|
|
+ if ([pair.value isKindOfClass:[NSData class]]) {
|
|
|
+ data = pair.value;
|
|
|
+ } else {
|
|
|
+ data = [[pair.value description] dataUsingEncoding:self.stringEncoding];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ [formData appendPartWithFormData:data name:[pair.field description]];
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -525,12 +498,12 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
while (!operation && (className = [enumerator nextObject])) {
|
|
|
Class op_class = NSClassFromString(className);
|
|
|
if (op_class && [op_class canProcessRequest:urlRequest]) {
|
|
|
- operation = [[(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest] autorelease];
|
|
|
+ operation = [(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!operation) {
|
|
|
- operation = [[[AFHTTPRequestOperation alloc] initWithRequest:urlRequest] autorelease];
|
|
|
+ operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
|
|
|
}
|
|
|
|
|
|
[operation setCompletionBlockWithSuccess:success failure:failure];
|
|
@@ -557,7 +530,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
}
|
|
|
|
|
|
- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests
|
|
|
- progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
+ progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
completionBlock:(void (^)(NSArray *operations))completionBlock
|
|
|
{
|
|
|
NSMutableArray *mutableOperations = [NSMutableArray array];
|
|
@@ -570,7 +543,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
}
|
|
|
|
|
|
- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
|
|
|
- progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
+ progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
completionBlock:(void (^)(NSArray *operations))completionBlock
|
|
|
{
|
|
|
__block dispatch_group_t dispatchGroup = dispatch_group_create();
|
|
@@ -580,22 +553,29 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
completionBlock(operations);
|
|
|
}
|
|
|
});
|
|
|
+#if AF_DISPATCH_RETAIN_RELEASE
|
|
|
dispatch_release(dispatchGroup);
|
|
|
+#endif
|
|
|
}];
|
|
|
|
|
|
- NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"];
|
|
|
-
|
|
|
for (AFHTTPRequestOperation *operation in operations) {
|
|
|
- AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease];
|
|
|
+ AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
|
|
operation.completionBlock = ^{
|
|
|
- dispatch_queue_t queue = operation.successCallbackQueue ? operation.successCallbackQueue : dispatch_get_main_queue();
|
|
|
+ dispatch_queue_t queue = operation.successCallbackQueue ?: dispatch_get_main_queue();
|
|
|
dispatch_group_async(dispatchGroup, queue, ^{
|
|
|
if (originalCompletionBlock) {
|
|
|
originalCompletionBlock();
|
|
|
}
|
|
|
|
|
|
+ __block NSUInteger numberOfFinishedOperations = 0;
|
|
|
+ [operations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
|
+ if ([(NSOperation *)obj isFinished]) {
|
|
|
+ numberOfFinishedOperations++;
|
|
|
+ }
|
|
|
+ }];
|
|
|
+
|
|
|
if (progressBlock) {
|
|
|
- progressBlock([[operations filteredArrayUsingPredicate:finishedOperationPredicate] count], [operations count]);
|
|
|
+ progressBlock(numberOfFinishedOperations, [operations count]);
|
|
|
}
|
|
|
|
|
|
dispatch_group_leave(dispatchGroup);
|
|
@@ -695,8 +675,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
|
|
|
HTTPClient.stringEncoding = self.stringEncoding;
|
|
|
HTTPClient.parameterEncoding = self.parameterEncoding;
|
|
|
- HTTPClient.registeredHTTPOperationClassNames = [[self.registeredHTTPOperationClassNames copyWithZone:zone] autorelease];
|
|
|
- HTTPClient.defaultHeaders = [[self.defaultHeaders copyWithZone:zone] autorelease];
|
|
|
+ HTTPClient.registeredHTTPOperationClassNames = [self.registeredHTTPOperationClassNames copyWithZone:zone];
|
|
|
+ HTTPClient.defaultHeaders = [self.defaultHeaders copyWithZone:zone];
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
|
HTTPClient.networkReachabilityStatusBlock = self.networkReachabilityStatusBlock;
|
|
|
#endif
|
|
@@ -717,7 +697,7 @@ static NSString * AFMultipartTemporaryFileDirectoryPath() {
|
|
|
|
|
|
NSError *error = nil;
|
|
|
if(![[NSFileManager defaultManager] createDirectoryAtPath:multipartTemporaryFilePath withIntermediateDirectories:YES attributes:nil error:&error]) {
|
|
|
- NSLog(@"Failed to create multipary temporary file directory at %@", multipartTemporaryFilePath);
|
|
|
+ NSLog(@"Failed to create multipart temporary file directory at %@", multipartTemporaryFilePath);
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -743,12 +723,16 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
}
|
|
|
|
|
|
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
- CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
|
|
|
- NSString *contentType = (NSString *)UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
|
|
|
+#ifdef __UTTYPE__
|
|
|
+ CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
|
|
|
+ NSString *contentType = (__bridge NSString *)UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
|
|
|
|
|
|
CFRelease(UTI);
|
|
|
|
|
|
- return [contentType autorelease];
|
|
|
+ return contentType;
|
|
|
+#else
|
|
|
+ return @"application/octet-stream";
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
|
@@ -821,17 +805,11 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
|
|
|
self.request = request;
|
|
|
self.stringEncoding = encoding;
|
|
|
- self.bodyStream = [[[AFMultipartBodyStream alloc] initWithStringEncoding:encoding] autorelease];
|
|
|
+ self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
|
|
|
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
-- (void)dealloc {
|
|
|
- [_request release];
|
|
|
- [_bodyStream release];
|
|
|
- [super dealloc];
|
|
|
-}
|
|
|
-
|
|
|
- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name {
|
|
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
|
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
|
|
@@ -846,7 +824,6 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
[self.bodyStream.HTTPBodyParts addObject:bodyPart];
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- (void)appendPartWithFileData:(NSData *)data
|
|
|
name:(NSString *)name
|
|
|
fileName:(NSString *)fileName
|
|
@@ -873,14 +850,14 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
if (![fileURL isFileURL]) {
|
|
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Expected URL to be a file URL", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
|
if (error != NULL) {
|
|
|
- *error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
|
|
+ *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
|
|
|
}
|
|
|
|
|
|
return NO;
|
|
|
} else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
|
|
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"File URL not reachable.", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
|
if (error != NULL) {
|
|
|
- *error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
|
|
+ *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
|
|
|
}
|
|
|
|
|
|
return NO;
|
|
@@ -908,7 +885,7 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
if ([self.bodyStream isEmpty]) {
|
|
|
return self.request;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// We have to set the initial and final boundaries here so that the body stream returns the correct content length.
|
|
|
[self.bodyStream setInitialAndFinalBoundaries];
|
|
|
|
|
@@ -943,13 +920,6 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
-- (void)dealloc {
|
|
|
- [_HTTPBodyParts release];
|
|
|
- [_HTTPBodyPartEnumerator release];
|
|
|
- [_currentHTTPBodyPart release];
|
|
|
- [super dealloc];
|
|
|
-}
|
|
|
-
|
|
|
- (void)setInitialAndFinalBoundaries {
|
|
|
if ([self.HTTPBodyParts count] > 0) { // If there's any HTTP body parts...
|
|
|
// Reset all HTTP body parts boundary settings first.
|
|
@@ -1104,22 +1074,44 @@ typedef enum {
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
-- (void)dealloc {
|
|
|
- [_headers release];
|
|
|
-
|
|
|
- if (_inputStream) {
|
|
|
- [_inputStream close];
|
|
|
- [_inputStream release];
|
|
|
- _inputStream = nil;
|
|
|
- }
|
|
|
-
|
|
|
- [super dealloc];
|
|
|
+- (void)appendPartWithFormData:(NSData *)data
|
|
|
+ name:(NSString *)name
|
|
|
+{
|
|
|
+ NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
|
|
+ [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)appendPartWithFileData:(NSData *)data
|
|
|
+ name:(NSString *)name
|
|
|
+ fileName:(NSString *)fileName
|
|
|
+ mimeType:(NSString *)mimeType
|
|
|
+{
|
|
|
+ NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
|
|
+ [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
|
|
+ [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
|
|
}
|
|
|
|
|
|
- (BOOL)transitionToNextPhase {
|
|
|
if (![[NSThread currentThread] isMainThread]) {
|
|
|
[self performSelectorOnMainThread:@selector(transitionToNextPhase) withObject:nil waitUntilDone:YES];
|
|
|
- return YES;
|
|
|
+ }
|
|
|
+
|
|
|
+ return YES;
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
|
|
+ name:(NSString *)name
|
|
|
+ error:(NSError **)error
|
|
|
+{
|
|
|
+ if (![fileURL isFileURL]) {
|
|
|
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
|
|
+ [userInfo setValue:fileURL forKey:NSURLErrorFailingURLErrorKey];
|
|
|
+ [userInfo setValue:NSLocalizedString(@"Expected URL to be a file URL", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
|
+ if (error != NULL) {
|
|
|
+ *error = [[NSError alloc] initWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
|
|
|
+ }
|
|
|
+
|
|
|
+ return NO;
|
|
|
}
|
|
|
|
|
|
switch (_phase) {
|