2012-07-18 12:17:55 -07:00
// AFHTTPClient . m
//
// Copyright ( c ) 2011 Gowalla ( http : // gowalla . com / )
2013-09-25 17:43:00 -07:00
//
2012-07-18 12:17:55 -07: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 :
2013-09-25 17:43:00 -07:00
//
2012-07-18 12:17:55 -07:00
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software .
2013-09-25 17:43:00 -07:00
//
2012-07-18 12:17:55 -07: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 .
# import < Foundation / Foundation . h >
# import "AFHTTPClient.h"
# import "AFHTTPRequestOperation.h"
# import < Availability . h >
# ifdef _SYSTEMCONFIGURATION _H
# import < netinet / in . h >
# import < netinet6 / in6 . h >
# import < arpa / inet . h >
# import < ifaddrs . h >
# import < netdb . h >
# endif
2013-09-25 17:43:00 -07:00
# if defined ( __IPHONE _OS _VERSION _MIN _REQUIRED )
# import < UIKit / UIKit . h >
# endif
2012-07-18 12:17:55 -07:00
# ifdef _SYSTEMCONFIGURATION _H
2013-09-25 17:43:00 -07:00
NSString * const AFNetworkingReachabilityDidChangeNotification = @ "com.alamofire.networking.reachability.change" ;
NSString * const AFNetworkingReachabilityNotificationStatusItem = @ "AFNetworkingReachabilityNotificationStatusItem" ;
2012-07-18 12:17:55 -07:00
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef ;
typedef void ( ^ AFNetworkReachabilityStatusBlock ) ( AFNetworkReachabilityStatus status ) ;
# else
typedef id AFNetworkReachabilityRef ;
# endif
typedef void ( ^ AFCompletionBlock ) ( void ) ;
static NSString * AFBase64EncodedStringFromString ( NSString * string ) {
NSData * data = [ NSData dataWithBytes : [ string UTF8String ] length : [ string lengthOfBytesUsingEncoding : NSUTF8StringEncoding ] ] ;
NSUInteger length = [ data length ] ;
NSMutableData * mutableData = [ NSMutableData dataWithLength : ( ( length + 2 ) / 3 ) * 4 ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
uint8_t * input = ( uint8_t * ) [ data bytes ] ;
uint8_t * output = ( uint8_t * ) [ mutableData mutableBytes ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -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 ) {
2013-09-25 17:43:00 -07:00
value | = ( 0 xFF & input [ j ] ) ;
2012-07-18 12:17:55 -07:00
}
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
static uint8_t const kAFBase64EncodingTable [ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -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-09-25 17:43:00 -07:00
return [ [ NSString alloc ] initWithData : mutableData encoding : NSASCIIStringEncoding ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( NSString * string , NSStringEncoding encoding ) {
static NSString * const kAFCharactersToBeEscaped = @ ":/?&=;+!@#$()',*" ;
static NSString * const kAFCharactersToLeaveUnescaped = @ "[]." ;
return ( __bridge _transfer NSString * ) CFURLCreateStringByAddingPercentEscapes ( kCFAllocatorDefault , ( __bridge CFStringRef ) string , ( __bridge CFStringRef ) kAFCharactersToLeaveUnescaped , ( __bridge CFStringRef ) kAFCharactersToBeEscaped , CFStringConvertNSStringEncodingToEncoding ( encoding ) ) ;
2012-07-18 12:17:55 -07:00
}
# pragma mark -
2013-09-25 17:43:00 -07:00
@ interface AFQueryStringPair : NSObject
@ property ( readwrite , nonatomic , strong ) id field ;
@ property ( readwrite , nonatomic , strong ) id value ;
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07:00
- ( id ) initWithField : ( id ) field value : ( id ) value ;
2012-07-18 12:17:55 -07:00
- ( NSString * ) URLEncodedStringValueWithEncoding : ( NSStringEncoding ) stringEncoding ;
@ end
2013-09-25 17:43:00 -07:00
@ implementation AFQueryStringPair
@ synthesize field = _field ;
2012-07-18 12:17:55 -07:00
@ synthesize value = _value ;
2013-09-25 17:43:00 -07:00
- ( id ) initWithField : ( id ) field value : ( id ) value {
2012-07-18 12:17:55 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-09-25 17:43:00 -07:00
self . field = field ;
2012-07-18 12:17:55 -07:00
self . value = value ;
2013-09-25 17:43:00 -07:00
return self ;
2012-07-18 12:17:55 -07:00
}
- ( NSString * ) URLEncodedStringValueWithEncoding : ( NSStringEncoding ) stringEncoding {
2013-09-25 17:43:00 -07:00
if ( ! self . value || [ self . value isEqual : [ NSNull null ] ] ) {
return AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . field description ] , stringEncoding ) ;
} else {
return [ NSString stringWithFormat : @ "%@=%@" , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . field description ] , stringEncoding ) , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . value description ] , stringEncoding ) ] ;
}
2012-07-18 12:17:55 -07:00
}
@ end
# pragma mark -
2013-09-25 17:43:00 -07:00
extern NSArray * AFQueryStringPairsFromDictionary ( NSDictionary * dictionary ) ;
extern NSArray * AFQueryStringPairsFromKeyAndValue ( NSString * key , id value ) ;
2012-07-18 12:17:55 -07:00
NSString * AFQueryStringFromParametersWithEncoding ( NSDictionary * parameters , NSStringEncoding stringEncoding ) {
2013-09-25 17:43:00 -07:00
NSMutableArray * mutablePairs = [ NSMutableArray array ] ;
for ( AFQueryStringPair * pair in AFQueryStringPairsFromDictionary ( parameters ) ) {
[ mutablePairs addObject : [ pair URLEncodedStringValueWithEncoding : stringEncoding ] ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
return [ mutablePairs componentsJoinedByString : @ "&" ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
NSArray * AFQueryStringPairsFromDictionary ( NSDictionary * dictionary ) {
return AFQueryStringPairsFromKeyAndValue ( nil , dictionary ) ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
NSArray * AFQueryStringPairsFromKeyAndValue ( NSString * key , id value ) {
2012-07-18 12:17:55 -07:00
NSMutableArray * mutableQueryStringComponents = [ NSMutableArray array ] ;
2013-09-25 17:43:00 -07:00
if ( [ value isKindOfClass : [ NSDictionary class ] ] ) {
NSDictionary * dictionary = value ;
// Sort dictionary keys to ensure consistent ordering in query string , which is important when deserializing potentially ambiguous sequences , such as an array of dictionaries
NSSortDescriptor * sortDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "description" ascending : YES selector : @ selector ( caseInsensitiveCompare : ) ] ;
for ( id nestedKey in [ dictionary . allKeys sortedArrayUsingDescriptors : @ [ sortDescriptor ] ] ) {
id nestedValue = [ dictionary objectForKey : nestedKey ] ;
if ( nestedValue ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( ( key ? [ NSString stringWithFormat : @ "%@[%@]" , key , nestedKey ] : nestedKey ) , nestedValue ) ] ;
}
}
} else if ( [ value isKindOfClass : [ NSArray class ] ] ) {
NSArray * array = value ;
for ( id nestedValue in array ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( [ NSString stringWithFormat : @ "%@[]" , key ] , nestedValue ) ] ;
}
} else if ( [ value isKindOfClass : [ NSSet class ] ] ) {
NSSet * set = value ;
for ( id obj in set ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( key , obj ) ] ;
}
2012-07-18 12:17:55 -07:00
} else {
2013-09-25 17:43:00 -07:00
[ mutableQueryStringComponents addObject : [ [ AFQueryStringPair alloc ] initWithField : key value : value ] ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
return mutableQueryStringComponents ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
@ interface AFStreamingMultipartFormData : NSObject < AFMultipartFormData >
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) urlRequest
stringEncoding : ( NSStringEncoding ) encoding ;
- ( NSMutableURLRequest * ) requestByFinalizingMultipartFormData ;
@ end
# pragma mark -
2012-07-18 12:17:55 -07:00
@ interface AFHTTPClient ( )
2013-09-25 17:43:00 -07: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-07-18 12:17:55 -07:00
# ifdef _SYSTEMCONFIGURATION _H
@ property ( readwrite , nonatomic , assign ) AFNetworkReachabilityRef networkReachability ;
@ property ( readwrite , nonatomic , assign ) AFNetworkReachabilityStatus networkReachabilityStatus ;
@ property ( readwrite , nonatomic , copy ) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock ;
# endif
# ifdef _SYSTEMCONFIGURATION _H
- ( void ) startMonitoringNetworkReachability ;
- ( void ) stopMonitoringNetworkReachability ;
# endif
@ end
@ implementation AFHTTPClient
@ synthesize baseURL = _baseURL ;
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize parameterEncoding = _parameterEncoding ;
@ synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames ;
@ synthesize defaultHeaders = _defaultHeaders ;
2013-09-25 17:43:00 -07:00
@ synthesize defaultCredential = _defaultCredential ;
2012-07-18 12:17:55 -07:00
@ synthesize operationQueue = _operationQueue ;
# ifdef _SYSTEMCONFIGURATION _H
@ synthesize networkReachability = _networkReachability ;
@ synthesize networkReachabilityStatus = _networkReachabilityStatus ;
@ synthesize networkReachabilityStatusBlock = _networkReachabilityStatusBlock ;
# endif
2013-09-25 17:43:00 -07:00
@ synthesize defaultSSLPinningMode = _defaultSSLPinningMode ;
@ synthesize allowsInvalidSSLCertificate = _allowsInvalidSSLCertificate ;
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07:00
+ ( instancetype ) clientWithBaseURL : ( NSURL * ) url {
return [ [ self alloc ] initWithBaseURL : url ] ;
}
- ( id ) init {
@ throw [ NSException exceptionWithName : NSInternalInconsistencyException reason : [ NSString stringWithFormat : @ "%@ Failed to call designated initializer. Invoke `initWithBaseURL:` instead." , NSStringFromClass ( [ self class ] ) ] userInfo : nil ] ;
2012-07-18 12:17:55 -07:00
}
- ( id ) initWithBaseURL : ( NSURL * ) url {
2013-09-25 17:43:00 -07:00
NSParameterAssert ( url ) ;
2012-07-18 12:17:55 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-09-25 17:43:00 -07: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-07-18 12:17:55 -07:00
self . baseURL = url ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
self . stringEncoding = NSUTF8StringEncoding ;
self . parameterEncoding = AFFormURLParameterEncoding ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
self . registeredHTTPOperationClassNames = [ NSMutableArray array ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
self . defaultHeaders = [ NSMutableDictionary dictionary ] ;
2013-09-25 17:43:00 -07:00
// Accept - Language HTTP Header ; see http : // www . w3 . org / Protocols / rfc2616 / rfc2616 - sec14 . html # sec14 .4
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 ] ] ;
* stop = q <= 0.5 f ;
} ] ;
[ self setDefaultHeader : @ "Accept-Language" value : [ acceptLanguagesComponents componentsJoinedByString : @ ", " ] ] ;
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu"
# if defined ( __IPHONE _OS _VERSION _MIN _REQUIRED )
2012-07-18 12:17:55 -07:00
// User - Agent Header ; see http : // www . w3 . org / Protocols / rfc2616 / rfc2616 - sec14 . html # sec14 .43
2013-09-25 17:43:00 -07:00
[ self setDefaultHeader : @ "User-Agent" value : [ NSString stringWithFormat : @ "%@/%@ (%@; iOS %@; Scale/%0.2f)" , [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleExecutableKey ] ? : [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleIdentifierKey ] , ( __bridge id ) CFBundleGetValueForInfoDictionaryKey ( CFBundleGetMainBundle ( ) , kCFBundleVersionKey ) ? : [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleVersionKey ] , [ [ UIDevice currentDevice ] model ] , [ [ UIDevice currentDevice ] systemVersion ] , ( [ [ UIScreen mainScreen ] respondsToSelector : @ selector ( scale ) ] ? [ [ UIScreen mainScreen ] scale ] : 1.0 f ) ] ] ;
# elif defined ( __MAC _OS _X _VERSION _MIN _REQUIRED )
[ self setDefaultHeader : @ "User-Agent" value : [ NSString stringWithFormat : @ "%@/%@ (Mac OS X %@)" , [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleExecutableKey ] ? : [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleIdentifierKey ] , [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : @ "CFBundleShortVersionString" ] ? : [ [ [ NSBundle mainBundle ] infoDictionary ] objectForKey : ( __bridge NSString * ) kCFBundleVersionKey ] , [ [ NSProcessInfo processInfo ] operatingSystemVersionString ] ] ] ;
2012-07-18 12:17:55 -07:00
# endif
2013-09-25 17:43:00 -07:00
# pragma clang diagnostic pop
2012-07-18 12:17:55 -07:00
# ifdef _SYSTEMCONFIGURATION _H
self . networkReachabilityStatus = AFNetworkReachabilityStatusUnknown ;
[ self startMonitoringNetworkReachability ] ;
# endif
2013-09-25 17:43:00 -07:00
self . operationQueue = [ [ NSOperationQueue alloc ] init ] ;
[ self . operationQueue setMaxConcurrentOperationCount : NSOperationQueueDefaultMaxConcurrentOperationCount ] ;
// # ifdef included for backwards - compatibility
# ifdef _AFNETWORKING _ALLOW _INVALID _SSL _CERTIFICATES _
self . allowsInvalidSSLCertificate = YES ;
# endif
2012-07-18 12:17:55 -07:00
return self ;
}
- ( void ) dealloc {
# ifdef _SYSTEMCONFIGURATION _H
[ self stopMonitoringNetworkReachability ] ;
# endif
}
- ( NSString * ) description {
return [ NSString stringWithFormat : @ "<%@: %p, baseURL: %@, defaultHeaders: %@, registeredOperationClasses: %@, operationQueue: %@>" , NSStringFromClass ( [ self class ] ) , self , [ self . baseURL absoluteString ] , self . defaultHeaders , self . registeredHTTPOperationClassNames , self . operationQueue ] ;
}
# pragma mark -
# ifdef _SYSTEMCONFIGURATION _H
static BOOL AFURLHostIsIPAddress ( NSURL * url ) {
struct sockaddr_in sa_in ;
struct sockaddr_in6 sa_in6 ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -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 ) ;
}
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags ( SCNetworkReachabilityFlags flags ) {
BOOL isReachable = ( ( flags & kSCNetworkReachabilityFlagsReachable ) ! = 0 ) ;
BOOL needsConnection = ( ( flags & kSCNetworkReachabilityFlagsConnectionRequired ) ! = 0 ) ;
2013-09-25 17:43:00 -07:00
BOOL canConnectionAutomatically = ( ( ( flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) ! = 0 ) || ( ( flags & kSCNetworkReachabilityFlagsConnectionOnTraffic ) ! = 0 ) ) ;
BOOL canConnectWithoutUserInteraction = ( canConnectionAutomatically && ( flags & kSCNetworkReachabilityFlagsInterventionRequired ) = = 0 ) ;
BOOL isNetworkReachable = ( isReachable && ( ! needsConnection || canConnectWithoutUserInteraction ) ) ;
2012-07-18 12:17:55 -07:00
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown ;
2013-09-25 17:43:00 -07:00
if ( isNetworkReachable = = NO ) {
2012-07-18 12:17:55 -07:00
status = AFNetworkReachabilityStatusNotReachable ;
}
# if TARGET_OS _IPHONE
2013-09-25 17:43:00 -07:00
else if ( ( flags & kSCNetworkReachabilityFlagsIsWWAN ) ! = 0 ) {
2012-07-18 12:17:55 -07:00
status = AFNetworkReachabilityStatusReachableViaWWAN ;
}
# endif
else {
status = AFNetworkReachabilityStatusReachableViaWiFi ;
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
return status ;
}
2013-09-25 17:43:00 -07:00
static void AFNetworkReachabilityCallback ( SCNetworkReachabilityRef __unused target , SCNetworkReachabilityFlags flags , void * info ) {
2012-07-18 12:17:55 -07:00
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags ( flags ) ;
2013-09-25 17:43:00 -07:00
AFNetworkReachabilityStatusBlock block = ( __bridge AFNetworkReachabilityStatusBlock ) info ;
2012-07-18 12:17:55 -07:00
if ( block ) {
block ( status ) ;
}
2013-09-25 17:43:00 -07:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter ] ;
[ notificationCenter postNotificationName : AFNetworkingReachabilityDidChangeNotification object : nil userInfo : [ NSDictionary dictionaryWithObject : [ NSNumber numberWithInteger : status ] forKey : AFNetworkingReachabilityNotificationStatusItem ] ] ;
} ) ;
2012-07-18 12:17:55 -07:00
}
static const void * AFNetworkReachabilityRetainCallback ( const void * info ) {
2013-09-25 17:43:00 -07:00
return Block_copy ( info ) ;
2012-07-18 12:17:55 -07:00
}
static void AFNetworkReachabilityReleaseCallback ( const void * info ) {
2013-09-25 17:43:00 -07:00
if ( info ) {
Block_release ( info ) ;
}
2012-07-18 12:17:55 -07:00
}
- ( void ) startMonitoringNetworkReachability {
[ self stopMonitoringNetworkReachability ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
if ( ! self . baseURL ) {
return ;
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
self . networkReachability = SCNetworkReachabilityCreateWithName ( kCFAllocatorDefault , [ [ self . baseURL host ] UTF8String ] ) ;
2013-09-25 17:43:00 -07:00
if ( ! self . networkReachability ) {
return ;
}
__weak __typeof ( & * self ) weakSelf = self ;
AFNetworkReachabilityStatusBlock callback = ^ ( AFNetworkReachabilityStatus status ) {
__strong __typeof ( & * weakSelf ) strongSelf = weakSelf ;
if ( ! strongSelf ) {
return ;
}
strongSelf . networkReachabilityStatus = status ;
if ( strongSelf . networkReachabilityStatusBlock ) {
strongSelf . networkReachabilityStatusBlock ( status ) ;
2012-07-18 12:17:55 -07:00
}
} ;
2013-09-25 17:43:00 -07:00
SCNetworkReachabilityContext context = { 0 , ( __bridge void * ) callback , AFNetworkReachabilityRetainCallback , AFNetworkReachabilityReleaseCallback , NULL } ;
2012-07-18 12:17:55 -07:00
SCNetworkReachabilitySetCallback ( self . networkReachability , AFNetworkReachabilityCallback , & context ) ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -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 ) ;
} ) ;
}
2013-09-25 17:43:00 -07:00
SCNetworkReachabilityScheduleWithRunLoop ( self . networkReachability , CFRunLoopGetMain ( ) , kCFRunLoopCommonModes ) ;
2012-07-18 12:17:55 -07:00
}
- ( void ) stopMonitoringNetworkReachability {
2013-09-25 17:43:00 -07:00
if ( self . networkReachability ) {
SCNetworkReachabilityUnscheduleFromRunLoop ( self . networkReachability , CFRunLoopGetMain ( ) , kCFRunLoopCommonModes ) ;
2012-07-18 12:17:55 -07:00
CFRelease ( _networkReachability ) ;
2013-09-25 17:43:00 -07:00
_networkReachability = NULL ;
2012-07-18 12:17:55 -07:00
}
}
- ( void ) setReachabilityStatusChangeBlock : ( void ( ^ ) ( AFNetworkReachabilityStatus status ) ) block {
self . networkReachabilityStatusBlock = block ;
}
# endif
# pragma mark -
- ( BOOL ) registerHTTPOperationClass : ( Class ) operationClass {
if ( ! [ operationClass isSubclassOfClass : [ AFHTTPRequestOperation class ] ] ) {
return NO ;
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
NSString * className = NSStringFromClass ( operationClass ) ;
[ self . registeredHTTPOperationClassNames removeObject : className ] ;
[ self . registeredHTTPOperationClassNames insertObject : className atIndex : 0 ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
return YES ;
}
- ( void ) unregisterHTTPOperationClass : ( Class ) operationClass {
NSString * className = NSStringFromClass ( operationClass ) ;
[ self . registeredHTTPOperationClassNames removeObject : className ] ;
}
# pragma mark -
- ( NSString * ) defaultValueForHeader : ( NSString * ) header {
return [ self . defaultHeaders valueForKey : header ] ;
}
- ( void ) setDefaultHeader : ( NSString * ) header value : ( NSString * ) value {
[ self . defaultHeaders setValue : value forKey : header ] ;
}
- ( void ) setAuthorizationHeaderWithUsername : ( NSString * ) username password : ( NSString * ) password {
NSString * basicAuthCredentials = [ NSString stringWithFormat : @ "%@:%@" , username , password ] ;
[ self setDefaultHeader : @ "Authorization" value : [ NSString stringWithFormat : @ "Basic %@" , AFBase64EncodedStringFromString ( basicAuthCredentials ) ] ] ;
}
- ( void ) setAuthorizationHeaderWithToken : ( NSString * ) token {
[ self setDefaultHeader : @ "Authorization" value : [ NSString stringWithFormat : @ "Token token=\" % @ \ "" , token ] ] ;
}
- ( void ) clearAuthorizationHeader {
[ self . defaultHeaders removeObjectForKey : @ "Authorization" ] ;
}
# pragma mark -
2013-09-25 17:43:00 -07:00
- ( NSMutableURLRequest * ) requestWithMethod : ( NSString * ) method
path : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
{
NSParameterAssert ( method ) ;
if ( ! path ) {
path = @ "" ;
}
2012-07-18 12:17:55 -07:00
NSURL * url = [ NSURL URLWithString : path relativeToURL : self . baseURL ] ;
2013-09-25 17:43:00 -07:00
NSMutableURLRequest * request = [ [ NSMutableURLRequest alloc ] initWithURL : url ] ;
2012-07-18 12:17:55 -07:00
[ request setHTTPMethod : method ] ;
[ request setAllHTTPHeaderFields : self . defaultHeaders ] ;
2013-09-25 17:43:00 -07:00
if ( parameters ) {
2012-07-18 12:17:55 -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 {
2013-09-25 17:43:00 -07:00
NSString * charset = ( __bridge NSString * ) CFStringConvertEncodingToIANACharSetName ( CFStringConvertNSStringEncodingToEncoding ( self . stringEncoding ) ) ;
NSError * error = nil ;
2012-07-18 12:17:55 -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" ] ;
2013-09-25 17:43:00 -07:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wassign-enum"
[ request setHTTPBody : [ NSJSONSerialization dataWithJSONObject : parameters options : 0 error : & error ] ] ;
# pragma clang diagnostic pop
2012-07-18 12:17:55 -07:00
break ;
case AFPropertyListParameterEncoding : ;
[ request setValue : [ NSString stringWithFormat : @ "application/x-plist; charset=%@" , charset ] forHTTPHeaderField : @ "Content-Type" ] ;
2013-09-25 17:43:00 -07:00
[ request setHTTPBody : [ NSPropertyListSerialization dataWithPropertyList : parameters format : NSPropertyListXMLFormat_v1 _0 options : 0 error : & error ] ] ;
2012-07-18 12:17:55 -07:00
break ;
}
2013-09-25 17:43:00 -07:00
if ( error ) {
NSLog ( @ "%@ %@: %@" , [ self class ] , NSStringFromSelector ( _cmd ) , error ) ;
}
2012-07-18 12:17:55 -07:00
}
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
return request ;
}
- ( NSMutableURLRequest * ) multipartFormRequestWithMethod : ( NSString * ) method
path : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2013-09-25 17:43:00 -07:00
constructingBodyWithBlock : ( void ( ^ ) ( id < AFMultipartFormData > formData ) ) block
2012-07-18 12:17:55 -07:00
{
2013-09-25 17:43:00 -07:00
NSParameterAssert ( method ) ;
NSParameterAssert ( ! [ method isEqualToString : @ "GET" ] && ! [ method isEqualToString : @ "HEAD" ] ) ;
2012-07-18 12:17:55 -07:00
NSMutableURLRequest * request = [ self requestWithMethod : method path : path parameters : nil ] ;
2013-09-25 17:43:00 -07:00
__block AFStreamingMultipartFormData * formData = [ [ AFStreamingMultipartFormData alloc ] initWithURLRequest : request stringEncoding : self . stringEncoding ] ;
2012-07-18 12:17:55 -07:00
if ( parameters ) {
2013-09-25 17:43:00 -07:00
for ( AFQueryStringPair * pair in AFQueryStringPairsFromDictionary ( parameters ) ) {
2012-07-18 12:17:55 -07:00
NSData * data = nil ;
2013-09-25 17:43:00 -07:00
if ( [ pair . value isKindOfClass : [ NSData class ] ] ) {
data = pair . value ;
} else if ( [ pair . value isEqual : [ NSNull null ] ] ) {
data = [ NSData data ] ;
2012-07-18 12:17:55 -07:00
} else {
2013-09-25 17:43:00 -07:00
data = [ [ pair . value description ] dataUsingEncoding : self . stringEncoding ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
if ( data ) {
2013-09-25 17:43:00 -07:00
[ formData appendPartWithFormData : data name : [ pair . field description ] ] ;
2012-07-18 12:17:55 -07:00
}
}
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
if ( block ) {
block ( formData ) ;
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
return [ formData requestByFinalizingMultipartFormData ] ;
}
2013-09-25 17:43:00 -07:00
- ( AFHTTPRequestOperation * ) HTTPRequestOperationWithRequest : ( NSURLRequest * ) urlRequest
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
AFHTTPRequestOperation * operation = nil ;
2013-09-25 17:43:00 -07:00
for ( NSString * className in self . registeredHTTPOperationClassNames ) {
Class operationClass = NSClassFromString ( className ) ;
if ( operationClass && [ operationClass canProcessRequest : urlRequest ] ) {
operation = [ ( AFHTTPRequestOperation * ) [ operationClass alloc ] initWithRequest : urlRequest ] ;
break ;
2012-07-18 12:17:55 -07:00
}
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
if ( ! operation ) {
2013-09-25 17:43:00 -07:00
operation = [ [ AFHTTPRequestOperation alloc ] initWithRequest : urlRequest ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
[ operation setCompletionBlockWithSuccess : success failure : failure ] ;
2013-09-25 17:43:00 -07:00
operation . credential = self . defaultCredential ;
operation . SSLPinningMode = self . defaultSSLPinningMode ;
operation . allowsInvalidSSLCertificate = self . allowsInvalidSSLCertificate ;
2012-07-18 12:17:55 -07:00
return operation ;
}
# pragma mark -
- ( void ) enqueueHTTPRequestOperation : ( AFHTTPRequestOperation * ) operation {
[ self . operationQueue addOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) cancelAllHTTPOperationsWithMethod : ( NSString * ) method
path : ( NSString * ) path
{
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu"
NSString * pathToBeMatched = [ [ [ self requestWithMethod : ( method ? : @ "GET" ) path : path parameters : nil ] URL ] path ] ;
# pragma clang diagnostic pop
2012-07-18 12:17:55 -07:00
for ( NSOperation * operation in [ self . operationQueue operations ] ) {
if ( ! [ operation isKindOfClass : [ AFHTTPRequestOperation class ] ] ) {
continue ;
}
2013-09-25 17:43:00 -07:00
BOOL hasMatchingMethod = ! method || [ method isEqualToString : [ [ ( AFHTTPRequestOperation * ) operation request ] HTTPMethod ] ] ;
BOOL hasMatchingPath = [ [ [ [ ( AFHTTPRequestOperation * ) operation request ] URL ] path ] isEqual : pathToBeMatched ] ;
if ( hasMatchingMethod && hasMatchingPath ) {
2012-07-18 12:17:55 -07:00
[ operation cancel ] ;
}
}
}
2013-09-25 17:43:00 -07:00
- ( void ) enqueueBatchOfHTTPRequestOperationsWithRequests : ( NSArray * ) urlRequests
progressBlock : ( void ( ^ ) ( NSUInteger numberOfFinishedOperations , NSUInteger totalNumberOfOperations ) ) progressBlock
2012-07-18 12:17:55 -07:00
completionBlock : ( void ( ^ ) ( NSArray * operations ) ) completionBlock
{
NSMutableArray * mutableOperations = [ NSMutableArray array ] ;
2013-09-25 17:43:00 -07:00
for ( NSURLRequest * request in urlRequests ) {
2012-07-18 12:17:55 -07:00
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : nil failure : nil ] ;
[ mutableOperations addObject : operation ] ;
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
[ self enqueueBatchOfHTTPRequestOperations : mutableOperations progressBlock : progressBlock completionBlock : completionBlock ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) enqueueBatchOfHTTPRequestOperations : ( NSArray * ) operations
progressBlock : ( void ( ^ ) ( NSUInteger numberOfFinishedOperations , NSUInteger totalNumberOfOperations ) ) progressBlock
2012-07-18 12:17:55 -07:00
completionBlock : ( void ( ^ ) ( NSArray * operations ) ) completionBlock
{
__block dispatch_group _t dispatchGroup = dispatch_group _create ( ) ;
NSBlockOperation * batchedOperation = [ NSBlockOperation blockOperationWithBlock : ^ {
dispatch_group _notify ( dispatchGroup , dispatch_get _main _queue ( ) , ^ {
if ( completionBlock ) {
completionBlock ( operations ) ;
}
} ) ;
2013-09-25 17:43:00 -07:00
# if ! OS_OBJECT _USE _OBJC
2012-07-18 12:17:55 -07:00
dispatch_release ( dispatchGroup ) ;
2013-09-25 17:43:00 -07:00
# endif
2012-07-18 12:17:55 -07:00
} ] ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
for ( AFHTTPRequestOperation * operation in operations ) {
2013-09-25 17:43:00 -07:00
AFCompletionBlock originalCompletionBlock = [ operation . completionBlock copy ] ;
__weak __typeof ( & * operation ) weakOperation = operation ;
2012-07-18 12:17:55 -07:00
operation . completionBlock = ^ {
2013-09-25 17:43:00 -07:00
__strong __typeof ( & * weakOperation ) strongOperation = weakOperation ;
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu"
dispatch_queue _t queue = strongOperation . successCallbackQueue ? : dispatch_get _main _queue ( ) ;
# pragma clang diagnostic pop
2012-07-18 12:17:55 -07:00
dispatch_group _async ( dispatchGroup , queue , ^ {
if ( originalCompletionBlock ) {
originalCompletionBlock ( ) ;
}
2013-09-25 17:43:00 -07:00
NSUInteger numberOfFinishedOperations = [ [ operations indexesOfObjectsPassingTest : ^ BOOL ( id op , NSUInteger __unused idx , BOOL __unused * stop ) {
return [ op isFinished ] ;
} ] count ] ;
2012-07-18 12:17:55 -07:00
if ( progressBlock ) {
2013-09-25 17:43:00 -07:00
progressBlock ( numberOfFinishedOperations , [ operations count ] ) ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
dispatch_group _leave ( dispatchGroup ) ;
} ) ;
} ;
2013-09-25 17:43:00 -07:00
2012-07-18 12:17:55 -07:00
dispatch_group _enter ( dispatchGroup ) ;
[ batchedOperation addDependency : operation ] ;
}
2013-09-25 17:43:00 -07:00
[ self . operationQueue addOperations : operations waitUntilFinished : NO ] ;
2012-07-18 12:17:55 -07:00
[ self . operationQueue addOperation : batchedOperation ] ;
}
# pragma mark -
2013-09-25 17:43:00 -07:00
- ( void ) getPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
NSURLRequest * request = [ self requestWithMethod : @ "GET" path : path parameters : parameters ] ;
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) postPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
NSURLRequest * request = [ self requestWithMethod : @ "POST" path : path parameters : parameters ] ;
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) putPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
NSURLRequest * request = [ self requestWithMethod : @ "PUT" path : path parameters : parameters ] ;
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) deletePath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
NSURLRequest * request = [ self requestWithMethod : @ "DELETE" path : path parameters : parameters ] ;
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
- ( void ) patchPath : ( NSString * ) path
parameters : ( NSDictionary * ) parameters
2012-07-18 12:17:55 -07:00
success : ( void ( ^ ) ( AFHTTPRequestOperation * operation , id responseObject ) ) success
failure : ( void ( ^ ) ( AFHTTPRequestOperation * operation , NSError * error ) ) failure
{
NSURLRequest * request = [ self requestWithMethod : @ "PATCH" path : path parameters : parameters ] ;
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : success failure : failure ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
2013-09-25 17:43:00 -07:00
# pragma mark - NSCoding
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07:00
- ( id ) initWithCoder : ( NSCoder * ) aDecoder {
NSURL * baseURL = [ aDecoder decodeObjectForKey : @ "baseURL" ] ;
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07:00
self = [ self initWithBaseURL : baseURL ] ;
if ( ! self ) {
return nil ;
}
self . stringEncoding = [ aDecoder decodeIntegerForKey : @ "stringEncoding" ] ;
self . parameterEncoding = ( AFHTTPClientParameterEncoding ) [ aDecoder decodeIntegerForKey : @ "parameterEncoding" ] ;
self . registeredHTTPOperationClassNames = [ aDecoder decodeObjectForKey : @ "registeredHTTPOperationClassNames" ] ;
self . defaultHeaders = [ aDecoder decodeObjectForKey : @ "defaultHeaders" ] ;
return self ;
}
- ( void ) encodeWithCoder : ( NSCoder * ) aCoder {
[ aCoder encodeObject : self . baseURL forKey : @ "baseURL" ] ;
[ aCoder encodeInteger : ( NSInteger ) self . stringEncoding forKey : @ "stringEncoding" ] ;
[ 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 ] ;
HTTPClient . stringEncoding = self . stringEncoding ;
HTTPClient . parameterEncoding = self . parameterEncoding ;
HTTPClient . registeredHTTPOperationClassNames = [ self . registeredHTTPOperationClassNames mutableCopyWithZone : zone ] ;
HTTPClient . defaultHeaders = [ self . defaultHeaders mutableCopyWithZone : zone ] ;
# ifdef _SYSTEMCONFIGURATION _H
HTTPClient . networkReachabilityStatusBlock = self . networkReachabilityStatusBlock ;
# endif
return HTTPClient ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
@ end
# pragma mark -
2012-07-18 12:17:55 -07:00
static NSString * const kAFMultipartFormBoundary = @ "Boundary+0xAbCdEfGbOuNdArY" ;
static NSString * const kAFMultipartFormCRLF = @ "\r\n" ;
2013-09-25 17:43:00 -07:00
static NSInteger const kAFStreamToStreamBufferSize = 1024 * 1024 ; // 1 meg default
2012-07-18 12:17:55 -07:00
static inline NSString * AFMultipartFormInitialBoundary ( ) {
return [ NSString stringWithFormat : @ "--%@%@" , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
}
static inline NSString * AFMultipartFormEncapsulationBoundary ( ) {
return [ NSString stringWithFormat : @ "%@--%@%@" , kAFMultipartFormCRLF , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
}
static inline NSString * AFMultipartFormFinalBoundary ( ) {
return [ NSString stringWithFormat : @ "%@--%@--%@" , kAFMultipartFormCRLF , kAFMultipartFormBoundary , kAFMultipartFormCRLF ] ;
}
2013-09-25 17:43:00 -07:00
static inline NSString * AFContentTypeForPathExtension ( NSString * extension ) {
# ifdef __UTTYPE __
NSString * UTI = ( __bridge _transfer NSString * ) UTTypeCreatePreferredIdentifierForTag ( kUTTagClassFilenameExtension , ( __bridge CFStringRef ) extension , NULL ) ;
NSString * contentType = ( __bridge _transfer NSString * ) UTTypeCopyPreferredTagWithClass ( ( __bridge CFStringRef ) UTI , kUTTagClassMIMEType ) ;
if ( ! contentType ) {
return @ "application/octet-stream" ;
} else {
return contentType ;
}
# else
return @ "application/octet-stream" ;
# endif
}
NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16 ;
NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2 ;
@ interface AFHTTPBodyPart : NSObject
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
@ property ( nonatomic , strong ) NSDictionary * headers ;
@ property ( nonatomic , strong ) id body ;
@ property ( nonatomic , assign ) unsigned long long bodyContentLength ;
@ property ( nonatomic , strong ) NSInputStream * inputStream ;
@ property ( nonatomic , assign ) BOOL hasInitialBoundary ;
@ property ( nonatomic , assign ) BOOL hasFinalBoundary ;
@ property ( nonatomic , readonly , getter = hasBytesAvailable ) BOOL bytesAvailable ;
@ property ( nonatomic , readonly ) unsigned long long contentLength ;
- ( NSInteger ) read : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length ;
@ end
@ interface AFMultipartBodyStream : NSInputStream < NSStreamDelegate >
@ property ( nonatomic , assign ) NSUInteger numberOfBytesInPacket ;
@ property ( nonatomic , assign ) NSTimeInterval delay ;
@ property ( nonatomic , strong ) NSInputStream * inputStream ;
@ property ( nonatomic , readonly ) unsigned long long contentLength ;
@ property ( nonatomic , readonly , getter = isEmpty ) BOOL empty ;
- ( id ) initWithStringEncoding : ( NSStringEncoding ) encoding ;
- ( void ) setInitialAndFinalBoundaries ;
- ( void ) appendHTTPBodyPart : ( AFHTTPBodyPart * ) bodyPart ;
@ end
# pragma mark -
@ interface AFStreamingMultipartFormData ( )
@ property ( readwrite , nonatomic , copy ) NSMutableURLRequest * request ;
@ property ( readwrite , nonatomic , strong ) AFMultipartBodyStream * bodyStream ;
2012-07-18 12:17:55 -07:00
@ property ( readwrite , nonatomic , assign ) NSStringEncoding stringEncoding ;
@ end
2013-09-25 17:43:00 -07:00
@ implementation AFStreamingMultipartFormData
2012-07-18 12:17:55 -07:00
@ synthesize request = _request ;
2013-09-25 17:43:00 -07:00
@ synthesize bodyStream = _bodyStream ;
2012-07-18 12:17:55 -07:00
@ synthesize stringEncoding = _stringEncoding ;
2013-09-25 17:43:00 -07:00
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) urlRequest
stringEncoding : ( NSStringEncoding ) encoding
2012-07-18 12:17:55 -07:00
{
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
2013-09-25 17:43:00 -07:00
self . request = urlRequest ;
2012-07-18 12:17:55 -07:00
self . stringEncoding = encoding ;
2013-09-25 17:43:00 -07:00
self . bodyStream = [ [ AFMultipartBodyStream alloc ] initWithStringEncoding : encoding ] ;
2012-07-18 12:17:55 -07:00
return self ;
}
2013-09-25 17:43:00 -07:00
- ( BOOL ) appendPartWithFileURL : ( NSURL * ) fileURL
name : ( NSString * ) name
error : ( NSError * __autoreleasing * ) error
{
NSParameterAssert ( fileURL ) ;
NSParameterAssert ( name ) ;
NSString * fileName = [ fileURL lastPathComponent ] ;
NSString * mimeType = AFContentTypeForPathExtension ( [ fileURL pathExtension ] ) ;
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07: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
error : ( NSError * __autoreleasing * ) error
{
NSParameterAssert ( fileURL ) ;
NSParameterAssert ( name ) ;
NSParameterAssert ( fileName ) ;
NSParameterAssert ( mimeType ) ;
if ( ! [ fileURL isFileURL ] ) {
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedStringFromTable ( @ "Expected URL to be a file URL" , @ "AFNetworking" , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
return NO ;
} else if ( [ fileURL checkResourceIsReachableAndReturnError : error ] = = NO ) {
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedStringFromTable ( @ "File URL not reachable." , @ "AFNetworking" , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
return NO ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -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" ] ;
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
bodyPart . body = fileURL ;
NSDictionary * fileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : [ fileURL path ] error : nil ] ;
bodyPart . bodyContentLength = [ [ fileAttributes objectForKey : NSFileSize ] unsignedLongLongValue ] ;
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
return YES ;
}
- ( 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 ] ;
}
- ( void ) appendPartWithFileData : ( NSData * ) data
name : ( NSString * ) name
fileName : ( NSString * ) fileName
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" ] ;
[ self appendPartWithHeaders : mutableHeaders body : data ] ;
}
- ( void ) appendPartWithFormData : ( NSData * ) data
name : ( NSString * ) name
{
NSParameterAssert ( name ) ;
NSMutableDictionary * mutableHeaders = [ NSMutableDictionary dictionary ] ;
[ mutableHeaders setValue : [ NSString stringWithFormat : @ "form-data; name=\" % @ \ "" , name ] forKey : @ "Content-Disposition" ] ;
[ self appendPartWithHeaders : mutableHeaders body : data ] ;
}
- ( void ) appendPartWithHeaders : ( NSDictionary * ) headers
body : ( NSData * ) body
{
NSParameterAssert ( body ) ;
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = headers ;
bodyPart . bodyContentLength = [ body length ] ;
bodyPart . body = body ;
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
}
- ( void ) throttleBandwidthWithPacketSize : ( NSUInteger ) numberOfBytes
delay : ( NSTimeInterval ) delay
{
self . bodyStream . numberOfBytesInPacket = numberOfBytes ;
self . bodyStream . delay = delay ;
2012-07-18 12:17:55 -07:00
}
- ( NSMutableURLRequest * ) requestByFinalizingMultipartFormData {
2013-09-25 17:43:00 -07:00
if ( [ self . bodyStream isEmpty ] ) {
2012-07-18 12:17:55 -07:00
return self . request ;
}
2013-09-25 17:43:00 -07:00
// Reset the initial and final boundaries to ensure correct Content - Length
[ self . bodyStream setInitialAndFinalBoundaries ] ;
2012-07-18 12:17:55 -07:00
[ self . request setValue : [ NSString stringWithFormat : @ "multipart/form-data; boundary=%@" , kAFMultipartFormBoundary ] forHTTPHeaderField : @ "Content-Type" ] ;
2013-09-25 17:43:00 -07:00
[ self . request setValue : [ NSString stringWithFormat : @ "%llu" , [ self . bodyStream contentLength ] ] forHTTPHeaderField : @ "Content-Length" ] ;
[ self . request setHTTPBodyStream : self . bodyStream ] ;
2012-07-18 12:17:55 -07:00
return self . request ;
}
2013-09-25 17:43:00 -07:00
@ end
2012-07-18 12:17:55 -07:00
2013-09-25 17:43:00 -07:00
# pragma mark -
@ interface AFMultipartBodyStream ( ) < NSCopying >
@ property ( nonatomic , assign ) NSStreamStatus streamStatus ;
@ property ( nonatomic , strong ) NSError * streamError ;
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
@ property ( nonatomic , strong ) NSMutableArray * HTTPBodyParts ;
@ property ( nonatomic , strong ) NSEnumerator * HTTPBodyPartEnumerator ;
@ property ( nonatomic , strong ) AFHTTPBodyPart * currentHTTPBodyPart ;
@ property ( nonatomic , strong ) NSOutputStream * outputStream ;
@ property ( nonatomic , strong ) NSMutableData * buffer ;
@ end
@ implementation AFMultipartBodyStream
@ synthesize streamStatus = _streamStatus ;
@ synthesize streamError = _streamError ;
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize HTTPBodyParts = _HTTPBodyParts ;
@ synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator ;
@ synthesize currentHTTPBodyPart = _currentHTTPBodyPart ;
@ synthesize inputStream = _inputStream ;
@ synthesize outputStream = _outputStream ;
@ synthesize buffer = _buffer ;
@ synthesize numberOfBytesInPacket = _numberOfBytesInPacket ;
@ synthesize delay = _delay ;
- ( id ) initWithStringEncoding : ( NSStringEncoding ) encoding {
self = [ super init ] ;
if ( ! self ) {
return nil ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
self . stringEncoding = encoding ;
self . HTTPBodyParts = [ NSMutableArray array ] ;
self . numberOfBytesInPacket = NSIntegerMax ;
return self ;
}
- ( void ) setInitialAndFinalBoundaries {
if ( [ self . HTTPBodyParts count ] > 0 ) {
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
bodyPart . hasInitialBoundary = NO ;
bodyPart . hasFinalBoundary = NO ;
}
[ [ self . HTTPBodyParts objectAtIndex : 0 ] setHasInitialBoundary : YES ] ;
[ [ self . HTTPBodyParts lastObject ] setHasFinalBoundary : YES ] ;
}
}
- ( void ) appendHTTPBodyPart : ( AFHTTPBodyPart * ) bodyPart {
[ self . HTTPBodyParts addObject : bodyPart ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( BOOL ) isEmpty {
return [ self . HTTPBodyParts count ] = = 0 ;
}
# pragma mark - NSInputStream
- ( NSInteger ) read : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length
2012-07-18 12:17:55 -07:00
{
2013-09-25 17:43:00 -07:00
if ( [ self streamStatus ] = = NSStreamStatusClosed ) {
return 0 ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
NSInteger bytesRead = 0 ;
while ( ( NSUInteger ) bytesRead < MIN ( length , self . numberOfBytesInPacket ) ) {
if ( ! self . currentHTTPBodyPart || ! [ self . currentHTTPBodyPart hasBytesAvailable ] ) {
if ( ! ( self . currentHTTPBodyPart = [ self . HTTPBodyPartEnumerator nextObject ] ) ) {
break ;
}
} else {
bytesRead + = [ self . currentHTTPBodyPart read : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
if ( self . delay > 0.0 f ) {
[ NSThread sleepForTimeInterval : self . delay ] ;
}
}
}
return bytesRead ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( BOOL ) getBuffer : ( __unused uint8_t * * ) buffer
length : ( __unused NSUInteger * ) len
2012-07-18 12:17:55 -07:00
{
2013-09-25 17:43:00 -07:00
return NO ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( BOOL ) hasBytesAvailable {
return [ self streamStatus ] = = NSStreamStatusOpen ;
}
# pragma mark - NSStream
- ( void ) open {
if ( self . streamStatus = = NSStreamStatusOpen ) {
return ;
}
self . streamStatus = NSStreamStatusOpen ;
[ self setInitialAndFinalBoundaries ] ;
self . HTTPBodyPartEnumerator = [ self . HTTPBodyParts objectEnumerator ] ;
}
- ( void ) close {
self . streamStatus = NSStreamStatusClosed ;
}
- ( id ) propertyForKey : ( __unused NSString * ) key {
return nil ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( BOOL ) setProperty : ( __unused id ) property
forKey : ( __unused NSString * ) key
2012-07-18 12:17:55 -07:00
{
2013-09-25 17:43:00 -07:00
return NO ;
}
- ( void ) scheduleInRunLoop : ( __unused NSRunLoop * ) aRunLoop
forMode : ( __unused NSString * ) mode
{ }
- ( void ) removeFromRunLoop : ( __unused NSRunLoop * ) aRunLoop
forMode : ( __unused NSString * ) mode
{ }
- ( unsigned long long ) contentLength {
unsigned long long length = 0 ;
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
length + = [ bodyPart contentLength ] ;
}
return length ;
}
# pragma mark - Undocumented CFReadStream Bridged Methods
- ( void ) _scheduleInCFRunLoop : ( __unused CFRunLoopRef ) aRunLoop
forMode : ( __unused CFStringRef ) aMode
{ }
- ( void ) _unscheduleFromCFRunLoop : ( __unused CFRunLoopRef ) aRunLoop
forMode : ( __unused CFStringRef ) aMode
{ }
- ( BOOL ) _setCFClientFlags : ( __unused CFOptionFlags ) inFlags
callback : ( __unused CFReadStreamClientCallBack ) inCallback
context : ( __unused CFStreamClientContext * ) inContext {
return NO ;
}
# pragma mark - NSCopying
- ( id ) copyWithZone : ( NSZone * ) zone {
AFMultipartBodyStream * bodyStreamCopy = [ [ [ self class ] allocWithZone : zone ] initWithStringEncoding : self . stringEncoding ] ;
for ( AFHTTPBodyPart * bodyPart in self . HTTPBodyParts ) {
[ bodyStreamCopy appendHTTPBodyPart : [ bodyPart copy ] ] ;
}
[ bodyStreamCopy setInitialAndFinalBoundaries ] ;
return bodyStreamCopy ;
}
@ end
# pragma mark -
typedef enum {
AFEncapsulationBoundaryPhase = 1 ,
AFHeaderPhase = 2 ,
AFBodyPhase = 3 ,
AFFinalBoundaryPhase = 4 ,
} AFHTTPBodyPartReadPhase ;
@ interface AFHTTPBodyPart ( ) < NSCopying > {
AFHTTPBodyPartReadPhase _phase ;
NSInputStream * _inputStream ;
unsigned long long _phaseReadOffset ;
}
- ( BOOL ) transitionToNextPhase ;
- ( NSInteger ) readData : ( NSData * ) data
intoBuffer : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length ;
@ end
@ implementation AFHTTPBodyPart
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize headers = _headers ;
@ synthesize body = _body ;
@ synthesize bodyContentLength = _bodyContentLength ;
@ synthesize inputStream = _inputStream ;
@ synthesize hasInitialBoundary = _hasInitialBoundary ;
@ synthesize hasFinalBoundary = _hasFinalBoundary ;
- ( id ) init {
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
[ self transitionToNextPhase ] ;
return self ;
}
- ( void ) dealloc {
if ( _inputStream ) {
[ _inputStream close ] ;
_inputStream = nil ;
}
}
- ( NSInputStream * ) inputStream {
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 ] ;
} else if ( [ self . body isKindOfClass : [ NSInputStream class ] ] ) {
_inputStream = self . body ;
2012-07-18 12:17:55 -07:00
}
}
2013-09-25 17:43:00 -07:00
return _inputStream ;
}
- ( NSString * ) stringForHeaders {
NSMutableString * headerString = [ NSMutableString string ] ;
for ( NSString * field in [ self . headers allKeys ] ) {
[ headerString appendString : [ NSString stringWithFormat : @ "%@: %@%@" , field , [ self . headers valueForKey : field ] , kAFMultipartFormCRLF ] ] ;
}
[ headerString appendString : kAFMultipartFormCRLF ] ;
return [ NSString stringWithString : headerString ] ;
}
- ( unsigned long long ) contentLength {
unsigned long long length = 0 ;
NSData * encapsulationBoundaryData = [ ( [ self hasInitialBoundary ] ? AFMultipartFormInitialBoundary ( ) : AFMultipartFormEncapsulationBoundary ( ) ) dataUsingEncoding : self . stringEncoding ] ;
length + = [ encapsulationBoundaryData length ] ;
NSData * headersData = [ [ self stringForHeaders ] dataUsingEncoding : self . stringEncoding ] ;
length + = [ headersData length ] ;
length + = _bodyContentLength ;
NSData * closingBoundaryData = ( [ self hasFinalBoundary ] ? [ AFMultipartFormFinalBoundary ( ) dataUsingEncoding : self . stringEncoding ] : [ NSData data ] ) ;
length + = [ closingBoundaryData length ] ;
return length ;
}
- ( BOOL ) hasBytesAvailable {
// Allows ` read : maxLength : ` to be called again if ` AFMultipartFormFinalBoundary` doesn ' t fit into the available buffer
if ( _phase = = AFFinalBoundaryPhase ) {
2012-07-18 12:17:55 -07:00
return YES ;
}
2013-09-25 17:43:00 -07:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcovered-switch-default"
switch ( self . inputStream . streamStatus ) {
case NSStreamStatusNotOpen :
case NSStreamStatusOpening :
case NSStreamStatusOpen :
case NSStreamStatusReading :
case NSStreamStatusWriting :
return YES ;
case NSStreamStatusAtEnd :
case NSStreamStatusClosed :
case NSStreamStatusError :
default :
return NO ;
}
# pragma clang diagnostic pop
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( NSInteger ) read : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length
{
NSInteger bytesRead = 0 ;
if ( _phase = = AFEncapsulationBoundaryPhase ) {
NSData * encapsulationBoundaryData = [ ( [ self hasInitialBoundary ] ? AFMultipartFormInitialBoundary ( ) : AFMultipartFormEncapsulationBoundary ( ) ) dataUsingEncoding : self . stringEncoding ] ;
bytesRead + = [ self readData : encapsulationBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
}
if ( _phase = = AFHeaderPhase ) {
NSData * headersData = [ [ self stringForHeaders ] dataUsingEncoding : self . stringEncoding ] ;
bytesRead + = [ self readData : headersData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
}
if ( _phase = = AFBodyPhase ) {
if ( [ self . inputStream hasBytesAvailable ] ) {
bytesRead + = [ self . inputStream read : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
}
if ( ! [ self . inputStream hasBytesAvailable ] ) {
[ self transitionToNextPhase ] ;
}
}
if ( _phase = = AFFinalBoundaryPhase ) {
NSData * closingBoundaryData = ( [ self hasFinalBoundary ] ? [ AFMultipartFormFinalBoundary ( ) dataUsingEncoding : self . stringEncoding ] : [ NSData data ] ) ;
bytesRead + = [ self readData : closingBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - ( NSUInteger ) bytesRead ) ] ;
}
return bytesRead ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
- ( NSInteger ) readData : ( NSData * ) data
intoBuffer : ( uint8_t * ) buffer
maxLength : ( NSUInteger ) length
{
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu"
NSRange range = NSMakeRange ( ( NSUInteger ) _phaseReadOffset , MIN ( [ data length ] - ( ( NSUInteger ) _phaseReadOffset ) , length ) ) ;
[ data getBytes : buffer range : range ] ;
# pragma clang diagnostic pop
_phaseReadOffset + = range . length ;
if ( ( ( NSUInteger ) _phaseReadOffset ) >= [ data length ] ) {
[ self transitionToNextPhase ] ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
return ( NSInteger ) range . length ;
}
- ( BOOL ) transitionToNextPhase {
if ( ! [ [ NSThread currentThread ] isMainThread ] ) {
[ self performSelectorOnMainThread : @ selector ( transitionToNextPhase ) withObject : nil waitUntilDone : YES ] ;
return YES ;
2012-07-18 12:17:55 -07:00
}
2013-09-25 17:43:00 -07:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcovered-switch-default"
switch ( _phase ) {
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 ;
case AFFinalBoundaryPhase :
default :
_phase = AFEncapsulationBoundaryPhase ;
break ;
}
_phaseReadOffset = 0 ;
# pragma clang diagnostic pop
return YES ;
}
# 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-07-18 12:17:55 -07:00
}
@ end