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
# import < SystemConfiguration / SystemConfiguration . h >
2012-03-09 15:48:59 -08: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-09-26 20:56:33 -04:00
# if __IPHONE _OS _VERSION _MIN _REQUIRED
# import < UIKit / UIKit . h >
# endif
2012-09-17 11:53:49 -07:00
// Workaround for management of dispatch_retain ( ) / dispatch_release ( ) by ARC with iOS 6 / Mac OS X 10.8
# if ( defined ( __IPHONE _OS _VERSION _MIN _REQUIRED ) && ( ! defined ( __IPHONE _6 _0 ) || __IPHONE _OS _VERSION _MIN _REQUIRED < __IPHONE _6 _0 ) ) || \
( defined ( __MAC _OS _X _VERSION _MIN _REQUIRED ) && ( ! defined ( __MAC _10 _8 ) || __MAC _OS _X _VERSION _MIN _REQUIRED < __MAC _10 _8 ) )
# define AF_DISPATCH _RETAIN _RELEASE 1
2012-09-15 12:41:58 +02:00
# endif
2012-02-01 11:27:57 -08:00
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 ] ;
2011-09-21 11:36:39 -05:00
2012-07-19 22:23:38 -07:00
uint8_t * input = ( uint8_t * ) [ data bytes ] ;
uint8_t * output = ( uint8_t * ) [ mutableData mutableBytes ] ;
2012-06-30 16:32:11 -07: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
}
}
static uint8_t const kAFBase64EncodingTable [ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
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 ] : ' = ' ;
}
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 ) {
2012-08-29 10:48:41 -07:00
// Escape characters that are legal in URIs , but have unintentional semantic significance when used in a query string parameter
static NSString * const kAFLegalCharactersToBeEscaped = @ ":/.?&=;+!@$()~" ;
2012-07-19 22:23:38 -07:00
2012-06-26 09:14:52 -07:00
return ( __bridge _transfer NSString * ) CFURLCreateStringByAddingPercentEscapes ( kCFAllocatorDefault , ( __bridge CFStringRef ) string , NULL , ( __bridge CFStringRef ) kAFLegalCharactersToBeEscaped , 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
@ property ( readwrite , nonatomic , retain ) id field ;
2012-03-19 12:44:06 -04:00
@ property ( readwrite , nonatomic , retain ) id value ;
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-07 22:47:04 +01:00
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 ;
}
2012-09-14 10:30:25 -07:00
2012-08-29 10:49:55 -07:00
self . field = field ;
2012-07-19 22:23:38 -07:00
self . value = value ;
return self ;
2012-03-19 12:44:06 -04:00
}
2012-03-28 10:05:00 -07:00
- ( NSString * ) URLEncodedStringValueWithEncoding : ( NSStringEncoding ) stringEncoding {
2012-08-29 10:49:55 -07:00
return [ NSString stringWithFormat : @ "%@=%@" , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( self . field , stringEncoding ) , AFPercentEscapedQueryStringPairMemberFromStringWithEncoding ( [ self . value description ] , stringEncoding ) ] ;
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
}
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 ] ;
if ( [ value isKindOfClass : [ NSDictionary class ] ] ) {
2012-08-29 10:49:55 -07:00
[ value enumerateKeysAndObjectsUsingBlock : ^ ( id nestedKey , id nestedValue , BOOL * stop ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( ( key ? [ NSString stringWithFormat : @ "%@[%@]" , key , nestedKey ] : nestedKey ) , nestedValue ) ] ;
} ] ;
2012-07-19 22:23:38 -07:00
} else if ( [ value isKindOfClass : [ NSArray class ] ] ) {
2012-08-29 10:49:55 -07:00
[ value enumerateObjectsUsingBlock : ^ ( id nestedValue , NSUInteger idx , BOOL * stop ) {
[ mutableQueryStringComponents addObjectsFromArray : AFQueryStringPairsFromKeyAndValue ( [ NSString stringWithFormat : @ "%@[]" , key ] , nestedValue ) ] ;
} ] ;
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
}
2012-07-19 22:23:38 -07:00
return mutableQueryStringComponents ;
2012-03-07 22:47:04 +01:00
}
2011-10-06 14:33:16 -05:00
static NSString * AFJSONStringFromParameters ( NSDictionary * parameters ) {
2012-07-19 22:23:38 -07:00
NSError * error = nil ;
2012-06-26 08:50:32 -07:00
NSData * JSONData = [ NSJSONSerialization dataWithJSONObject : parameters options : 0 error : & error ] ;;
2012-07-19 22:23:38 -07:00
if ( ! error ) {
2012-06-26 09:14:52 -07:00
return [ [ NSString alloc ] initWithData : JSONData encoding : NSUTF8StringEncoding ] ;
2012-07-19 22:23:38 -07:00
} else {
return nil ;
}
2011-10-06 14:33:16 -05:00
}
static NSString * AFPropertyListStringFromParameters ( NSDictionary * parameters ) {
2012-07-19 22:23:38 -07:00
NSString * propertyListString = nil ;
NSError * error = nil ;
NSData * propertyListData = [ NSPropertyListSerialization dataWithPropertyList : parameters format : NSPropertyListXMLFormat_v1 _0 options : 0 error : & error ] ;
if ( ! error ) {
2012-06-26 09:14:52 -07:00
propertyListString = [ [ NSString alloc ] initWithData : propertyListData encoding : NSUTF8StringEncoding ] ;
2012-07-19 22:23:38 -07:00
}
return propertyListString ;
2011-09-21 11:36:39 -05:00
}
2011-06-01 11:51:53 -05:00
2012-09-25 11:06:03 -07:00
@ interface AFStreamingMultipartFormData : NSObject < AFMultipartFormData >
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) request
stringEncoding : ( NSStringEncoding ) encoding ;
- ( NSMutableURLRequest * ) requestByFinalizingMultipartFormData ;
@ end
# pragma mark -
2011-09-21 22:42:01 -05:00
@ interface AFHTTPClient ( )
2012-06-26 09:14:52 -07:00
@ property ( readwrite , nonatomic ) NSURL * baseURL ;
@ property ( readwrite , nonatomic ) NSMutableArray * registeredHTTPOperationClassNames ;
@ property ( readwrite , nonatomic ) NSMutableDictionary * defaultHeaders ;
@ property ( readwrite , nonatomic ) 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 ;
@ 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
2011-09-22 09:43:58 -05:00
+ ( AFHTTPClient * ) 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-07-19 22:23:38 -07:00
self = [ super init ] ;
if ( ! self ) {
return nil ;
}
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
}
2012-08-11 14:26:03 -04:00
2012-07-19 22:23:38 -07:00
self . baseURL = url ;
self . stringEncoding = NSUTF8StringEncoding ;
self . parameterEncoding = AFFormURLParameterEncoding ;
2011-06-01 11:51:53 -05:00
2012-07-19 22:23:38 -07:00
self . registeredHTTPOperationClassNames = [ NSMutableArray array ] ;
2011-06-01 11:51:53 -05:00
self . defaultHeaders = [ NSMutableDictionary dictionary ] ;
2012-09-03 11:11:24 -07:00
// Accept - Language HTTP Header ; see http : // www . w3 . org / Protocols / rfc2616 / rfc2616 - sec14 . html # sec14 .4
NSString * preferredLanguageCodes = [ [ NSLocale preferredLanguages ] componentsJoinedByString : @ ", " ] ;
[ self setDefaultHeader : @ "Accept-Language" value : [ NSString stringWithFormat : @ "%@, en-us;q=0.8" , preferredLanguageCodes ] ] ;
2012-07-19 22:23:38 -07:00
2011-10-11 12:26:34 -05:00
# if __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 ) ] ] ;
2011-10-11 16:55:14 -05:00
# elif __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
2012-07-19 22:23:38 -07: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
2012-07-19 22:23:38 -07: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 ] ;
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 ;
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 ) ;
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown ;
if ( isNetworkReachable = = NO ) {
status = AFNetworkReachabilityStatusNotReachable ;
}
2012-03-20 16:43:19 -07:00
# if TARGET_OS _IPHONE
2012-07-19 22:23:38 -07:00
else if ( ( flags & kSCNetworkReachabilityFlagsIsWWAN ) ! = 0 ) {
status = AFNetworkReachabilityStatusReachableViaWWAN ;
}
2012-03-20 16:43:19 -07:00
# endif
2012-07-19 22:23:38 -07:00
else {
status = AFNetworkReachabilityStatusReachableViaWiFi ;
}
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 ) ;
}
2012-08-31 09:04:54 -07:00
[ [ NSNotificationCenter defaultCenter ] postNotificationName : AFNetworkingReachabilityDidChangeNotification object : nil userInfo : [ NSDictionary dictionaryWithObject : [ NSNumber numberWithInteger : status ] forKey : AFNetworkingReachabilityNotificationStatusItem ] ] ;
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-09-17 11:53:49 -07:00
static void AFNetworkReachabilityReleaseCallback ( const void * 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 ] ;
if ( ! self . baseURL ) {
return ;
}
self . networkReachability = SCNetworkReachabilityCreateWithName ( kCFAllocatorDefault , [ [ self . baseURL host ] UTF8String ] ) ;
AFNetworkReachabilityStatusBlock callback = ^ ( AFNetworkReachabilityStatus status ) {
self . networkReachabilityStatus = status ;
if ( self . networkReachabilityStatusBlock ) {
self . networkReachabilityStatusBlock ( status ) ;
}
} ;
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 ) ;
/ * 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 ;
}
NSString * className = NSStringFromClass ( operationClass ) ;
[ self . registeredHTTPOperationClassNames removeObject : className ] ;
[ self . registeredHTTPOperationClassNames insertObject : className atIndex : 0 ] ;
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-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 ] ;
2011-07-27 15:14:15 -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-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" ] ;
[ request setHTTPBody : [ AFJSONStringFromParameters ( parameters ) dataUsingEncoding : self . stringEncoding ] ] ;
break ;
case AFPropertyListParameterEncoding : ;
[ request setValue : [ NSString stringWithFormat : @ "application/x-plist; charset=%@" , charset ] forHTTPHeaderField : @ "Content-Type" ] ;
[ request setHTTPBody : [ AFPropertyListStringFromParameters ( parameters ) dataUsingEncoding : self . stringEncoding ] ] ;
break ;
}
}
2011-07-27 15:14:15 -05:00
}
2012-07-19 22:23:38 -07: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-07-19 22:23:38 -07:00
NSMutableURLRequest * request = [ self requestWithMethod : method path : path parameters : nil ] ;
2012-09-25 09:56:34 -07:00
__block AFStreamingMultipartFormData * formData = [ [ AFStreamingMultipartFormData alloc ] initWithURLRequest : request stringEncoding : self . stringEncoding ] ;
2012-08-23 10:16:43 -07: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-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
}
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
}
2012-06-05 08:56:27 -07:00
2012-07-19 22:23:38 -07:00
if ( block ) {
block ( formData ) ;
2011-09-21 14:00:05 -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 ;
NSString * className = nil ;
NSEnumerator * enumerator = [ self . registeredHTTPOperationClassNames reverseObjectEnumerator ] ;
while ( ! operation && ( className = [ enumerator nextObject ] ) ) {
Class op_class = NSClassFromString ( className ) ;
if ( op_class && [ op_class canProcessRequest : urlRequest ] ) {
2012-06-26 09:14:52 -07:00
operation = [ ( AFHTTPRequestOperation * ) [ op_class alloc ] initWithRequest : urlRequest ] ;
2012-07-19 22:23:38 -07:00
}
2011-10-05 15:44:51 -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
}
[ operation setCompletionBlockWithSuccess : success failure : failure ] ;
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-01-19 16:42:12 -08:00
- ( void ) cancelAllHTTPOperationsWithMethod : ( NSString * ) method path : ( NSString * ) path {
2012-07-19 22:23:38 -07:00
for ( NSOperation * operation in [ self . operationQueue operations ] ) {
if ( ! [ operation isKindOfClass : [ AFHTTPRequestOperation class ] ] ) {
continue ;
}
if ( ( ! method || [ method isEqualToString : [ [ ( AFHTTPRequestOperation * ) operation request ] HTTPMethod ] ] ) && [ path isEqualToString : [ [ [ ( AFHTTPRequestOperation * ) operation request ] URL ] path ] ] ) {
[ operation cancel ] ;
}
2011-08-14 20:19:59 -05:00
}
}
2012-08-23 10:16:43 -07:00
- ( void ) enqueueBatchOfHTTPRequestOperationsWithRequests : ( NSArray * ) requests
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 ] ;
for ( NSURLRequest * request in requests ) {
AFHTTPRequestOperation * operation = [ self HTTPRequestOperationWithRequest : request success : nil failure : nil ] ;
[ mutableOperations addObject : operation ] ;
}
[ 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-01 10:45:43 -07:00
# ifdef AF_DISPATCH _RETAIN _RELEASE
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
} ] ;
2012-06-30 16:32:11 -07: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 ] ;
2012-07-19 22:23:38 -07:00
operation . completionBlock = ^ {
2012-07-16 19:21:30 +02:00
dispatch_queue _t queue = operation . successCallbackQueue ? : dispatch_get _main _queue ( ) ;
2012-07-19 22:23:38 -07:00
dispatch_group _async ( dispatchGroup , queue , ^ {
if ( originalCompletionBlock ) {
originalCompletionBlock ( ) ;
}
2012-08-22 11:32:59 -07:00
__block NSUInteger numberOfFinishedOperations = 0 ;
2012-08-22 11:31:49 -07:00
[ operations enumerateObjectsUsingBlock : ^ ( id obj , NSUInteger idx , BOOL * stop ) {
if ( [ ( NSOperation * ) obj isFinished ] ) {
2012-08-22 11:32:59 -07:00
numberOfFinishedOperations + + ;
2012-08-22 11:31:49 -07: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
}
dispatch_group _leave ( dispatchGroup ) ;
} ) ;
} ;
dispatch_group _enter ( dispatchGroup ) ;
[ batchedOperation addDependency : operation ] ;
[ self enqueueHTTPRequestOperation : operation ] ;
}
[ 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" ] ;
self = [ self initWithBaseURL : baseURL ] ;
if ( ! self ) {
return nil ;
}
self . stringEncoding = [ aDecoder decodeIntegerForKey : @ "stringEncoding" ] ;
self . parameterEncoding = [ 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 : 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 ;
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" ;
2012-06-12 22:46:39 -07:00
static NSInteger const kAFStreamToStreamBufferSize = 1024 * 1024 ; // 1 meg default
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 ) ;
return ( __bridge _transfer NSString * ) UTTypeCopyPreferredTagWithClass ( ( __bridge CFStringRef ) UTI , kUTTagClassMIMEType ) ;
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 ;
NSUInteger const kAFUploadStream3GSuggestedDelay = 0.2 ;
2012-08-23 16:21:14 -07:00
@ interface AFHTTPBodyPart : NSObject
2012-09-25 11:06:03 -07:00
2012-08-23 16:21:14 -07:00
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
@ property ( nonatomic , retain ) NSDictionary * headers ;
@ property ( nonatomic , retain ) NSInputStream * inputStream ;
@ property ( nonatomic , assign ) unsigned long long bodyContentLength ;
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 ;
@ property ( readonly , getter = hasBytesAvailable ) BOOL bytesAvailable ;
@ property ( readonly ) unsigned long long contentLength ;
- ( NSInteger ) read : ( uint8_t * ) buffer maxLength : ( NSUInteger ) length ;
2012-06-30 16:32:11 -07:00
2012-08-23 16:21:14 -07:00
@ end
2012-09-25 11:06:03 -07:00
@ interface AFMultipartBodyStream : NSInputStream < NSStreamDelegate >
2011-09-21 14:00:05 -05:00
2012-09-30 17:38:07 -07:00
@ property ( nonatomic , assign ) NSUInteger numberOfBytesInPacket ;
@ property ( nonatomic , assign ) NSTimeInterval delay ;
2012-09-25 11:06:03 -07:00
@ property ( readonly ) unsigned long long contentLength ;
@ property ( 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 ;
@ property ( readwrite , nonatomic , retain ) AFMultipartBodyStream * bodyStream ;
@ 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-08-23 10:16:43 -07:00
- ( id ) initWithURLRequest : ( NSMutableURLRequest * ) request
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 ;
}
2012-08-23 14:33:04 -07:00
2012-08-23 10:16:43 -07:00
self . request = request ;
self . stringEncoding = encoding ;
2012-09-25 09:56:34 -07:00
self . bodyStream = [ [ AFMultipartBodyStream alloc ] initWithStringEncoding : encoding ] ;
2012-08-23 14:33:04 -07: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
{
if ( ! [ fileURL isFileURL ] ) {
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedString ( @ "Expected URL to be a file URL" , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
return NO ;
} else if ( [ fileURL checkResourceIsReachableAndReturnError : error ] = = NO ) {
NSDictionary * userInfo = [ NSDictionary dictionaryWithObject : NSLocalizedString ( @ "File URL not reachable." , nil ) forKey : NSLocalizedFailureReasonErrorKey ] ;
if ( error ! = NULL ) {
* error = [ [ NSError alloc ] initWithDomain : AFNetworkingErrorDomain code : NSURLErrorBadURL userInfo : userInfo ] ;
}
return NO ;
}
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=\" % @ \ "; filename=\" % @ \ "" , name , [ [ fileURL URLByDeletingPathExtension ] lastPathComponent ] ] forKey : @ "Content-Disposition" ] ;
[ mutableHeaders setValue : AFContentTypeForPathExtension ( [ fileURL pathExtension ] ) forKey : @ "Content-Type" ] ;
2012-08-23 10:16:43 -07:00
2012-08-23 14:33:04 -07:00
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
2012-09-26 11:39:28 -07:00
bodyPart . inputStream = [ NSInputStream inputStreamWithURL : fileURL ] ;
NSDictionary * fileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : [ fileURL path ] error : nil ] ;
bodyPart . bodyContentLength = [ [ fileAttributes objectForKey : NSFileSize ] unsignedLongLongValue ] ;
2012-08-23 14:33:04 -07:00
2012-09-25 11:06:03 -07:00
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
2012-09-26 11:39:28 -07:00
return YES ;
2012-08-23 10:16:43 -07:00
}
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-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" ] ;
2012-08-23 14:33:04 -07:00
2012-08-23 16:21:14 -07:00
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
bodyPart . bodyContentLength = [ data length ] ;
2012-09-25 11:06:03 -07:00
bodyPart . inputStream = [ NSInputStream inputStreamWithData : data ] ;
2012-08-23 16:21:14 -07:00
2012-09-25 11:06:03 -07:00
[ self . bodyStream appendHTTPBodyPart : bodyPart ] ;
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-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" ] ;
2012-08-23 14:33:04 -07:00
AFHTTPBodyPart * bodyPart = [ [ AFHTTPBodyPart alloc ] init ] ;
bodyPart . stringEncoding = self . stringEncoding ;
bodyPart . headers = mutableHeaders ;
2012-09-26 11:39:28 -07:00
bodyPart . bodyContentLength = [ data length ] ;
bodyPart . inputStream = [ NSInputStream inputStreamWithData : data ] ;
2012-08-23 14:33:04 -07: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
{
self . bodyStream . numberOfBytesInPacket = numberOfBytes ;
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
}
2012-09-25 10:19:15 -07: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 ] ;
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" ] ;
[ self . request setHTTPBodyStream : self . bodyStream ] ;
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 -
@ interface AFMultipartBodyStream ( )
@ property ( nonatomic , assign ) NSStreamStatus streamStatus ;
@ property ( nonatomic , retain ) NSError * streamError ;
@ property ( nonatomic , assign ) NSStringEncoding stringEncoding ;
@ property ( nonatomic , retain ) NSMutableArray * HTTPBodyParts ;
@ property ( nonatomic , retain ) NSEnumerator * HTTPBodyPartEnumerator ;
@ property ( nonatomic , retain ) AFHTTPBodyPart * currentHTTPBodyPart ;
@ end
2012-07-19 22:23:38 -07:00
2012-08-23 14:33:04 -07:00
@ implementation AFMultipartBodyStream
2012-09-25 11:06:03 -07:00
@ synthesize streamStatus = _streamStatus ;
@ synthesize streamError = _streamError ;
2012-08-23 14:33:04 -07:00
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize HTTPBodyParts = _HTTPBodyParts ;
@ synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator ;
@ synthesize currentHTTPBodyPart = _currentHTTPBodyPart ;
2012-09-30 17:38:07 -07:00
@ synthesize numberOfBytesInPacket = _numberOfBytesInPacket ;
@ 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 ;
}
2012-09-25 11:06:03 -07:00
self . stringEncoding = encoding ;
2012-08-23 16:21:14 -07:00
self . HTTPBodyParts = [ NSMutableArray array ] ;
2012-09-30 17:38:07 -07:00
self . numberOfBytesInPacket = NSIntegerMax ;
2012-08-23 16:21:14 -07:00
2012-08-23 14:33:04 -07:00
return self ;
2011-09-21 14:00:05 -05:00
}
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
}
2012-09-25 10:33:46 -07: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 ] ;
}
2012-09-25 10:33:46 -07:00
- ( BOOL ) isEmpty {
return [ self . HTTPBodyParts count ] = = 0 ;
}
# pragma mark - NSInputStream
- ( NSInteger ) read : ( uint8_t * ) buffer maxLength : ( NSUInteger ) length {
if ( [ self streamStatus ] = = NSStreamStatusClosed ) {
return 0 ;
}
NSInteger bytesRead = 0 ;
2012-09-30 17:38:07 -07:00
while ( ( NSUInteger ) bytesRead < MIN ( length , self . numberOfBytesInPacket ) ) {
2012-09-25 10:33:46 -07:00
if ( ! self . currentHTTPBodyPart || ! [ self . currentHTTPBodyPart hasBytesAvailable ] ) {
if ( ! ( self . currentHTTPBodyPart = [ self . HTTPBodyPartEnumerator nextObject ] ) ) {
break ;
}
} else {
bytesRead + = [ self . currentHTTPBodyPart read : & buffer [ bytesRead ] maxLength : length - bytesRead ] ;
2012-09-30 17:38:07 -07:00
if ( self . delay > 0.0 f ) {
[ NSThread sleepForTimeInterval : self . delay ] ;
}
2012-09-25 10:33:46 -07:00
}
}
2012-09-30 17:38:07 -07:00
2012-09-25 10:33:46 -07:00
return bytesRead ;
}
- ( BOOL ) getBuffer : ( uint8_t * * ) buffer length : ( NSUInteger * ) len {
return NO ;
}
- ( BOOL ) hasBytesAvailable {
return [ self streamStatus ] = = NSStreamStatusOpen ;
}
# pragma mark - NSStream
2012-06-30 16:32:11 -07:00
2012-08-23 10:16:43 -07:00
- ( void ) open {
2012-09-25 10:33:46 -07:00
if ( self . streamStatus = = NSStreamStatusOpen ) {
return ;
2012-08-23 14:33:04 -07:00
}
2012-08-23 16:21:14 -07:00
2012-09-25 11:06:03 -07:00
self . streamStatus = NSStreamStatusOpen ;
2012-09-25 10:33:46 -07:00
[ self setInitialAndFinalBoundaries ] ;
self . HTTPBodyPartEnumerator = [ self . HTTPBodyParts objectEnumerator ] ;
2012-06-30 16:32:11 -07:00
}
2012-08-23 10:16:43 -07:00
- ( void ) close {
2012-09-25 11:06:03 -07:00
self . streamStatus = NSStreamStatusClosed ;
2012-06-30 16:32:11 -07:00
}
- ( id ) propertyForKey : ( NSString * ) key {
2012-08-23 10:16:43 -07:00
return nil ;
2012-06-30 16:32:11 -07:00
}
- ( BOOL ) setProperty : ( id ) property forKey : ( NSString * ) key {
2012-08-23 10:16:43 -07:00
return NO ;
2012-06-30 16:32:11 -07:00
}
2012-09-25 10:33:46 -07:00
- ( void ) scheduleInRunLoop : ( NSRunLoop * ) aRunLoop
forMode : ( NSString * ) mode
{ }
- ( void ) removeFromRunLoop : ( NSRunLoop * ) aRunLoop
forMode : ( NSString * ) mode
{ }
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 ] ;
}
2012-09-25 10:19:15 -07:00
2012-08-23 16:21:14 -07:00
return length ;
}
2012-09-25 10:33:46 -07:00
# pragma mark - Undocumented CFReadStream Bridged Methods
2012-06-30 16:32:11 -07:00
2012-08-23 14:33:04 -07:00
- ( void ) _scheduleInCFRunLoop : ( CFRunLoopRef ) aRunLoop
forMode : ( CFStringRef ) aMode
{ }
- ( void ) _unscheduleFromCFRunLoop : ( CFRunLoopRef ) aRunLoop
forMode : ( CFStringRef ) aMode
{ }
2012-06-30 16:32:11 -07:00
- ( BOOL ) _setCFClientFlags : ( CFOptionFlags ) inFlags
callback : ( CFReadStreamClientCallBack ) inCallback
context : ( CFStreamClientContext * ) inContext {
2012-08-23 16:21:14 -07:00
return NO ;
2012-06-30 16:32:11 -07:00
}
2012-08-23 14:33:04 -07:00
@ end
# pragma mark -
2012-08-23 16:21:14 -07:00
typedef enum {
AFEncapsulationBoundaryPhase = 1 ,
AFHeaderPhase = 2 ,
AFBodyPhase = 3 ,
AFFinalBoundaryPhase = 4 ,
} AFHTTPBodyPartReadPhase ;
@ interface AFHTTPBodyPart ( ) {
2012-08-23 14:33:04 -07:00
AFHTTPBodyPartReadPhase _phase ;
unsigned long long _phaseReadOffset ;
}
2012-08-23 16:21:14 -07:00
- ( BOOL ) transitionToNextPhase ;
@ end
@ implementation AFHTTPBodyPart
2012-08-23 14:33:04 -07:00
@ synthesize stringEncoding = _stringEncoding ;
@ synthesize headers = _headers ;
@ synthesize bodyContentLength = _bodyContentLength ;
2012-09-25 11:06:03 -07:00
@ synthesize inputStream = _inputStream ;
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 ;
}
2012-09-25 10:19:15 -07:00
2012-08-23 14:33:04 -07:00
[ self transitionToNextPhase ] ;
return self ;
}
2012-09-25 10:19:15 -07:00
- ( void ) dealloc {
if ( _inputStream ) {
[ _inputStream close ] ;
_inputStream = nil ;
}
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 ] ;
2012-09-25 10:19:15 -07: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 ;
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 ] ;
2012-09-25 10:19:15 -07:00
2012-08-23 14:33:04 -07:00
return length ;
}
2012-09-25 10:33:46 -07:00
- ( BOOL ) hasBytesAvailable {
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 :
return NO ;
}
}
2012-08-23 14:33:04 -07:00
- ( NSInteger ) read : ( uint8_t * ) buffer maxLength : ( NSUInteger ) length {
NSInteger bytesRead = 0 ;
2012-09-25 10:19:15 -07:00
2012-08-23 14:33:04 -07:00
if ( _phase = = AFEncapsulationBoundaryPhase ) {
NSData * encapsulationBoundaryData = [ ( [ self hasInitialBoundary ] ? AFMultipartFormInitialBoundary ( ) : AFMultipartFormEncapsulationBoundary ( ) ) dataUsingEncoding : self . stringEncoding ] ;
2012-09-25 03:33:51 +08:00
bytesRead + = [ self readData : encapsulationBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
if ( _phase = = AFHeaderPhase ) {
NSData * headersData = [ [ self stringForHeaders ] dataUsingEncoding : self . stringEncoding ] ;
2012-09-25 03:33:51 +08:00
bytesRead + = [ self readData : headersData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
if ( _phase = = AFBodyPhase ) {
if ( [ self . inputStream hasBytesAvailable ] ) {
2012-09-25 03:33:51 +08:00
bytesRead + = [ self . inputStream read : & buffer [ bytesRead ] maxLength : ( length - bytesRead ) ] ;
2012-08-23 16:21:14 -07:00
}
if ( ! [ self . inputStream hasBytesAvailable ] ) {
2012-08-23 14:33:04 -07:00
[ self transitionToNextPhase ] ;
}
}
if ( _phase = = AFFinalBoundaryPhase ) {
NSData * closingBoundaryData = ( [ self hasFinalBoundary ] ? [ AFMultipartFormFinalBoundary ( ) dataUsingEncoding : self . stringEncoding ] : [ NSData data ] ) ;
2012-09-25 03:33:51 +08:00
bytesRead + = [ self readData : closingBoundaryData intoBuffer : & buffer [ bytesRead ] maxLength : ( length - bytesRead ) ] ;
2012-08-23 14:33:04 -07:00
}
2012-09-25 10:19:15 -07: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
{
NSRange range = NSMakeRange ( _phaseReadOffset , MIN ( [ data length ] , length ) ) ;
[ data getBytes : buffer range : range ] ;
_phaseReadOffset + = range . length ;
if ( range . length >= [ data length ] ) {
[ self transitionToNextPhase ] ;
}
return range . length ;
}
- ( BOOL ) transitionToNextPhase {
if ( ! [ [ NSThread currentThread ] isMainThread ] ) {
[ self performSelectorOnMainThread : @ selector ( transitionToNextPhase ) withObject : nil waitUntilDone : YES ] ;
return YES ;
}
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 ;
2012-10-02 09:41:57 -07:00
default :
2012-09-25 10:33:46 -07:00
_phase = AFEncapsulationBoundaryPhase ;
break ;
2012-08-23 14:33:04 -07:00
}
2012-09-25 10:33:46 -07:00
_phaseReadOffset = 0 ;
return YES ;
2012-08-23 14:33:04 -07:00
}
@ end