2011-09-21 22:42:01 -05:00
// AFHTTPClient . m
2011-06-01 11:51:53 -05:00
//
// Copyright ( c ) 2011 Gowalla ( http : // gowalla . com / )
2012-08-23 10:16:43 -07:00
//
2011-06-01 11:51:53 -05:00
// Permission is hereby granted , free of charge , to any person obtaining a copy
// of this software and associated documentation files ( the "Software" ) , to deal
// in the Software without restriction , including without limitation the rights
// to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
// copies of the Software , and to permit persons to whom the Software is
// furnished to do so , subject to the following conditions :
2012-08-23 10:16:43 -07:00
//
2011-06-01 11:51:53 -05:00
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software .
2012-08-23 10:16:43 -07:00
//
2011-06-01 11:51:53 -05:00
// THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
// IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
// LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE .
2011-10-11 12:26:34 -05:00
# import < Foundation / Foundation . h >
2011-09-21 22:42:01 -05:00
# import "AFHTTPClient.h"
2011-10-11 12:26:34 -05:00
# import "AFHTTPRequestOperation.h"
2011-10-06 14:33:16 -05:00
2011-10-11 12:26:34 -05:00
# import < Availability . h >
2012-01-19 17:26:12 -08:00
# ifdef _SYSTEMCONFIGURATION _H
2013-01-27 12:15:07 -05:00
# import < netinet / in . h >
# import < netinet6 / in6 . h >
# import < arpa / inet . h >
# import < ifaddrs . h >
# import < netdb . h >
2012-01-19 17:26:12 -08:00
# endif
2012-11-30 18:12:47 +11:00
# if defined ( __IPHONE _OS _VERSION _MIN _REQUIRED )
2013-01-27 12:15:07 -05:00
# import < UIKit / UIKit . h >
2012-09-26 20:56:33 -04:00
# endif
2012-01-19 17:26:12 -08:00
# ifdef _SYSTEMCONFIGURATION _H
2012-08-31 09:04:54 -07:00
NSString * const AFNetworkingReachabilityDidChangeNotification = @ "com.alamofire.networking.reachability.change" ;
NSString * const AFNetworkingReachabilityNotificationStatusItem = @ "AFNetworkingReachabilityNotificationStatusItem" ;
2012-01-19 17:26:12 -08:00
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef ;
2012-03-09 15:48:59 -08:00
typedef void ( ^ AFNetworkReachabilityStatusBlock ) ( AFNetworkReachabilityStatus status ) ;
2012-01-19 17:26:12 -08:00
# else
typedef id AFNetworkReachabilityRef ;
# endif
2012-01-23 08:44:59 -08:00
typedef void ( ^ AFCompletionBlock ) ( void ) ;
2012-01-10 12:20:30 -08:00
2011-09-21 11:36:39 -05:00
static NSString * AFBase64EncodedStringFromString ( NSString * string ) {
2012-07-19 22:23:38 -07:00
NSData * data = [ NSData dataWithBytes : [ string UTF8String ] length : [ string lengthOfBytesUsingEncoding : NSUTF8StringEncoding ] ] ;
NSUInteger length = [ data length ] ;
NSMutableData * mutableData = [ NSMutableData dataWithLength : ( ( length + 2 ) / 3 ) * 4 ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
uint8_t * input = ( uint8_t * ) [ data bytes ] ;
uint8_t * output = ( uint8_t * ) [ mutableData mutableBytes ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
for ( NSUInteger i = 0 ; i < length ; i + = 3 ) {
NSUInteger value = 0 ;
for ( NSUInteger j = i ; j < ( i + 3 ) ; j + + ) {
value < <= 8 ;
if ( j < length ) {
2012-08-23 10:16:43 -07:00
value | = ( 0 xFF & input [ j ] ) ;
2012-07-19 22:23:38 -07:00
}
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
static uint8_t const kAFBase64EncodingTable [ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
NSUInteger idx = ( i / 3 ) * 4 ;
output [ idx + 0 ] = kAFBase64EncodingTable [ ( value > > 18 ) & 0 x3F ] ;
output [ idx + 1 ] = kAFBase64EncodingTable [ ( value > > 12 ) & 0 x3F ] ;
output [ idx + 2 ] = ( i + 1 ) < length ? kAFBase64EncodingTable [ ( value > > 6 ) & 0 x3F ] : ' = ' ;
output [ idx + 3 ] = ( i + 2 ) < length ? kAFBase64EncodingTable [ ( value > > 0 ) & 0 x3F ] : ' = ' ;
}
2013-01-27 12:15:07 -05:00
2012-06-26 09:14:52 -07:00
return [ [ NSString alloc ] initWithData : mutableData encoding : NSASCIIStringEncoding ] ;
2011-09-21 11:36:39 -05:00
}
2012-09-04 19:24:03 +02:00
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( NSString * string , NSStringEncoding encoding ) {
2013-03-07 20:42:16 -08:00
static NSString * const kAFCharactersToBeEscaped = @ ":/?&=;+!@#$()~',*" ;
2012-10-24 15:55:40 -02:00
static NSString * const kAFCharactersToLeaveUnescaped = @ "[]." ;
2013-01-27 12:15:07 -05:00
2012-10-03 08:49:39 -07:00
return ( __bridge _transfer NSString * ) CFURLCreateStringByAddingPercentEscapes ( kCFAllocatorDefault , ( __bridge CFStringRef ) string , ( __bridge CFStringRef ) kAFCharactersToLeaveUnescaped , ( __bridge CFStringRef ) kAFCharactersToBeEscaped , CFStringConvertNSStringEncodingToEncoding ( encoding ) ) ;
2011-10-06 14:33:16 -05:00
}
2012-03-19 12:44:06 -04:00
# pragma mark -
2012-03-07 22:47:04 +01:00
2012-08-29 10:49:55 -07:00
@ interface AFQueryStringPair : NSObject
2012-10-09 09:26:50 -07:00
@ property ( readwrite , nonatomic , strong ) id field ;
@ property ( readwrite , nonatomic , strong ) id value ;
2012-03-19 12:44:06 -04:00
2012-08-29 10:49:55 -07:00
- ( id ) initWithField : ( id ) field value : ( id ) value ;
2012-09-25 09:56:34 -07:00
2012-03-28 10:05:00 -07:00
- ( NSString * ) URLEncodedStringValueWithEncoding : ( NSStringEncoding ) stringEncoding ;
2012-03-19 12:44:06 -04:00
@ end
2012-09-03 11:11:24 -07:00
@ implementation AFQueryStringPair
2012-08-29 10:49:55 -07:00
@ synthesize field = _field ;
2012-03-19 12:44:06 -04:00
@ synthesize value = _value ;
2012-08-29 10:49:55 -07:00
- ( id ) initWithField : ( id ) field value : ( id ) value {
2012-07-19 22:23:38 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-08-29 10:49:55 -07:00
self . field = field ;
2012-07-19 22:23:38 -07:00
self . value = value ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return self ;
2012-03-19 12:44:06 -04:00
}
2012-03-28 10:05:00 -07:00
- ( NSString * ) URLEncodedStringValueWithEncoding : ( NSStringEncoding ) stringEncoding {
2012-10-05 09:20:05 -07:00
if ( ! self . value || [ self . value isEqual : [ NSNull null ] ] ) {
2012-11-06 15:16:48 +01:00
return AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . field description ] , stringEncoding ) ;
2012-10-05 09:20:05 -07:00
} else {
2012-11-06 15:16:48 +01:00
return [ NSString stringWithFormat : @ "%@=%@" , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . field description ] , stringEncoding ) , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . value description ] , stringEncoding ) ] ;
2012-10-05 09:20:05 -07:00
}
2012-03-07 22:47:04 +01:00
}
2012-03-19 12:44:06 -04:00
@ end
# pragma mark -
2012-08-29 10:49:55 -07:00
extern NSArray * AFQueryStringPairsFromDictionary ( NSDictionary * dictionary ) ;
extern NSArray * AFQueryStringPairsFromKeyAndValue ( NSString * key , id value ) ;
2012-03-07 22:47:04 +01:00
2012-03-28 10:05:00 -07:00
NSString * AFQueryStringFromParametersWithEncoding ( NSDictionary * parameters , NSStringEncoding stringEncoding ) {
2012-08-29 10:49:55 -07:00
NSMutableArray * mutablePairs = [ NSMutableArray array ] ;
for ( AFQueryStringPair * pair in AFQueryStringPairsFromDictionary ( parameters ) ) {
[ mutablePairs addObject : [ pair URLEncodedStringValueWithEncoding : stringEncoding ] ] ;
2012-07-19 22:23:38 -07:00
}
2013-01-27 12:15:07 -05:00
2012-08-29 10:49:55 -07:00
return [ mutablePairs componentsJoinedByString : @ "&" ] ;
2012-03-19 12:44:06 -04:00
}
2012-08-29 10:49:55 -07:00
NSArray * AFQueryStringPairsFromDictionary ( NSDictionary * dictionary ) {
return AFQueryStringPairsFromKeyAndValue ( nil , dictionary ) ;
2012-03-19 12:44:06 -04:00
}
2012-08-29 10:49:55 -07:00
NSArray * AFQueryStringPairsFromKeyAndValue ( NSString * key , id value ) {
2012-07-19 22:23:38 -07:00
NSMutableArray * mutableQueryStringComponents = [ NSMutableArray array ] ;
2013-01-27 12:15:07 -05:00
2012-12-27 16:23:27 -05:00
if ( [ value isKindOfClass : [ NSDictionary class ] ] ) {
2013-01-30 11:44:33 +11:00
NSDictionary * dictionary = value ;
2012-11-09 14:23:51 -08:00
// Sort dictionary keys to ensure consistent ordering in query string , which is important when deserializing potentially ambiguous sequences , such as an array of dictionaries
2012-11-05 12:03:23 -08:00
NSSortDescriptor * sortDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "description" ascending : YES selector : @ selector ( caseInsensitiveCompare : ) ] ;
2013-01-30 11:44:33 +11:00
[ [ [ dictionary allKeys ] sortedArrayUsingDescriptors : [ NSArray arrayWithObject : sortDescriptor ] ] enumerateObjectsUsingBlock : ^ ( id nestedKey , __unused NSUInteger idx , __unused BOOL * stop ) {
id nestedValue = [ dictionary objectForKey : nestedKey ] ;
2012-11-05 12:03:23 -08:00
if ( nestedValue ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( ( key ? [ NSString stringWithFormat : @ "%@[%@]" , key , nestedKey ] : nestedKey ) , nestedValue ) ] ;
}
2012-08-29 10:49:55 -07:00
} ] ;
2012-12-27 16:23:27 -05:00
} else if ( [ value isKindOfClass : [ NSArray class ] ] ) {
2012-11-29 19:08:41 +11:00
NSArray * array = value ;
2012-11-29 18:46:04 +11:00
[ array enumerateObjectsUsingBlock : ^ ( id nestedValue , __unused NSUInteger idx , __unused BOOL * stop ) {
2012-08-29 10:49:55 -07:00
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( [ NSString stringWithFormat : @ "%@[]" , key ] , nestedValue ) ] ;
} ] ;
2013-02-05 12:46:03 +00:00
} else if ( [ value isKindOfClass : [ NSSet class ] ] ) {
NSSet * set = value ;
[ set enumerateObjectsUsingBlock : ^ ( id obj , BOOL * stop ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( key , obj ) ] ;
} ] ;
2012-07-19 22:23:38 -07:00
} else {
2012-09-14 10:30:25 -07:00
[ mutableQueryStringComponents addObject : [ [ AFQueryStringPair alloc ] initWithField : key value : value ] ] ;
2012-08-23 10:16:43 -07:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return mutableQueryStringComponents ;
2012-03-07 22:47:04 +01:00
}
2012-09-25 11:06:03 -07:00
@ interface AFStreamingMultipartFormData : NSObject < AFMultipartFormData >
2012-10-14 10:22:40 -07:00
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) urlRequest
2012-09-25 11:06:03 -07:00
stringEncoding : ( NSStringEncoding ) encoding ;
- ( NSMutableURLRequest * ) requestByFinalizingMultipartFormData ;
@ end
# pragma mark -
2011-09-21 22:42:01 -05:00
@ interface AFHTTPClient ( )
2013-01-05 22:19:59 -08:00
@ property ( readwrite , nonatomic , strong ) NSURL * baseURL ;
@ property ( readwrite , nonatomic , strong ) NSMutableArray * registeredHTTPOperationClassNames ;
@ property ( readwrite , nonatomic , strong ) NSMutableDictionary * defaultHeaders ;
@ property ( readwrite , nonatomic , strong ) NSURLCredential * defaultCredential ;
@ property ( readwrite , nonatomic , strong ) NSOperationQueue * operationQueue ;
2012-03-05 16:01:12 -06:00
# ifdef _SYSTEMCONFIGURATION _H
2012-01-19 17:26:12 -08:00
@ property ( readwrite , nonatomic , assign ) AFNetworkReachabilityRef networkReachability ;
2012-03-09 15:48:59 -08:00
@ property ( readwrite , nonatomic , assign ) AFNetworkReachabilityStatus networkReachabilityStatus ;
2012-01-10 12:20:30 -08:00
@ property ( readwrite , nonatomic , copy ) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock ;
2012-03-05 16:01:12 -06:00
# endif
2012-02-01 11:27:57 -08:00
# ifdef _SYSTEMCONFIGURATION _H
- ( void ) startMonitoringNetworkReachability ;
- ( void ) stopMonitoringNetworkReachability ;
# endif
2011-06-01 11:51:53 -05:00
@ end
2011-09-21 22:42:01 -05:00
@ implementation AFHTTPClient
2011-09-16 10:02:51 -05:00
@ synthesize baseURL = _baseURL ;
2011-09-21 11:36:39 -05:00
@ synthesize stringEncoding = _stringEncoding ;
2011-10-06 14:33:16 -05:00
@ synthesize parameterEncoding = _parameterEncoding ;
2011-10-05 15:44:51 -05:00
@ synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames ;
2011-06-01 11:51:53 -05:00
@ synthesize defaultHeaders = _defaultHeaders ;
2013-01-05 22:19:59 -08:00
@ synthesize defaultCredential = _defaultCredential ;
2011-06-01 11:51:53 -05:00
@ synthesize operationQueue = _operationQueue ;
2012-03-05 16:01:12 -06:00
# ifdef _SYSTEMCONFIGURATION _H
2012-01-10 12:20:30 -08:00
@ synthesize networkReachability = _networkReachability ;
2012-03-09 15:48:59 -08:00
@ synthesize networkReachabilityStatus = _networkReachabilityStatus ;
2012-01-10 12:20:30 -08:00
@ synthesize networkReachabilityStatusBlock = _networkReachabilityStatusBlock ;
2012-03-05 16:01:12 -06:00
# endif
2011-06-01 11:51:53 -05:00
2012-12-23 10:59:56 +02:00
+ ( instancetype ) clientWithBaseURL : ( NSURL * ) url {
2012-06-26 09:14:52 -07:00
return [ [ self alloc ] initWithBaseURL : url ] ;
2011-09-22 09:43:58 -05:00
}
2011-09-16 10:02:51 -05:00
- ( id ) initWithBaseURL : ( NSURL * ) url {
2012-10-14 10:06:50 -07:00
NSParameterAssert ( url ) ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-08-11 14:26:03 -04:00
// Ensure terminal slash for baseURL path , so that NSURL + URLWithString : relativeToURL : works as expected
if ( [ [ url path ] length ] > 0 && ! [ [ url absoluteString ] hasSuffix : @ "/" ] ) {
url = [ url URLByAppendingPathComponent : @ "" ] ;
2012-08-08 11:07:20 -07:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
self . baseURL = url ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
self . stringEncoding = NSUTF8StringEncoding ;
self . parameterEncoding = AFFormURLParameterEncoding ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
self . registeredHTTPOperationClassNames = [ NSMutableArray array ] ;
2013-01-27 12:15:07 -05:00
2011-06-01 11:51:53 -05:00
self . defaultHeaders = [ NSMutableDictionary dictionary ] ;
2013-01-27 12:15:07 -05:00
2012-09-03 11:11:24 -07:00
// Accept - Language HTTP Header ; see http : // www . w3 . org / Protocols / rfc2616 / rfc2616 - sec14 . html # sec14 .4
2013-01-26 11:32:13 -05:00
NSMutableArray * acceptLanguagesComponents = [ NSMutableArray array ] ;
[ [ NSLocale preferredLanguages ] enumerateObjectsUsingBlock : ^ ( id obj , NSUInteger idx , BOOL * stop ) {
float q = 1.0 f - ( idx * 0.1 f ) ;
[ acceptLanguagesComponents addObject : [ NSString stringWithFormat : @ "%@;q=%0.1g" , obj , q ] ] ;
2013-02-01 22:43:30 +00:00
* stop = q <= 0.5 f ;
2013-01-26 11:32:13 -05:00
} ] ;
[ self setDefaultHeader : @ "Accept-Language" value : [ acceptLanguagesComponents componentsJoinedByString : @ ", " ] ] ;
2012-07-19 22:23:38 -07:00
2012-11-30 18:12:47 +11:00
# if defined ( __IPHONE _OS _VERSION _MIN _REQUIRED )
2012-07-19 22:23:38 -07:00
// User - Agent Header ; see http : // www . w3 . org / Protocols / rfc2616 / rfc2616 - sec14 . html # sec14 .43
2012-09-14 10:30:25 -07:00
[ 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.0 f ) ] ] ;
2012-11-30 18:12:47 +11:00
# elif defined ( __MAC _OS _X _VERSION _MIN _REQUIRED )
2012-08-29 14:16:27 -07:00
[ 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 ] ] ] ;
2011-10-11 12:26:34 -05:00
# endif
2013-01-27 12:15:07 -05:00
2012-02-01 11:27:57 -08:00
# ifdef _SYSTEMCONFIGURATION _H
2012-07-19 22:23:38 -07:00
self . networkReachabilityStatus = AFNetworkReachabilityStatusUnknown ;
[ self startMonitoringNetworkReachability ] ;
2012-02-01 11:27:57 -08:00
# endif
2013-01-27 12:15:07 -05:00
2012-06-26 09:14:52 -07:00
self . operationQueue = [ [ NSOperationQueue alloc ] init ] ;
2012-08-06 17:30:01 -04:00
[ self . operationQueue setMaxConcurrentOperationCount : NSOperationQueueDefaultMaxConcurrentOperationCount ] ;
2013-01-27 12:15:07 -05:00
2013-03-25 17:21:56 -05:00
// This ifdef has been added for backwards compatibility purposes
# ifdef _AFNETWORKING _ALLOW _INVALID _SSL _CERTIFICATES _
self . allowInvalidSSLCertificate = YES ;
# endif
2012-07-19 22:23:38 -07:00
return self ;
2011-06-01 11:51:53 -05:00
}
- ( void ) dealloc {
2012-02-01 11:27:57 -08:00
# ifdef _SYSTEMCONFIGURATION _H
2012-07-19 22:23:38 -07:00
[ self stopMonitoringNetworkReachability ] ;
2012-02-01 11:27:57 -08:00
# endif
2011-06-01 11:51:53 -05:00
}
2012-01-23 08:41:55 -08:00
- ( NSString * ) description {
2012-07-19 22:23:38 -07:00
return [ NSString stringWithFormat : @ "<%@: %p, baseURL: %@, defaultHeaders: %@, registeredOperationClasses: %@, operationQueue: %@>" , NSStringFromClass ( [ self class ] ) , self , [ self . baseURL absoluteString ] , self . defaultHeaders , self . registeredHTTPOperationClassNames , self . operationQueue ] ;
2012-01-23 08:41:55 -08:00
}
2011-10-05 15:44:51 -05:00
# pragma mark -
2012-01-19 17:26:12 -08:00
# ifdef _SYSTEMCONFIGURATION _H
2012-03-20 16:43:19 -07:00
static BOOL AFURLHostIsIPAddress ( NSURL * url ) {
2012-07-19 22:23:38 -07:00
struct sockaddr_in sa_in ;
struct sockaddr_in6 sa_in6 ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return [ url host ] && ( inet_pton ( AF_INET , [ [ url host ] UTF8String ] , & sa_in ) = = 1 || inet_pton ( AF_INET6 , [ [ url host ] UTF8String ] , & sa_in6 ) = = 1 ) ;
2012-03-20 16:43:19 -07:00
}
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags ( SCNetworkReachabilityFlags flags ) {
2012-07-19 22:23:38 -07:00
BOOL isReachable = ( ( flags & kSCNetworkReachabilityFlagsReachable ) ! = 0 ) ;
BOOL needsConnection = ( ( flags & kSCNetworkReachabilityFlagsConnectionRequired ) ! = 0 ) ;
BOOL isNetworkReachable = ( isReachable && ! needsConnection ) ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown ;
2012-12-27 16:23:27 -05:00
if ( isNetworkReachable = = NO ) {
2012-07-19 22:23:38 -07:00
status = AFNetworkReachabilityStatusNotReachable ;
}
2012-03-20 16:43:19 -07:00
# if TARGET_OS _IPHONE
2012-12-27 16:23:27 -05:00
else if ( ( flags & kSCNetworkReachabilityFlagsIsWWAN ) ! = 0 ) {
2012-07-19 22:23:38 -07:00
status = AFNetworkReachabilityStatusReachableViaWWAN ;
}
2012-03-20 16:43:19 -07:00
# endif
2012-07-19 22:23:38 -07:00
else {
status = AFNetworkReachabilityStatusReachableViaWiFi ;
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return status ;
2012-03-20 16:43:19 -07:00
}
2012-08-23 10:16:43 -07:00
static void AFNetworkReachabilityCallback ( SCNetworkReachabilityRef __unused target , SCNetworkReachabilityFlags flags , void * info ) {
2012-07-19 22:23:38 -07:00
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags ( flags ) ;
2012-06-26 09:14:52 -07:00
AFNetworkReachabilityStatusBlock block = ( __bridge AFNetworkReachabilityStatusBlock ) info ;
2012-07-19 22:23:38 -07:00
if ( block ) {
block ( status ) ;
}
2013-01-27 12:15:07 -05:00
2012-12-27 12:22:46 -05:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2013-01-30 11:22:15 +11:00
NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter ] ;
[ notificationCenter postNotificationName : AFNetworkingReachabilityDidChangeNotification object : nil userInfo : [ NSDictionary dictionaryWithObject : [ NSNumber numberWithInteger : status ] forKey : AFNetworkingReachabilityNotificationStatusItem ] ] ;
2012-12-27 12:22:46 -05:00
} ) ;
2012-01-10 12:20:30 -08:00
}
2012-03-20 16:43:19 -07:00
static const void * AFNetworkReachabilityRetainCallback ( const void * info ) {
2012-06-26 09:14:52 -07:00
return ( __bridge _retained const void * ) ( [ ( __bridge AFNetworkReachabilityStatusBlock ) info copy ] ) ;
2012-03-11 10:53:06 -07:00
}
2012-12-26 11:37:18 -05:00
static void AFNetworkReachabilityReleaseCallback ( const void * info ) {
if ( info ) {
CFRelease ( info ) ;
}
}
2012-03-11 10:53:06 -07:00
2012-02-01 11:27:57 -08:00
- ( void ) startMonitoringNetworkReachability {
2012-07-19 22:23:38 -07:00
[ self stopMonitoringNetworkReachability ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
if ( ! self . baseURL ) {
return ;
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
self . networkReachability = SCNetworkReachabilityCreateWithName ( kCFAllocatorDefault , [ [ self . baseURL host ] UTF8String ] ) ;
2013-01-27 12:15:07 -05:00
2012-11-30 14:22:05 -08:00
if ( ! self . networkReachability ) {
return ;
}
2013-01-27 12:15:07 -05:00
2012-10-31 07:42:19 -07:00
__weak __typeof ( & * self ) weakSelf = self ;
2012-12-27 16:23:27 -05:00
AFNetworkReachabilityStatusBlock callback = ^ ( AFNetworkReachabilityStatus status ) {
2012-10-31 07:42:19 -07:00
__strong __typeof ( & * weakSelf ) strongSelf = weakSelf ;
2012-10-30 11:58:54 -07:00
if ( ! strongSelf ) {
return ;
}
2013-01-27 12:15:07 -05:00
2012-10-30 11:58:54 -07:00
strongSelf . networkReachabilityStatus = status ;
if ( strongSelf . networkReachabilityStatusBlock ) {
strongSelf . networkReachabilityStatusBlock ( status ) ;
2012-07-19 22:23:38 -07:00
}
} ;
2013-01-27 12:15:07 -05:00
2012-06-26 09:14:52 -07:00
SCNetworkReachabilityContext context = { 0 , ( __bridge void * ) callback , AFNetworkReachabilityRetainCallback , AFNetworkReachabilityReleaseCallback , NULL } ;
2012-07-19 22:23:38 -07:00
SCNetworkReachabilitySetCallback ( self . networkReachability , AFNetworkReachabilityCallback , & context ) ;
SCNetworkReachabilityScheduleWithRunLoop ( self . networkReachability , CFRunLoopGetMain ( ) , ( CFStringRef ) NSRunLoopCommonModes ) ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
/ * Network reachability monitoring does not establish a baseline for IP addresses as it does for hostnames , so if the base URL host is an IP address , the initial reachability callback is manually triggered .
* /
if ( AFURLHostIsIPAddress ( self . baseURL ) ) {
SCNetworkReachabilityFlags flags ;
SCNetworkReachabilityGetFlags ( self . networkReachability , & flags ) ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags ( flags ) ;
callback ( status ) ;
} ) ;
2012-03-13 09:12:58 -05:00
}
2012-02-01 11:27:57 -08:00
}
- ( void ) stopMonitoringNetworkReachability {
2012-07-19 22:23:38 -07:00
if ( _networkReachability ) {
SCNetworkReachabilityUnscheduleFromRunLoop ( _networkReachability , CFRunLoopGetMain ( ) , ( CFStringRef ) NSRunLoopCommonModes ) ;
CFRelease ( _networkReachability ) ;
2012-09-19 16:00:15 -04:00
_networkReachability = NULL ;
2012-07-19 22:23:38 -07:00
}
2012-02-01 11:27:57 -08:00
}
2012-03-09 15:48:59 -08:00
- ( void ) setReachabilityStatusChangeBlock : ( void ( ^ ) ( AFNetworkReachabilityStatus status ) ) block {
2012-07-19 22:23:38 -07:00
self . networkReachabilityStatusBlock = block ;
2012-01-10 12:20:30 -08:00
}
2012-01-19 17:26:12 -08:00
# endif
2012-01-10 12:20:30 -08:00
# pragma mark -
2011-10-05 15:44:51 -05:00
- ( BOOL ) registerHTTPOperationClass : ( Class ) operationClass {
2012-07-19 22:23:38 -07:00
if ( ! [ operationClass isSubclassOfClass : [ AFHTTPRequestOperation class ] ] ) {
return NO ;
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
NSString * className = NSStringFromClass ( operationClass ) ;
[ self . registeredHTTPOperationClassNames removeObject : className ] ;
[ self . registeredHTTPOperationClassNames insertObject : className atIndex : 0 ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return YES ;
2011-10-05 15:44:51 -05:00
}
2011-10-12 10:41:59 -05:00
- ( void ) unregisterHTTPOperationClass : ( Class ) operationClass {
2012-07-19 22:23:38 -07:00
NSString * className = NSStringFromClass ( operationClass ) ;
[ self . registeredHTTPOperationClassNames removeObject : className ] ;
2011-10-12 10:41:59 -05:00
}
2011-10-05 15:44:51 -05:00
# pragma mark -
2011-06-01 11:51:53 -05:00
- ( NSString * ) defaultValueForHeader : ( NSString * ) header {
return [ self . defaultHeaders valueForKey : header ] ;
}
- ( void ) setDefaultHeader : ( NSString * ) header value : ( NSString * ) value {
2011-09-26 08:50:41 -05:00
[ self . defaultHeaders setValue : value forKey : header ] ;
2011-06-01 11:51:53 -05:00
}
2011-08-24 15:21:17 -05:00
- ( void ) setAuthorizationHeaderWithUsername : ( NSString * ) username password : ( NSString * ) password {
2011-09-21 11:36:39 -05:00
NSString * basicAuthCredentials = [ NSString stringWithFormat : @ "%@:%@" , username , password ] ;
2012-07-19 22:23:38 -07:00
[ self setDefaultHeader : @ "Authorization" value : [ NSString stringWithFormat : @ "Basic %@" , AFBase64EncodedStringFromString ( basicAuthCredentials ) ] ] ;
2011-08-24 15:21:17 -05:00
}
2011-06-01 11:51:53 -05:00
- ( void ) setAuthorizationHeaderWithToken : ( NSString * ) token {
2012-07-19 22:23:38 -07:00
[ self setDefaultHeader : @ "Authorization" value : [ NSString stringWithFormat : @ "Token token=\" % @ \ "" , token ] ] ;
2011-06-01 11:51:53 -05:00
}
- ( void ) clearAuthorizationHeader {
[ self . defaultHeaders removeObjectForKey : @ "Authorization" ] ;
}
# pragma mark -
2012-08-23 10:16:43 -07:00
- ( NSMutableURLRequest * ) requestWithMethod : ( NSString * ) method
path : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
{
2012-10-14 10:06:50 -07:00
NSParameterAssert ( method ) ;
2013-01-27 12:15:07 -05:00
2012-10-09 08:58:13 -07:00
if ( ! path ) {
path = @ "" ;
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
NSURL * url = [ NSURL URLWithString : path relativeToURL : self . baseURL ] ;
2012-06-26 09:14:52 -07:00
NSMutableURLRequest * request = [ [ NSMutableURLRequest alloc ] initWithURL : url ] ;
2012-07-19 22:23:38 -07:00
[ request setHTTPMethod : method ] ;
[ request setAllHTTPHeaderFields : self . defaultHeaders ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 10:16:43 -07:00
if ( parameters ) {
2012-07-19 22:23:38 -07:00
if ( [ method isEqualToString : @ "GET" ] || [ method isEqualToString : @ "HEAD" ] || [ method isEqualToString : @ "DELETE" ] ) {
url = [ NSURL URLWithString : [ [ url absoluteString ] stringByAppendingFormat : [ path rangeOfString : @ "?" ] . location = = NSNotFound ? @ "?%@" : @ "&%@" , AFQueryStringFromParametersWithEncoding ( parameters , self . stringEncoding ) ] ] ;
[ request setURL : url ] ;
} else {
2012-06-26 09:14:52 -07:00
NSString * charset = ( __bridge NSString * ) CFStringConvertEncodingToIANACharSetName ( CFStringConvertNSStringEncodingToEncoding ( self . stringEncoding ) ) ;
2012-10-31 09:55:18 -07:00
NSError * error = nil ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
switch ( self . parameterEncoding ) {
case AFFormURLParameterEncoding : ;
[ request setValue : [ NSString stringWithFormat : @ "application/x-www-form-urlencoded; charset=%@" , charset ] forHTTPHeaderField : @ "Content-Type" ] ;
[ request setHTTPBody : [ AFQueryStringFromParametersWithEncoding ( parameters , self . stringEncoding ) dataUsingEncoding : self . stringEncoding ] ] ;
break ;
case AFJSONParameterEncoding : ;
[ request setValue : [ NSString stringWithFormat : @ "application/json; charset=%@" , charset ] forHTTPHeaderField : @ "Content-Type" ] ;
2012-10-31 09:55:18 -07:00
[ request setHTTPBody : [ NSJSONSerialization dataWithJSONObject : parameters options : 0 error : & error ] ] ;
2012-07-19 22:23:38 -07:00
break ;
case AFPropertyListParameterEncoding : ;
[ request setValue : [ NSString stringWithFormat : @ "application/x-plist; charset=%@" , charset ] forHTTPHeaderField : @ "Content-Type" ] ;
2012-10-31 09:55:18 -07:00
[ request setHTTPBody : [ NSPropertyListSerialization dataWithPropertyList : parameters format : NSPropertyListXMLFormat_v1 _0 options : 0 error : & error ] ] ;
2012-07-19 22:23:38 -07:00
break ;
}
2013-01-27 12:15:07 -05:00
2012-10-31 09:55:18 -07:00
if ( error ) {
NSLog ( @ "%@ %@: %@" , [ self class ] , NSStringFromSelector ( _cmd ) , error ) ;
}
2012-07-19 22:23:38 -07:00
}
2011-07-27 15:14:15 -05:00
}
2013-01-27 12:15:07 -05:00
2011-07-27 15:14:15 -05:00
return request ;
}
2011-09-21 14:00:05 -05:00
- ( NSMutableURLRequest * ) multipartFormRequestWithMethod : ( NSString * ) method
path : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-09-25 09:56:34 -07:00
constructingBodyWithBlock : ( void ( ^ ) ( id < AFMultipartFormData > formData ) ) block
2011-09-21 14:00:05 -05:00
{
2012-10-14 10:06:50 -07:00
NSParameterAssert ( method ) ;
NSParameterAssert ( ! [ method isEqualToString : @ "GET" ] && ! [ method isEqualToString : @ "HEAD" ] ) ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
NSMutableURLRequest * request = [ self requestWithMethod : method path : path parameters : nil ] ;
2013-01-27 12:15:07 -05:00
2012-09-25 09:56:34 -07:00
__block AFStreamingMultipartFormData * formData = [ [ AFStreamingMultipartFormData alloc ] initWithURLRequest : request stringEncoding : self . stringEncoding ] ;
2013-01-27 12:15:07 -05:00
2012-06-21 22:13:04 +09:00
if ( parameters ) {
2012-08-29 10:49:55 -07:00
for ( AFQueryStringPair * pair in AFQueryStringPairsFromDictionary ( parameters ) ) {
2012-06-21 22:13:04 +09:00
NSData * data = nil ;
2012-08-29 10:49:55 -07:00
if ( [ pair . value isKindOfClass : [ NSData class ] ] ) {
data = pair . value ;
2012-10-05 09:12:00 -07:00
} else if ( [ pair . value isEqual : [ NSNull null ] ] ) {
2012-10-05 15:56:48 +02:00
data = [ NSData data ] ;
2012-06-21 22:13:04 +09:00
} else {
2012-08-29 10:49:55 -07:00
data = [ [ pair . value description ] dataUsingEncoding : self . stringEncoding ] ;
2012-06-21 22:13:04 +09:00
}
2013-01-27 12:15:07 -05:00
2012-06-21 22:13:04 +09:00
if ( data ) {
2012-08-29 10:49:55 -07:00
[ formData appendPartWithFormData : data name : [ pair . field description ] ] ;
2012-06-21 22:13:04 +09:00
}
2012-07-19 22:23:38 -07:00
}
2012-03-19 12:44:06 -04:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
if ( block ) {
block ( formData ) ;
2011-09-21 14:00:05 -05:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return [ formData requestByFinalizingMultipartFormData ] ;
2011-09-21 14:00:05 -05:00
}
2012-08-23 10:16:43 -07:00
- ( AFHTTPRequestOperation * ) HTTPRequestOperationWithRequest : ( NSURLRequest * ) urlRequest
2011-11-07 11:43:19 -06:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
2011-09-26 14:46:46 -05:00
{
2012-07-19 22:23:38 -07:00
AFHTTPRequestOperation * operation = nil ;
2013-03-11 13:15:19 +00:00
2013-03-14 12:46:16 -07:00
for ( NSString * className in self . registeredHTTPOperationClassNames ) {
2013-03-12 10:47:45 +00:00
Class operationClass = NSClassFromString ( className ) ;
if ( operationClass && [ operationClass canProcessRequest : urlRequest ] ) {
operation = [ ( AFHTTPRequestOperation * ) [ operationClass alloc ] initWithRequest : urlRequest ] ;
2013-03-11 13:15:19 +00:00
break ;
2012-07-19 22:23:38 -07:00
}
2011-10-05 15:44:51 -05:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
if ( ! operation ) {
2012-06-26 09:14:52 -07:00
operation = [ [ AFHTTPRequestOperation alloc ] initWithRequest : urlRequest ] ;
2012-07-19 22:23:38 -07:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
[ operation setCompletionBlockWithSuccess : success failure : failure ] ;
2013-01-04 12:52:14 -08:00
operation . credential = self . defaultCredential ;
2013-03-24 02:09:08 -04:00
# ifdef _AFNETWORKING _PIN _SSL _CERTIFICATES _
operation . SSLPinningMode = self . defaultSSLPinningMode ;
# endif
2013-03-25 17:26:28 -05:00
operation . allowInvalidSSLCertificate = self . allowInvalidSSLCertificate ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
return operation ;
2011-10-06 14:33:16 -05:00
}
2012-01-19 16:42:12 -08:00
# pragma mark -
2011-10-06 14:33:16 -05:00
- ( void ) enqueueHTTPRequestOperation : ( AFHTTPRequestOperation * ) operation {
2012-07-19 22:23:38 -07:00
[ self . operationQueue addOperation : operation ] ;
2011-07-27 15:14:15 -05:00
}
2012-10-09 09:10:23 -07:00
- ( void ) cancelAllHTTPOperationsWithMethod : ( NSString * ) method
path : ( NSString * ) path
2012-11-09 14:23:51 -08:00
{
2013-02-09 19:36:37 +01:00
NSString * pathToBeMatched = [ [ [ self requestWithMethod : ( method ? : @ "GET" ) path : path parameters : nil ] URL ] path ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
for ( NSOperation * operation in [ self . operationQueue operations ] ) {
if ( ! [ operation isKindOfClass : [ AFHTTPRequestOperation class ] ] ) {
continue ;
}
2013-01-27 12:15:07 -05:00
2012-10-09 09:10:23 -07:00
BOOL hasMatchingMethod = ! method || [ method isEqualToString : [ [ ( AFHTTPRequestOperation * ) operation request ] HTTPMethod ] ] ;
2013-02-09 19:36:37 +01:00
BOOL hasMatchingPath = [ [ [ [ ( AFHTTPRequestOperation * ) operation request ] URL ] path ] isEqual : pathToBeMatched ] ;
2013-01-27 12:15:07 -05:00
2013-02-09 19:36:37 +01:00
if ( hasMatchingMethod && hasMatchingPath ) {
2012-07-19 22:23:38 -07:00
[ operation cancel ] ;
}
2011-08-14 20:19:59 -05:00
}
}
2012-10-14 10:22:40 -07:00
- ( void ) enqueueBatchOfHTTPRequestOperationsWithRequests : ( NSArray * ) urlRequests
2012-09-03 11:11:24 -07:00
progressBlock : ( void ( ^ ) ( NSUInteger numberOfFinishedOperations , NSUInteger totalNumberOfOperations ) ) progressBlock
2011-12-17 23:49:51 -06:00
completionBlock : ( void ( ^ ) ( NSArray * operations ) ) completionBlock
{
2012-07-19 22:23:38 -07:00
NSMutableArray * mutableOperations = [ NSMutableArray array ] ;
2012-10-14 10:22:40 -07:00
for ( NSURLRequest * request in urlRequests ) {
2012-07-19 22:23:38 -07:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : nil failure : nil ] ;
[ mutableOperations addObject : operation ] ;
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
[ self enqueueBatchOfHTTPRequestOperations : mutableOperations progressBlock : progressBlock completionBlock : completionBlock ] ;
2011-12-17 23:49:51 -06:00
}
2012-08-23 10:16:43 -07:00
- ( void ) enqueueBatchOfHTTPRequestOperations : ( NSArray * ) operations
2012-09-03 11:11:24 -07:00
progressBlock : ( void ( ^ ) ( NSUInteger numberOfFinishedOperations , NSUInteger totalNumberOfOperations ) ) progressBlock
2011-12-17 23:49:51 -06:00
completionBlock : ( void ( ^ ) ( NSArray * operations ) ) completionBlock
{
2012-07-19 22:23:38 -07:00
__block dispatch_group _t dispatchGroup = dispatch_group _create ( ) ;
NSBlockOperation * batchedOperation = [ NSBlockOperation blockOperationWithBlock : ^ {
dispatch_group _notify ( dispatchGroup , dispatch_get _main _queue ( ) , ^ {
if ( completionBlock ) {
completionBlock ( operations ) ;
}
} ) ;
2012-10-05 10:24:28 -07:00
# if ! OS_OBJECT _USE _OBJC
2012-07-19 22:23:38 -07:00
dispatch_release ( dispatchGroup ) ;
2012-09-15 12:41:58 +02:00
# endif
2012-07-19 22:23:38 -07:00
} ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
for ( AFHTTPRequestOperation * operation in operations ) {
2012-06-26 09:14:52 -07:00
AFCompletionBlock originalCompletionBlock = [ operation . completionBlock copy ] ;
2013-02-01 02:45:13 +00:00
__weak __typeof ( & * operation ) weakOperation = operation ;
2012-07-19 22:23:38 -07:00
operation . completionBlock = ^ {
2013-02-01 02:45:13 +00:00
__strong __typeof ( & * weakOperation ) strongOperation = weakOperation ;
dispatch_queue _t queue = strongOperation . successCallbackQueue ? : dispatch_get _main _queue ( ) ;
2012-07-19 22:23:38 -07:00
dispatch_group _async ( dispatchGroup , queue , ^ {
if ( originalCompletionBlock ) {
originalCompletionBlock ( ) ;
}
2013-01-27 12:15:07 -05:00
2012-08-22 11:32:59 -07:00
__block NSUInteger numberOfFinishedOperations = 0 ;
2012-11-29 18:03:34 +11:00
[ operations enumerateObjectsUsingBlock : ^ ( id obj , __unused NSUInteger idx , __unused BOOL * stop ) {
2012-08-22 11:31:49 -07:00
if ( [ ( NSOperation * ) obj isFinished ] ) {
2012-08-22 11:32:59 -07:00
numberOfFinishedOperations + + ;
2012-08-22 11:31:49 -07:00
}
} ] ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
if ( progressBlock ) {
2012-08-22 11:32:59 -07:00
progressBlock ( numberOfFinishedOperations , [ operations count ] ) ;
2012-07-19 22:23:38 -07:00
}
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
dispatch_group _leave ( dispatchGroup ) ;
} ) ;
} ;
2013-01-27 12:15:07 -05:00
2012-07-19 22:23:38 -07:00
dispatch_group _enter ( dispatchGroup ) ;
[ batchedOperation addDependency : operation ] ;
}
2012-11-06 12:03:19 -08:00
[ self . operationQueue addOperations : operations waitUntilFinished : NO ] ;
2012-07-19 22:23:38 -07:00
[ self . operationQueue addOperation : batchedOperation ] ;
2011-12-17 23:49:51 -06:00
}
2011-08-14 20:19:59 -05:00
# pragma mark -
2012-08-23 10:16:43 -07:00
- ( void ) getPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2011-10-24 13:08:58 -05:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
2011-09-26 14:46:46 -05:00
{
2011-06-01 11:51:53 -05:00
NSURLRequest * request = [ self requestWithMethod : @ "GET" path : path parameters : parameters ] ;
2012-07-19 22:23:38 -07:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
2011-06-01 11:51:53 -05:00
}
2012-08-23 10:16:43 -07:00
- ( void ) postPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2011-10-24 13:08:58 -05:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
2011-09-26 14:46:46 -05:00
{
2011-07-27 15:14:15 -05:00
NSURLRequest * request = [ self requestWithMethod : @ "POST" path : path parameters : parameters ] ;
2011-11-07 11:43:19 -06:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
2012-07-19 22:23:38 -07:00
[ self enqueueHTTPRequestOperation : operation ] ;
2011-06-01 11:51:53 -05:00
}
2012-08-23 10:16:43 -07:00
- ( void ) putPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2011-10-24 13:08:58 -05:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
2011-09-26 14:46:46 -05:00
{
2011-07-27 15:14:15 -05:00
NSURLRequest * request = [ self requestWithMethod : @ "PUT" path : path parameters : parameters ] ;
2011-11-07 11:43:19 -06:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
2012-07-19 22:23:38 -07:00
[ self enqueueHTTPRequestOperation : operation ] ;
2011-07-27 15:14:15 -05:00
}
2011-06-01 11:51:53 -05:00
2012-08-23 10:16:43 -07:00
- ( void ) deletePath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2011-10-24 13:08:58 -05:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
2011-09-26 14:46:46 -05:00
{
2011-07-27 15:14:15 -05:00
NSURLRequest * request = [ self requestWithMethod : @ "DELETE" path : path parameters : parameters ] ;
2011-11-07 11:43:19 -06:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
2012-07-19 22:23:38 -07:00
[ self enqueueHTTPRequestOperation : operation ] ;
2011-06-01 11:51:53 -05:00
}
2012-08-23 10:16:43 -07:00
- ( void ) patchPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-02-28 18:18:08 -08:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
2012-07-19 22:23:38 -07:00
NSURLRequest * request = [ self requestWithMethod : @ "PATCH" path : path parameters : parameters ] ;
2012-02-28 18:18:08 -08:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
2012-07-19 22:23:38 -07:00
[ self enqueueHTTPRequestOperation : operation ] ;
2012-02-28 18:18:08 -08:00
}
2012-08-15 10:22:07 -07:00
# pragma mark - NSCoding
- ( id ) initWithCoder : ( NSCoder * ) aDecoder {
NSURL * baseURL = [ aDecoder decodeObjectForKey : @ "baseURL" ] ;
2013-01-27 12:15:07 -05:00
2012-08-15 10:22:07 -07:00
self = [ self initWithBaseURL : baseURL ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-11-09 14:23:51 -08:00
self . stringEncoding = [ aDecoder decodeIntegerForKey : @ "stringEncoding" ] ;
self . parameterEncoding = [ aDecoder decodeIntegerForKey : @ "parameterEncoding" ] ;
2012-08-15 10:22:07 -07:00
self . registeredHTTPOperationClassNames = [ aDecoder decodeObjectForKey : @ "registeredHTTPOperationClassNames" ] ;
self . defaultHeaders = [ aDecoder decodeObjectForKey : @ "defaultHeaders" ] ;
2013-01-27 12:15:07 -05:00
2012-08-15 10:22:07 -07:00
return self ;
}
- ( void ) encodeWithCoder : ( NSCoder * ) aCoder {
[ aCoder encodeObject : self . baseURL forKey : @ "baseURL" ] ;
2012-11-29 17:48:42 +11:00
[ aCoder encodeInteger : ( NSInteger ) self . stringEncoding forKey : @ "stringEncoding" ] ;
2012-08-15 10:22:07 -07:00
[ aCoder encodeInteger : self . parameterEncoding forKey : @ "parameterEncoding" ] ;
[ aCoder encodeObject : self . registeredHTTPOperationClassNames forKey : @ "registeredHTTPOperationClassNames" ] ;
[ aCoder encodeObject : self . defaultHeaders forKey : @ "defaultHeaders" ] ;
}
# pragma mark - NSCopying
- ( id ) copyWithZone : ( NSZone * ) zone {
AFHTTPClient * HTTPClient = [ [ [ self class ] allocWithZone : zone ] initWithBaseURL : self . baseURL ] ;
2013-01-27 12:15:07 -05:00
2012-08-15 10:22:07 -07:00
HTTPClient . stringEncoding = self . stringEncoding ;
HTTPClient . parameterEncoding = self . parameterEncoding ;
2012-09-14 10:30:25 -07:00
HTTPClient . registeredHTTPOperationClassNames = [ self . registeredHTTPOperationClassNames copyWithZone : zone ] ;
HTTPClient . defaultHeaders = [ self . defaultHeaders copyWithZone : zone ] ;
2012-08-16 07:49:50 -07:00
# ifdef _SYSTEMCONFIGURATION _H
2012-08-15 10:22:07 -07:00
HTTPClient . networkReachabilityStatusBlock = self . networkReachabilityStatusBlock ;
2012-08-16 07:49:50 -07:00
# endif
2012-08-15 10:22:07 -07:00
return HTTPClient ;
}
2011-06-01 11:51:53 -05:00
@ end
2011-09-21 14:00:05 -05:00
# pragma mark -
2012-06-05 08:56:27 -07:00
static NSString * const kAFMultipartFormBoundary = @ "Boundary+0xAbCdEfGbOuNdArY" ;
2012-01-18 16:51:58 -08:00
static NSString * const kAFMultipartFormCRLF = @ "\r\n" ;
2013-01-05 22:19:59 -08:00
static NSInteger const kAFStreamToStreamBufferSize = 1024 * 1024 ; // 1 meg default
2012-06-12 22:46:39 -07:00
2011-11-29 14:16:48 -08:00
static inline NSString * AFMultipartFormInitialBoundary ( ) {
2012-07-19 22:23:38 -07:00
return [ NSString stringWithFormat : @ "--%@%@" , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
2011-11-29 14:16:48 -08:00
}
2011-09-26 12:51:20 -05:00
static inline NSString * AFMultipartFormEncapsulationBoundary ( ) {
2012-07-19 22:23:38 -07:00
return [ NSString stringWithFormat : @ "%@--%@%@" , kAFMultipartFormCRLF , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
2011-09-26 12:51:20 -05:00
}
2011-09-21 14:00:05 -05:00
2011-09-26 12:51:20 -05:00
static inline NSString * AFMultipartFormFinalBoundary ( ) {
2012-07-19 22:23:38 -07:00
return [ NSString stringWithFormat : @ "%@--%@--%@" , kAFMultipartFormCRLF , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
2012-06-30 16:32:11 -07:00
}
2012-08-23 14:33:04 -07:00
static inline NSString * AFContentTypeForPathExtension ( NSString * extension ) {
2012-09-25 09:56:34 -07:00
# ifdef __UTTYPE __
2012-09-25 11:06:03 -07:00
NSString * UTI = ( __bridge _transfer NSString * ) UTTypeCreatePreferredIdentifierForTag ( kUTTagClassFilenameExtension , ( __bridge CFStringRef ) extension , NULL ) ;
2013-02-09 11:49:06 -05:00
NSString * contentType = ( __bridge _transfer NSString * ) UTTypeCopyPreferredTagWithClass ( ( __bridge CFStringRef ) UTI , kUTTagClassMIMEType ) ;
if ( ! contentType ) {
return @ "application/octet-stream" ;
} else {
return contentType ;
}
2012-09-25 09:56:34 -07:00
# else
return @ "application/octet-stream" ;
# endif
2012-08-23 14:33:04 -07:00
}
2012-09-30 17:38:07 -07:00
NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16 ;
2012-10-04 23:03:54 +02:00
NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2 ;
2012-09-30 17:38:07 -07:00
2012-08-23 16:21:14 -07:00
@ interface AFHTTPBodyPart : NSObject
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
2012-10-09 09:26:50 -07:00
@ property ( nonatomic , strong ) NSDictionary * headers ;
2013-01-05 23:40:24 -08:00
@ property ( nonatomic , strong ) id body ;
2012-08-23 16:21:14 -07:00
@ property ( nonatomic , assign ) unsigned long long bodyContentLength ;
2013-01-05 23:40:24 -08:00
@ property ( nonatomic , readonly ) NSInputStream * inputStream ;
2012-08-23 14:33:04 -07:00
2012-08-23 16:21:14 -07:00
@ property ( nonatomic , assign ) BOOL hasInitialBoundary ;
@ property ( nonatomic , assign ) BOOL hasFinalBoundary ;
2012-11-30 18:13:43 +11:00
@ property ( nonatomic , readonly , getter = hasBytesAvailable ) BOOL bytesAvailable ;
@ property ( nonatomic , readonly ) unsigned long long contentLength ;
2012-08-23 16:21:14 -07:00
2013-01-05 22:19:59 -08:00
- ( NSInteger ) read : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length ;
2012-08-23 16:21:14 -07:00
@ end
2013-02-21 14:35:41 -05:00
@ interface AFMultipartBodyStreamProvider : NSObject
2013-03-24 01:30:46 -04:00
@ property ( nonatomic , assign ) NSUInteger bufferLength ;
2012-09-30 17:38:07 -07:00
@ property ( nonatomic , assign ) NSTimeInterval delay ;
2013-03-24 01:42:50 -04:00
@ property ( nonatomic , readonly ) NSInputStream * inputStream ;
2012-11-30 18:13:43 +11:00
@ property ( nonatomic , readonly ) unsigned long long contentLength ;
@ property ( nonatomic , readonly , getter = isEmpty ) BOOL empty ;
2012-08-23 14:33:04 -07:00
2012-09-25 11:06:03 -07:00
- ( id ) initWithStringEncoding : ( NSStringEncoding ) encoding ;
- ( void ) setInitialAndFinalBoundaries ;
- ( void ) appendHTTPBodyPart : ( AFHTTPBodyPart * ) bodyPart ;
2012-08-23 14:33:04 -07:00
@ end
2012-06-30 16:32:11 -07:00
2012-08-23 16:21:14 -07:00
# pragma mark -
2012-09-25 11:06:03 -07:00
@ interface AFStreamingMultipartFormData ( )
@ property ( readwrite , nonatomic , copy ) NSMutableURLRequest * request ;
2013-02-21 14:35:41 -05:00
@ property ( readwrite , nonatomic , strong ) AFMultipartBodyStreamProvider * bodyStream ;
2012-09-25 11:06:03 -07:00
@ property ( readwrite , nonatomic , assign ) NSStringEncoding stringEncoding ;
@ end
2012-08-23 14:33:04 -07:00
@ implementation AFStreamingMultipartFormData
2012-06-05 08:56:27 -07:00
@ synthesize request = _request ;
2012-08-23 14:33:04 -07:00
@ synthesize bodyStream = _bodyStream ;
2011-09-21 14:00:05 -05:00
@ synthesize stringEncoding = _stringEncoding ;
2012-10-14 10:22:40 -07:00
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) urlRequest
2012-08-23 10:16:43 -07:00
stringEncoding : ( NSStringEncoding ) encoding
2012-06-05 08:56:27 -07:00
{
2012-08-23 10:16:43 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-10-14 10:22:40 -07:00
self . request = urlRequest ;
2012-08-23 10:16:43 -07:00
self . stringEncoding = encoding ;
2013-02-21 14:35:41 -05:00
self . bodyStream = [ [ AFMultipartBodyStreamProvider alloc ] initWithStringEncoding : encoding ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 10:16:43 -07:00
return self ;
2011-09-21 14:00:05 -05:00
}
2012-09-26 11:39:28 -07:00
- ( BOOL ) appendPartWithFileURL : ( NSURL * ) fileURL
name : ( NSString * ) name
error : ( NSError * __autoreleasing * ) error
{
2012-10-14 10:06:50 -07:00
NSParameterAssert ( fileURL ) ;
NSParameterAssert ( name ) ;
2013-01-27 12:15:07 -05:00
2013-02-15 21:13:09 +01:00
NSString * fileName = [ fileURL lastPathComponent ] ;
NSString * mimeType = AFContentTypeForPathExtension ( [ fileURL pathExtension ] ) ;
2013-03-14 12:48:05 -07:00
2013-02-15 21:13:09 +01:00
return [ self appendPartWithFileURL : fileURL name : name fileName : fileName mimeType : mimeType error : error ] ;
}
- ( BOOL ) appendPartWithFileURL : ( NSURL * ) fileURL
name : ( NSString * ) name
fileName : ( NSString * ) fileName
mimeType : ( NSString * ) mimeType
2013-03-14 12:48:05 -07:00
error : ( NSError * __autoreleasing * ) error
2013-02-15 21:13:09 +01:00
{
NSParameterAssert ( fileURL ) ;
NSParameterAssert ( name ) ;
NSParameterAssert ( fileName ) ;
NSParameterAssert ( mimeType ) ;
2012-09-26 11:39:28 -07:00
if ( ! [ fileURL isFileURL ] ) {
2012-11-14 17:44:11 +01:00
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedStringFromTable ( @ "Expected URL to be a file URL" , @ "AFNetworking" , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
2012-09-26 11:39:28 -07:00
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
2013-01-27 12:15:07 -05:00
2012-09-26 11:39:28 -07:00
return NO ;
} else if ( [ fileURL checkResourceIsReachableAndReturnError : error ] = = NO ) {
2012-11-14 17:44:11 +01:00
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedStringFromTable ( @ "File URL not reachable." , @ "AFNetworking" , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
2012-09-26 11:39:28 -07:00
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
2013-01-27 12:15:07 -05:00
2012-09-26 11:39:28 -07:00
return NO ;
}
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
NSMutableDictionary * mutableHeaders = [ NSMutableDictionary dictionary ] ;
2013-02-15 21:13:09 +01:00
[ mutableHeaders setValue : [ NSString stringWithFormat : @ "form-data; name=\" % @ \ "; filename=\" % @ \ "" , name , fileName ] forKey : @ "Content-Disposition" ] ;
[ mutableHeaders setValue : mimeType forKey : @ "Content-Type" ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
2013-01-05 23:40:24 -08:00
bodyPart . body = fileURL ;
2013-01-05 15:10:47 -05:00
2012-09-26 11:39:28 -07:00
NSDictionary * fileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : [ fileURL path ] error : nil ] ;
bodyPart . bodyContentLength = [ [ fileAttributes objectForKey : NSFileSize ] unsignedLongLongValue ] ;
2013-01-27 12:15:07 -05:00
2012-09-25 11:06:03 -07:00
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
2013-01-27 12:15:07 -05:00
2012-09-26 11:39:28 -07:00
return YES ;
2012-08-23 10:16:43 -07:00
}
2013-03-24 02:13:37 -04:00
- ( void ) appendPartWithInputStream : ( NSInputStream * ) inputStream
name : ( NSString * ) name
fileName : ( NSString * ) fileName
length : ( unsigned long long ) length
mimeType : ( NSString * ) mimeType
{
NSParameterAssert ( name ) ;
NSParameterAssert ( fileName ) ;
NSParameterAssert ( mimeType ) ;
NSMutableDictionary * mutableHeaders = [ NSMutableDictionary dictionary ] ;
[ mutableHeaders setValue : [ NSString stringWithFormat : @ "form-data; name=\" % @ \ "; filename=\" % @ \ "" , name , fileName ] forKey : @ "Content-Disposition" ] ;
[ mutableHeaders setValue : mimeType forKey : @ "Content-Type" ] ;
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
bodyPart . body = inputStream ;
bodyPart . bodyContentLength = length ;
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
}
2012-08-23 16:21:14 -07:00
- ( void ) appendPartWithFileData : ( NSData * ) data
name : ( NSString * ) name
fileName : ( NSString * ) fileName
mimeType : ( NSString * ) mimeType
2012-09-25 10:19:15 -07:00
{
2012-10-14 10:06:50 -07:00
NSParameterAssert ( name ) ;
NSParameterAssert ( fileName ) ;
NSParameterAssert ( mimeType ) ;
2013-01-27 12:15:07 -05:00
2012-08-23 16:21:14 -07:00
NSMutableDictionary * mutableHeaders = [ NSMutableDictionary dictionary ] ;
[ mutableHeaders setValue : [ NSString stringWithFormat : @ "form-data; name=\" % @ \ "; filename=\" % @ \ "" , name , fileName ] forKey : @ "Content-Disposition" ] ;
[ mutableHeaders setValue : mimeType forKey : @ "Content-Type" ] ;
2013-01-27 12:15:07 -05:00
2012-10-03 08:37:25 -07:00
[ self appendPartWithHeaders : mutableHeaders body : data ] ;
2012-08-23 10:16:43 -07:00
}
2012-09-26 11:39:28 -07:00
- ( void ) appendPartWithFormData : ( NSData * ) data
name : ( NSString * ) name
2012-08-23 16:21:14 -07:00
{
2012-10-14 10:06:50 -07:00
NSParameterAssert ( name ) ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
NSMutableDictionary * mutableHeaders = [ NSMutableDictionary dictionary ] ;
2012-09-26 11:39:28 -07:00
[ mutableHeaders setValue : [ NSString stringWithFormat : @ "form-data; name=\" % @ \ "" , name ] forKey : @ "Content-Disposition" ] ;
2013-01-27 12:15:07 -05:00
2012-10-03 08:37:25 -07:00
[ self appendPartWithHeaders : mutableHeaders body : data ] ;
}
- ( void ) appendPartWithHeaders : ( NSDictionary * ) headers
body : ( NSData * ) body
{
2012-12-17 10:31:00 -08:00
NSParameterAssert ( body ) ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
2012-10-03 08:37:25 -07:00
bodyPart . headers = headers ;
bodyPart . bodyContentLength = [ body length ] ;
2013-01-05 23:40:24 -08:00
bodyPart . body = body ;
2013-01-27 12:15:07 -05:00
2012-09-25 11:06:03 -07:00
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
2012-06-30 16:32:11 -07:00
}
2012-09-30 17:38:07 -07:00
- ( void ) throttleBandwidthWithPacketSize : ( NSUInteger ) numberOfBytes
delay : ( NSTimeInterval ) delay
{
2013-03-24 01:30:46 -04:00
self . bodyStream . bufferLength = numberOfBytes ;
2012-09-30 17:38:07 -07:00
self . bodyStream . delay = delay ;
}
2012-08-23 14:33:04 -07:00
- ( NSMutableURLRequest * ) requestByFinalizingMultipartFormData {
if ( [ self . bodyStream isEmpty ] ) {
return self . request ;
2012-08-23 10:16:43 -07:00
}
2013-01-27 12:15:07 -05:00
2012-09-25 11:06:03 -07:00
// Reset the initial and final boundaries to ensure correct Content - Length
2012-09-25 03:33:51 +08:00
[ self . bodyStream setInitialAndFinalBoundaries ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
[ self . request setValue : [ NSString stringWithFormat : @ "multipart/form-data; boundary=%@" , kAFMultipartFormBoundary ] forHTTPHeaderField : @ "Content-Type" ] ;
[ self . request setValue : [ NSString stringWithFormat : @ "%llu" , [ self . bodyStream contentLength ] ] forHTTPHeaderField : @ "Content-Length" ] ;
2013-02-21 14:35:41 -05:00
[ self . request setHTTPBodyStream : self . bodyStream . inputStream ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
return self . request ;
2012-08-23 10:16:43 -07:00
}
2012-07-19 22:23:38 -07:00
2012-08-23 14:33:04 -07:00
@ end
2012-08-23 10:16:43 -07:00
2012-09-25 11:06:03 -07:00
# pragma mark -
2013-02-21 14:35:41 -05:00
@ interface AFMultipartBodyStreamProvider ( ) < NSCopying , NSStreamDelegate >
2012-09-25 11:06:03 -07:00
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
2012-10-09 09:26:50 -07:00
@ property ( nonatomic , strong ) NSMutableArray * HTTPBodyParts ;
@ property ( nonatomic , strong ) NSEnumerator * HTTPBodyPartEnumerator ;
@ property ( nonatomic , strong ) AFHTTPBodyPart * currentHTTPBodyPart ;
2013-03-24 01:23:38 -04:00
@ property ( nonatomic , strong ) NSInputStream * inputStream ;
@ property ( nonatomic , strong ) NSOutputStream * outputStream ;
@ property ( nonatomic , strong ) NSMutableData * buffer ;
2012-09-25 11:06:03 -07:00
@ end
2012-07-19 22:23:38 -07:00
2013-03-24 01:30:46 -04:00
static const NSUInteger AFMultipartBodyStreamProviderDefaultBufferLength = 4096 ;
2013-02-21 14:35:41 -05:00
@ implementation AFMultipartBodyStreamProvider {
2013-03-24 01:23:38 -04:00
@ private
// Workaround for stream delegates being weakly referenced , but otherwise unowned
__strong id _self ;
2013-02-21 14:35:41 -05:00
}
2012-08-23 14:33:04 -07:00
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize HTTPBodyParts = _HTTPBodyParts ;
@ synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator ;
@ synthesize currentHTTPBodyPart = _currentHTTPBodyPart ;
2013-03-24 01:23:38 -04:00
@ synthesize inputStream = _inputStream ;
@ synthesize outputStream = _outputStream ;
@ synthesize buffer = _buffer ;
2013-03-24 01:30:46 -04:00
@ synthesize bufferLength = _numberOfBytesInPacket ;
2012-09-30 17:38:07 -07:00
@ synthesize delay = _delay ;
2012-08-23 10:16:43 -07:00
2012-08-23 14:33:04 -07:00
- ( id ) initWithStringEncoding : ( NSStringEncoding ) encoding {
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-11-09 14:23:51 -08:00
self . stringEncoding = encoding ;
2012-08-23 16:21:14 -07:00
self . HTTPBodyParts = [ NSMutableArray array ] ;
2013-03-24 01:30:46 -04:00
self . bufferLength = NSIntegerMax ;
2013-02-21 14:35:41 -05:00
2013-03-24 01:23:38 -04:00
self . buffer = [ [ NSMutableData alloc ] init ] ;
2013-03-24 01:30:46 -04:00
self . bufferLength = AFMultipartBodyStreamProviderDefaultBufferLength ;
2013-02-21 14:35:41 -05:00
2012-08-23 14:33:04 -07:00
return self ;
2011-09-21 14:00:05 -05:00
}
2013-02-21 14:35:41 -05:00
- ( void ) dealloc {
_outputStream . delegate = nil ;
}
2012-09-25 03:33:51 +08:00
- ( void ) setInitialAndFinalBoundaries {
2012-09-25 10:33:46 -07:00
if ( [ self . HTTPBodyParts count ] > 0 ) {
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
bodyPart . hasInitialBoundary = NO ;
bodyPart . hasFinalBoundary = NO ;
2012-09-25 03:33:51 +08:00
}
2013-01-27 12:15:07 -05:00
2012-09-25 03:33:51 +08:00
[ [ self . HTTPBodyParts objectAtIndex : 0 ] setHasInitialBoundary : YES ] ;
[ [ self . HTTPBodyParts lastObject ] setHasFinalBoundary : YES ] ;
}
}
2012-09-25 11:06:03 -07:00
- ( void ) appendHTTPBodyPart : ( AFHTTPBodyPart * ) bodyPart {
[ self . HTTPBodyParts addObject : bodyPart ] ;
}
2013-02-21 14:35:41 -05:00
- ( NSInputStream * ) inputStream {
2013-03-24 01:23:38 -04:00
if ( _inputStream = = nil ) {
2013-02-21 14:35:41 -05:00
CFReadStreamRef readStream ;
CFWriteStreamRef writeStream ;
2013-03-24 01:30:46 -04:00
CFStreamCreateBoundPair ( NULL , & readStream , & writeStream , self . bufferLength ) ;
2013-02-21 14:35:41 -05:00
_inputStream = CFBridgingRelease ( readStream ) ;
_outputStream = CFBridgingRelease ( writeStream ) ;
_outputStream . delegate = self ;
2013-03-24 01:23:38 -04:00
if ( [ NSThread isMainThread ] ) {
[ _outputStream scheduleInRunLoop : [ NSRunLoop currentRunLoop ] forMode : NSDefaultRunLoopMode ] ;
} else {
2013-02-22 17:36:57 -05:00
dispatch_sync ( dispatch_get _main _queue ( ) , ^ {
2013-03-24 01:23:38 -04:00
[ _outputStream scheduleInRunLoop : [ NSRunLoop currentRunLoop ] forMode : NSDefaultRunLoopMode ] ;
2013-02-22 17:36:57 -05:00
} ) ;
}
2013-02-21 14:35:41 -05:00
[ _outputStream open ] ;
2013-03-24 01:23:38 -04:00
_self = self ;
2013-02-21 14:35:41 -05:00
}
return _inputStream ;
}
2012-09-25 10:33:46 -07:00
- ( BOOL ) isEmpty {
return [ self . HTTPBodyParts count ] = = 0 ;
}
2013-02-21 14:35:41 -05:00
# pragma mark - NSStreamDelegate
2012-09-25 10:33:46 -07:00
2013-03-24 01:23:38 -04:00
- ( void ) stream : ( NSStream * ) stream
handleEvent : ( NSStreamEvent ) eventCode
{
if ( eventCode & NSStreamEventHasSpaceAvailable ) {
2013-02-21 14:35:41 -05:00
[ self handleOutputStreamSpaceAvailable ] ;
2012-09-25 10:33:46 -07:00
}
2013-02-21 14:35:41 -05:00
}
2013-01-27 12:15:07 -05:00
2013-02-21 14:35:41 -05:00
- ( void ) handleOutputStreamSpaceAvailable {
2013-03-24 01:23:38 -04:00
while ( [ _outputStream hasSpaceAvailable ] ) {
if ( [ _buffer length ] > 0 ) {
NSInteger numberOfBytesWritten = [ _outputStream write : [ _buffer bytes ] maxLength : [ _buffer length ] ] ;
if ( numberOfBytesWritten < 0 ) {
2013-02-21 14:35:41 -05:00
[ self close ] ;
return ;
2012-09-25 10:33:46 -07:00
}
2013-03-24 01:23:38 -04:00
[ _buffer replaceBytesInRange : NSMakeRange ( 0 , numberOfBytesWritten ) withBytes : NULL length : 0 ] ;
2012-09-25 10:33:46 -07:00
} else {
2013-03-24 01:23:38 -04:00
if ( ! self . currentHTTPBodyPart ) {
if ( ! self . HTTPBodyPartEnumerator ) {
2013-02-21 14:35:41 -05:00
self . HTTPBodyPartEnumerator = [ self . HTTPBodyParts objectEnumerator ] ;
}
self . currentHTTPBodyPart = [ self . HTTPBodyPartEnumerator nextObject ] ;
}
2013-03-24 01:23:38 -04:00
if ( ! self . currentHTTPBodyPart ) {
2013-02-21 14:35:41 -05:00
[ self close ] ;
return ;
2012-09-30 17:38:07 -07:00
}
2013-02-21 14:35:41 -05:00
2013-03-24 01:30:46 -04:00
[ _buffer setLength : self . bufferLength ] ;
2013-03-24 01:23:38 -04:00
NSInteger numberOfBytesRead = [ self . currentHTTPBodyPart read : [ _buffer mutableBytes ] maxLength : [ _buffer length ] ] ;
if ( numberOfBytesRead < 0 ) {
2013-02-21 14:35:41 -05:00
[ self close ] ;
return ;
}
2013-03-24 01:23:38 -04:00
[ _buffer setLength : numberOfBytesRead ] ;
2013-03-24 01:30:46 -04:00
2013-03-24 01:23:38 -04:00
if ( numberOfBytesRead = = 0 ) {
2013-02-21 14:35:41 -05:00
self . currentHTTPBodyPart = nil ;
2013-03-24 01:30:46 -04:00
}
if ( self . delay > 0.0 f ) {
[ NSThread sleepForTimeInterval : self . delay ] ;
}
2012-09-25 10:33:46 -07:00
}
}
2012-06-30 16:32:11 -07:00
}
2012-08-23 10:16:43 -07:00
- ( void ) close {
2013-02-21 14:35:41 -05:00
[ _outputStream close ] ;
_outputStream . delegate = nil ;
2013-03-24 01:23:38 -04:00
_self = nil ;
2012-06-30 16:32:11 -07:00
}
2012-08-23 16:21:14 -07:00
- ( unsigned long long ) contentLength {
unsigned long long length = 0 ;
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
length + = [ bodyPart contentLength ] ;
}
2013-01-27 12:15:07 -05:00
2012-08-23 16:21:14 -07:00
return length ;
}
2013-01-05 23:40:24 -08:00
# pragma mark - NSCopying
2013-03-24 01:23:38 -04:00
- ( id ) copyWithZone : ( NSZone * ) zone {
2013-02-21 14:35:41 -05:00
AFMultipartBodyStreamProvider * bodyStreamCopy = [ [ [ self class ] allocWithZone : zone ] initWithStringEncoding : self . stringEncoding ] ;
2013-01-05 23:40:24 -08:00
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
[ bodyStreamCopy appendHTTPBodyPart : [ bodyPart copy ] ] ;
}
[ bodyStreamCopy setInitialAndFinalBoundaries ] ;
return bodyStreamCopy ;
}
2012-08-23 14:33:04 -07:00
@ end
# pragma mark -
2012-10-09 17:38:08 -07:00
typedef enum {
2013-02-21 14:35:41 -05:00
AFInitialPhase = 0 ,
2012-08-23 16:21:14 -07:00
AFEncapsulationBoundaryPhase = 1 ,
AFHeaderPhase = 2 ,
AFBodyPhase = 3 ,
AFFinalBoundaryPhase = 4 ,
2013-02-21 14:35:41 -05:00
AFCompletedPhase = 5 ,
2012-10-09 17:38:08 -07:00
} AFHTTPBodyPartReadPhase ;
2012-08-23 16:21:14 -07:00
2013-01-05 15:10:47 -05:00
@ interface AFHTTPBodyPart ( ) < NSCopying > {
2012-08-23 14:33:04 -07:00
AFHTTPBodyPartReadPhase _phase ;
2013-01-05 15:10:47 -05:00
NSInputStream * _inputStream ;
2012-08-23 14:33:04 -07:00
unsigned long long _phaseReadOffset ;
}
2012-08-23 16:21:14 -07:00
- ( BOOL ) transitionToNextPhase ;
2013-01-05 22:19:59 -08:00
- ( NSInteger ) readData : ( NSData * ) data
intoBuffer : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length ;
2012-08-23 16:21:14 -07:00
@ end
@ implementation AFHTTPBodyPart
2012-08-23 14:33:04 -07:00
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize headers = _headers ;
2013-01-05 23:40:24 -08:00
@ synthesize body = _body ;
2012-08-23 14:33:04 -07:00
@ synthesize bodyContentLength = _bodyContentLength ;
2012-10-01 10:45:43 -07:00
@ synthesize hasInitialBoundary = _hasInitialBoundary ;
@ synthesize hasFinalBoundary = _hasFinalBoundary ;
2012-08-23 14:33:04 -07:00
- ( id ) init {
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
[ self transitionToNextPhase ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
return self ;
}
2012-09-25 10:19:15 -07:00
- ( void ) dealloc {
if ( _inputStream ) {
[ _inputStream close ] ;
_inputStream = nil ;
2012-11-09 14:23:51 -08:00
}
2012-08-23 14:33:04 -07:00
}
2013-01-05 15:10:47 -05:00
- ( NSInputStream * ) inputStream {
2013-01-05 23:40:24 -08:00
if ( ! _inputStream ) {
if ( [ self . body isKindOfClass : [ NSData class ] ] ) {
_inputStream = [ NSInputStream inputStreamWithData : self . body ] ;
} else if ( [ self . body isKindOfClass : [ NSURL class ] ] ) {
_inputStream = [ NSInputStream inputStreamWithURL : self . body ] ;
2013-03-24 01:42:29 -04:00
} else if ( [ self . body isKindOfClass : [ NSInputStream class ] ] ) {
2013-03-18 17:02:41 -04:00
_inputStream = self . body ;
2013-01-05 23:40:24 -08:00
}
2013-01-05 15:10:47 -05:00
}
return _inputStream ;
}
2012-08-23 14:33:04 -07:00
- ( NSString * ) stringForHeaders {
NSMutableString * headerString = [ NSMutableString string ] ;
for ( NSString * field in [ self . headers allKeys ] ) {
[ headerString appendString : [ NSString stringWithFormat : @ "%@: %@%@" , field , [ self . headers valueForKey : field ] , kAFMultipartFormCRLF ] ] ;
}
2012-09-25 03:33:51 +08:00
[ headerString appendString : kAFMultipartFormCRLF ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
return [ NSString stringWithString : headerString ] ;
}
2012-06-30 16:32:11 -07:00
2012-08-23 14:33:04 -07:00
- ( unsigned long long ) contentLength {
unsigned long long length = 0 ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
NSData * encapsulationBoundaryData = [ ( [ self hasInitialBoundary ] ? AFMultipartFormInitialBoundary ( ) : AFMultipartFormEncapsulationBoundary ( ) ) dataUsingEncoding : self . stringEncoding ] ;
length + = [ encapsulationBoundaryData length ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
NSData * headersData = [ [ self stringForHeaders ] dataUsingEncoding : self . stringEncoding ] ;
length + = [ headersData length ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
length + = _bodyContentLength ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
NSData * closingBoundaryData = ( [ self hasFinalBoundary ] ? [ AFMultipartFormFinalBoundary ( ) dataUsingEncoding : self . stringEncoding ] : [ NSData data ] ) ;
length + = [ closingBoundaryData length ] ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
return length ;
}
2012-09-25 10:33:46 -07:00
- ( BOOL ) hasBytesAvailable {
2013-02-07 14:19:54 -08:00
// Allows ` read : maxLength : ` to be called again if ` AFMultipartFormFinalBoundary` doesn ' t fit into the available buffer
2012-11-09 14:23:51 -08:00
if ( _phase = = AFFinalBoundaryPhase ) {
return YES ;
}
2013-01-27 12:15:07 -05:00
2013-02-04 00:21:42 +01:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcovered-switch-default"
2012-09-25 10:33:46 -07:00
switch ( self . inputStream . streamStatus ) {
2012-10-02 09:41:57 -07:00
case NSStreamStatusNotOpen :
case NSStreamStatusOpening :
2012-10-01 10:45:43 -07:00
case NSStreamStatusOpen :
case NSStreamStatusReading :
case NSStreamStatusWriting :
return YES ;
2012-09-25 10:33:46 -07:00
case NSStreamStatusAtEnd :
case NSStreamStatusClosed :
case NSStreamStatusError :
2013-01-24 17:01:25 -05:00
default :
2012-09-25 10:33:46 -07:00
return NO ;
}
2013-02-04 00:21:42 +01:00
# pragma clang diagnostic pop
2012-09-25 10:33:46 -07:00
}
2012-08-23 14:33:04 -07:00
2013-01-05 22:19:59 -08:00
- ( NSInteger ) read : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length
{
2012-08-23 14:33:04 -07:00
NSInteger bytesRead = 0 ;
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
if ( _phase = = AFEncapsulationBoundaryPhase ) {
NSData * encapsulationBoundaryData = [ ( [ self hasInitialBoundary ] ? AFMultipartFormInitialBoundary ( ) : AFMultipartFormEncapsulationBoundary ( ) ) dataUsingEncoding : self . stringEncoding ] ;
2012-11-29 17:48:42 +11:00
bytesRead + = [ self readData : encapsulationBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
if ( _phase = = AFHeaderPhase ) {
NSData * headersData = [ [ self stringForHeaders ] dataUsingEncoding : self . stringEncoding ] ;
2012-11-29 17:48:42 +11:00
bytesRead + = [ self readData : headersData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
if ( _phase = = AFBodyPhase ) {
if ( [ self . inputStream hasBytesAvailable ] ) {
2012-11-29 17:48:42 +11:00
bytesRead + = [ self . inputStream read : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
2012-08-23 16:21:14 -07:00
}
2013-01-27 12:15:07 -05:00
2012-08-23 16:21:14 -07:00
if ( ! [ self . inputStream hasBytesAvailable ] ) {
2012-08-23 14:33:04 -07:00
[ self transitionToNextPhase ] ;
}
}
2013-01-27 12:15:07 -05:00
2012-08-23 14:33:04 -07:00
if ( _phase = = AFFinalBoundaryPhase ) {
NSData * closingBoundaryData = ( [ self hasFinalBoundary ] ? [ AFMultipartFormFinalBoundary ( ) dataUsingEncoding : self . stringEncoding ] : [ NSData data ] ) ;
2012-11-29 17:48:42 +11:00
bytesRead + = [ self readData : closingBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
2012-12-27 16:23:27 -05:00
2012-08-23 14:33:04 -07:00
return bytesRead ;
}
2012-09-25 10:33:46 -07:00
- ( NSInteger ) readData : ( NSData * ) data
intoBuffer : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length
{
2012-11-01 02:42:14 +08:00
NSRange range = NSMakeRange ( ( NSUInteger ) _phaseReadOffset , MIN ( [ data length ] - ( ( NSUInteger ) _phaseReadOffset ) , length ) ) ;
2012-09-25 10:33:46 -07:00
[ data getBytes : buffer range : range ] ;
2013-01-27 12:15:07 -05:00
2012-09-25 10:33:46 -07:00
_phaseReadOffset + = range . length ;
2013-01-27 12:15:07 -05:00
2012-11-01 02:42:14 +08:00
if ( ( ( NSUInteger ) _phaseReadOffset ) >= [ data length ] ) {
2012-09-25 10:33:46 -07:00
[ self transitionToNextPhase ] ;
}
2013-01-27 12:15:07 -05:00
2012-11-29 17:48:42 +11:00
return ( NSInteger ) range . length ;
2012-09-25 10:33:46 -07:00
}
- ( BOOL ) transitionToNextPhase {
if ( ! [ [ NSThread currentThread ] isMainThread ] ) {
[ self performSelectorOnMainThread : @ selector ( transitionToNextPhase ) withObject : nil waitUntilDone : YES ] ;
return YES ;
}
2013-01-27 12:15:07 -05:00
2013-02-01 02:39:02 +00:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcovered-switch-default"
2012-09-25 10:33:46 -07:00
switch ( _phase ) {
2013-02-21 14:35:41 -05:00
case AFInitialPhase :
_phase = AFEncapsulationBoundaryPhase ;
break ;
2012-09-25 10:33:46 -07:00
case AFEncapsulationBoundaryPhase :
_phase = AFHeaderPhase ;
break ;
case AFHeaderPhase :
[ self . inputStream scheduleInRunLoop : [ NSRunLoop currentRunLoop ] forMode : NSRunLoopCommonModes ] ;
[ self . inputStream open ] ;
_phase = AFBodyPhase ;
break ;
case AFBodyPhase :
[ self . inputStream close ] ;
_phase = AFFinalBoundaryPhase ;
break ;
2012-11-30 18:14:26 +11:00
case AFFinalBoundaryPhase :
2013-02-21 14:35:41 -05:00
case AFCompletedPhase :
2013-01-30 16:25:56 +00:00
default :
2013-02-21 14:35:41 -05:00
_phase = AFCompletedPhase ;
2012-09-25 10:33:46 -07:00
break ;
2012-08-23 14:33:04 -07:00
}
2012-09-25 10:33:46 -07:00
_phaseReadOffset = 0 ;
2013-02-01 02:39:02 +00:00
# pragma clang diagnostic pop
2013-01-27 12:15:07 -05:00
2012-09-25 10:33:46 -07:00
return YES ;
2012-08-23 14:33:04 -07:00
}
2013-01-05 23:40:24 -08:00
# pragma mark - NSCopying
- ( id ) copyWithZone : ( NSZone * ) zone {
AFHTTPBodyPart * bodyPart = [ [ [ self class ] allocWithZone : zone ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = self . headers ;
bodyPart . bodyContentLength = self . bodyContentLength ;
bodyPart . body = self . body ;
return bodyPart ;
}
2012-08-23 14:33:04 -07:00
@ end