Merge branch 'master' into invalid-ssl
This commit is contained in:
commit
bcb8aea682
17 changed files with 719 additions and 329 deletions
|
|
@ -1,22 +1,25 @@
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'AFNetworking'
|
s.name = 'AFNetworking'
|
||||||
s.version = '1.1.0'
|
s.version = '1.2.0'
|
||||||
s.license = 'MIT'
|
s.license = 'MIT'
|
||||||
s.summary = 'A delightful iOS and OS X networking framework.'
|
s.summary = 'A delightful iOS and OS X networking framework.'
|
||||||
s.homepage = 'https://github.com/AFNetworking/AFNetworking'
|
s.homepage = 'https://github.com/AFNetworking/AFNetworking'
|
||||||
s.authors = { 'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com' }
|
s.authors = { 'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com' }
|
||||||
s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', :tag => '1.1.0' }
|
s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', :tag => '1.2.0' }
|
||||||
s.source_files = 'AFNetworking'
|
s.source_files = 'AFNetworking'
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
|
|
||||||
s.ios.deployment_target = '5.0'
|
s.ios.deployment_target = '5.0'
|
||||||
s.ios.frameworks = 'MobileCoreServices', 'SystemConfiguration'
|
s.ios.frameworks = 'MobileCoreServices', 'SystemConfiguration', 'Security'
|
||||||
|
|
||||||
s.osx.deployment_target = '10.7'
|
s.osx.deployment_target = '10.7'
|
||||||
s.osx.frameworks = 'CoreServices', 'SystemConfiguration'
|
s.osx.frameworks = 'CoreServices', 'SystemConfiguration', 'Security'
|
||||||
|
|
||||||
s.prefix_header_contents = <<-EOS
|
s.prefix_header_contents = <<-EOS
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
#import <SystemConfiguration/SystemConfiguration.h>
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
#import <MobileCoreServices/MobileCoreServices.h>
|
#import <MobileCoreServices/MobileCoreServices.h>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "AFURLConnectionOperation.h"
|
||||||
|
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
|
@ -137,6 +138,13 @@ typedef enum {
|
||||||
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Default SSL pinning mode for each `AFHTTPRequestOperation` which will be enqueued with `enqueueHTTPRequestOperation:`.
|
||||||
|
*/
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
///---------------------------------------------
|
///---------------------------------------------
|
||||||
/// @name Creating and Initializing HTTP Clients
|
/// @name Creating and Initializing HTTP Clients
|
||||||
///---------------------------------------------
|
///---------------------------------------------
|
||||||
|
|
@ -440,7 +448,7 @@ typedef enum {
|
||||||
///----------------
|
///----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
### Network Reachability
|
## Network Reachability
|
||||||
|
|
||||||
The following constants are provided by `AFHTTPClient` as possible network reachability statuses.
|
The following constants are provided by `AFHTTPClient` as possible network reachability statuses.
|
||||||
|
|
||||||
|
|
@ -471,7 +479,7 @@ typedef enum {
|
||||||
A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification.
|
A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification.
|
||||||
The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status.
|
The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status.
|
||||||
|
|
||||||
### Parameter Encoding
|
## Parameter Encoding
|
||||||
|
|
||||||
The following constants are provided by `AFHTTPClient` as possible methods for serializing parameters into query string or message body values.
|
The following constants are provided by `AFHTTPClient` as possible methods for serializing parameters into query string or message body values.
|
||||||
|
|
||||||
|
|
@ -543,12 +551,44 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
|
||||||
|
|
||||||
@return `YES` if the file data was successfully appended, otherwise `NO`.
|
@return `YES` if the file data was successfully appended, otherwise `NO`.
|
||||||
|
|
||||||
@discussion The filename and MIME type for this data in the form will be automatically generated, using `NSURLResponse` `-suggestedFilename` and `-MIMEType`, respectively.
|
@discussion The filename and MIME type for this data in the form will be automatically generated, using the last path component of the `fileURL` and system associated MIME type for the `fileURL` extension, respectively.
|
||||||
*/
|
*/
|
||||||
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
||||||
name:(NSString *)name
|
name:(NSString *)name
|
||||||
error:(NSError * __autoreleasing *)error;
|
error:(NSError * __autoreleasing *)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
||||||
|
|
||||||
|
@param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`.
|
||||||
|
@param name The name to be associated with the specified data. This parameter must not be `nil`.
|
||||||
|
@param fileName The file name to be used in the `Content-Disposition` header. This parameter must not be `nil`.
|
||||||
|
@param mimeType The declared MIME type of the file data. This parameter must not be `nil`.
|
||||||
|
@param error If an error occurs, upon return contains an `NSError` object that describes the problem.
|
||||||
|
|
||||||
|
@return `YES` if the file data was successfully appended otherwise `NO`.
|
||||||
|
*/
|
||||||
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
mimeType:(NSString *)mimeType
|
||||||
|
error:(NSError * __autoreleasing *)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary.
|
||||||
|
|
||||||
|
@param inputStream The input stream to be appended to the form data
|
||||||
|
@param name The name to be associated with the specified input stream. This parameter must not be `nil`.
|
||||||
|
@param fileName The filename to be associated with the specified input stream. This parameter must not be `nil`.
|
||||||
|
@param length The length of the specified input stream in bytes.
|
||||||
|
@param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`.
|
||||||
|
*/
|
||||||
|
- (void)appendPartWithInputStream:(NSInputStream *)inputStream
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
length:(unsigned long long)length
|
||||||
|
mimeType:(NSString *)mimeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
||||||
|
|
||||||
|
|
@ -572,6 +612,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
|
||||||
- (void)appendPartWithFormData:(NSData *)data
|
- (void)appendPartWithFormData:(NSData *)data
|
||||||
name:(NSString *)name;
|
name:(NSString *)name;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends HTTP headers, followed by the encoded data and the multipart form boundary.
|
Appends HTTP headers, followed by the encoded data and the multipart form boundary.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
||||||
static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~'";
|
static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',*";
|
||||||
static NSString * const kAFCharactersToLeaveUnescaped = @"[].";
|
static NSString * const kAFCharactersToLeaveUnescaped = @"[].";
|
||||||
|
|
||||||
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
||||||
|
|
@ -146,10 +146,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||||
|
|
||||||
if ([value isKindOfClass:[NSDictionary class]]) {
|
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
|
// 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:)];
|
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(caseInsensitiveCompare:)];
|
||||||
[[[value allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) {
|
[[[dictionary allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) {
|
||||||
id nestedValue = [value objectForKey:nestedKey];
|
id nestedValue = [dictionary objectForKey:nestedKey];
|
||||||
if (nestedValue) {
|
if (nestedValue) {
|
||||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
||||||
}
|
}
|
||||||
|
|
@ -159,6 +160,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
[array enumerateObjectsUsingBlock:^(id nestedValue, __unused NSUInteger idx, __unused BOOL *stop) {
|
[array enumerateObjectsUsingBlock:^(id nestedValue, __unused NSUInteger idx, __unused BOOL *stop) {
|
||||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
||||||
}];
|
}];
|
||||||
|
} else if ([value isKindOfClass:[NSSet class]]) {
|
||||||
|
NSSet *set = value;
|
||||||
|
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||||
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
|
||||||
|
}];
|
||||||
} else {
|
} else {
|
||||||
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
||||||
}
|
}
|
||||||
|
|
@ -234,8 +240,13 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
self.defaultHeaders = [NSMutableDictionary dictionary];
|
self.defaultHeaders = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
||||||
NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
|
||||||
[self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
[[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||||
|
float q = 1.0f - (idx * 0.1f);
|
||||||
|
[acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
|
||||||
|
*stop = q <= 0.5f;
|
||||||
|
}];
|
||||||
|
[self setDefaultHeader:@"Accept-Language" value:[acceptLanguagesComponents componentsJoinedByString:@", "]];
|
||||||
|
|
||||||
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||||
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
|
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
|
||||||
|
|
@ -304,7 +315,8 @@ static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused targ
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
|
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -505,12 +517,12 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
||||||
{
|
{
|
||||||
AFHTTPRequestOperation *operation = nil;
|
AFHTTPRequestOperation *operation = nil;
|
||||||
NSString *className = nil;
|
|
||||||
NSEnumerator *enumerator = [self.registeredHTTPOperationClassNames reverseObjectEnumerator];
|
for (NSString *className in self.registeredHTTPOperationClassNames) {
|
||||||
while (!operation && (className = [enumerator nextObject])) {
|
Class operationClass = NSClassFromString(className);
|
||||||
Class op_class = NSClassFromString(className);
|
if (operationClass && [operationClass canProcessRequest:urlRequest]) {
|
||||||
if (op_class && [op_class canProcessRequest:urlRequest]) {
|
operation = [(AFHTTPRequestOperation *)[operationClass alloc] initWithRequest:urlRequest];
|
||||||
operation = [(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest];
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,6 +533,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
[operation setCompletionBlockWithSuccess:success failure:failure];
|
[operation setCompletionBlockWithSuccess:success failure:failure];
|
||||||
|
|
||||||
operation.credential = self.defaultCredential;
|
operation.credential = self.defaultCredential;
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
operation.SSLPinningMode = self.defaultSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
|
|
@ -534,7 +549,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
- (void)cancelAllHTTPOperationsWithMethod:(NSString *)method
|
- (void)cancelAllHTTPOperationsWithMethod:(NSString *)method
|
||||||
path:(NSString *)path
|
path:(NSString *)path
|
||||||
{
|
{
|
||||||
NSString *URLStringToMatched = [[[self requestWithMethod:(method ?: @"GET") path:path parameters:nil] URL] absoluteString];
|
NSString *pathToBeMatched = [[[self requestWithMethod:(method ?: @"GET") path:path parameters:nil] URL] path];
|
||||||
|
|
||||||
for (NSOperation *operation in [self.operationQueue operations]) {
|
for (NSOperation *operation in [self.operationQueue operations]) {
|
||||||
if (![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
|
if (![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
|
||||||
|
|
@ -542,9 +557,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL hasMatchingMethod = !method || [method isEqualToString:[[(AFHTTPRequestOperation *)operation request] HTTPMethod]];
|
BOOL hasMatchingMethod = !method || [method isEqualToString:[[(AFHTTPRequestOperation *)operation request] HTTPMethod]];
|
||||||
BOOL hasMatchingURL = [[[[(AFHTTPRequestOperation *)operation request] URL] absoluteString] isEqualToString:URLStringToMatched];
|
BOOL hasMatchingPath = [[[[(AFHTTPRequestOperation *)operation request] URL] path] isEqual:pathToBeMatched];
|
||||||
|
|
||||||
if (hasMatchingMethod && hasMatchingURL) {
|
if (hasMatchingMethod && hasMatchingPath) {
|
||||||
[operation cancel];
|
[operation cancel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -581,9 +596,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
|
|
||||||
for (AFHTTPRequestOperation *operation in operations) {
|
for (AFHTTPRequestOperation *operation in operations) {
|
||||||
AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
||||||
__weak AFHTTPRequestOperation *weakOperation = operation;
|
__weak __typeof(&*operation)weakOperation = operation;
|
||||||
operation.completionBlock = ^{
|
operation.completionBlock = ^{
|
||||||
dispatch_queue_t queue = weakOperation.successCallbackQueue ?: dispatch_get_main_queue();
|
__strong __typeof(&*weakOperation)strongOperation = weakOperation;
|
||||||
|
dispatch_queue_t queue = strongOperation.successCallbackQueue ?: dispatch_get_main_queue();
|
||||||
dispatch_group_async(dispatchGroup, queue, ^{
|
dispatch_group_async(dispatchGroup, queue, ^{
|
||||||
if (originalCompletionBlock) {
|
if (originalCompletionBlock) {
|
||||||
originalCompletionBlock();
|
originalCompletionBlock();
|
||||||
|
|
@ -729,7 +745,12 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
||||||
#ifdef __UTTYPE__
|
#ifdef __UTTYPE__
|
||||||
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
|
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
|
||||||
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
|
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
|
||||||
|
if (!contentType) {
|
||||||
|
return @"application/octet-stream";
|
||||||
|
} else {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return @"application/octet-stream";
|
return @"application/octet-stream";
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -755,9 +776,10 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
maxLength:(NSUInteger)length;
|
maxLength:(NSUInteger)length;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
@interface AFMultipartBodyStreamProvider : NSObject
|
||||||
@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
|
@property (nonatomic, assign) NSUInteger bufferLength;
|
||||||
@property (nonatomic, assign) NSTimeInterval delay;
|
@property (nonatomic, assign) NSTimeInterval delay;
|
||||||
|
@property (nonatomic, readonly) NSInputStream *inputStream;
|
||||||
@property (nonatomic, readonly) unsigned long long contentLength;
|
@property (nonatomic, readonly) unsigned long long contentLength;
|
||||||
@property (nonatomic, readonly, getter = isEmpty) BOOL empty;
|
@property (nonatomic, readonly, getter = isEmpty) BOOL empty;
|
||||||
|
|
||||||
|
|
@ -770,7 +792,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
@interface AFStreamingMultipartFormData ()
|
@interface AFStreamingMultipartFormData ()
|
||||||
@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
|
@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
|
||||||
@property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream;
|
@property (readwrite, nonatomic, strong) AFMultipartBodyStreamProvider *bodyStream;
|
||||||
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
@ -789,7 +811,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
self.request = urlRequest;
|
self.request = urlRequest;
|
||||||
self.stringEncoding = encoding;
|
self.stringEncoding = encoding;
|
||||||
self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
|
self.bodyStream = [[AFMultipartBodyStreamProvider alloc] initWithStringEncoding:encoding];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -801,6 +823,23 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
NSParameterAssert(fileURL);
|
NSParameterAssert(fileURL);
|
||||||
NSParameterAssert(name);
|
NSParameterAssert(name);
|
||||||
|
|
||||||
|
NSString *fileName = [fileURL lastPathComponent];
|
||||||
|
NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]);
|
||||||
|
|
||||||
|
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]) {
|
if (![fileURL isFileURL]) {
|
||||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
|
|
@ -818,8 +857,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, [fileURL lastPathComponent]] forKey:@"Content-Disposition"];
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
||||||
[mutableHeaders setValue:AFContentTypeForPathExtension([fileURL pathExtension]) forKey:@"Content-Type"];
|
[mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
||||||
|
|
||||||
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
||||||
bodyPart.stringEncoding = self.stringEncoding;
|
bodyPart.stringEncoding = self.stringEncoding;
|
||||||
|
|
@ -834,6 +873,32 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
return YES;
|
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
|
- (void)appendPartWithFileData:(NSData *)data
|
||||||
name:(NSString *)name
|
name:(NSString *)name
|
||||||
fileName:(NSString *)fileName
|
fileName:(NSString *)fileName
|
||||||
|
|
@ -878,7 +943,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
||||||
delay:(NSTimeInterval)delay
|
delay:(NSTimeInterval)delay
|
||||||
{
|
{
|
||||||
self.bodyStream.numberOfBytesInPacket = numberOfBytes;
|
self.bodyStream.bufferLength = numberOfBytes;
|
||||||
self.bodyStream.delay = delay;
|
self.bodyStream.delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -892,7 +957,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
[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 setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
|
||||||
[self.request setHTTPBodyStream:self.bodyStream];
|
[self.request setHTTPBodyStream:self.bodyStream.inputStream];
|
||||||
|
|
||||||
return self.request;
|
return self.request;
|
||||||
}
|
}
|
||||||
|
|
@ -901,24 +966,31 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
@interface AFMultipartBodyStream () <NSCopying>
|
@interface AFMultipartBodyStreamProvider () <NSCopying, NSStreamDelegate>
|
||||||
@property (nonatomic, assign) NSStreamStatus streamStatus;
|
|
||||||
@property (nonatomic, strong) NSError *streamError;
|
|
||||||
|
|
||||||
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
@property (nonatomic, strong) NSMutableArray *HTTPBodyParts;
|
@property (nonatomic, strong) NSMutableArray *HTTPBodyParts;
|
||||||
@property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
|
@property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
|
||||||
@property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
|
@property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
|
||||||
|
@property (nonatomic, strong) NSInputStream *inputStream;
|
||||||
|
@property (nonatomic, strong) NSOutputStream *outputStream;
|
||||||
|
@property (nonatomic, strong) NSMutableData *buffer;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFMultipartBodyStream
|
static const NSUInteger AFMultipartBodyStreamProviderDefaultBufferLength = 4096;
|
||||||
@synthesize streamStatus = _streamStatus;
|
|
||||||
@synthesize streamError = _streamError;
|
@implementation AFMultipartBodyStreamProvider {
|
||||||
|
@private
|
||||||
|
// Workaround for stream delegates being weakly referenced, but otherwise unowned
|
||||||
|
__strong id _self;
|
||||||
|
}
|
||||||
@synthesize stringEncoding = _stringEncoding;
|
@synthesize stringEncoding = _stringEncoding;
|
||||||
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
||||||
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
||||||
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
||||||
@synthesize numberOfBytesInPacket = _numberOfBytesInPacket;
|
@synthesize inputStream = _inputStream;
|
||||||
|
@synthesize outputStream = _outputStream;
|
||||||
|
@synthesize buffer = _buffer;
|
||||||
|
@synthesize bufferLength = _numberOfBytesInPacket;
|
||||||
@synthesize delay = _delay;
|
@synthesize delay = _delay;
|
||||||
|
|
||||||
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
||||||
|
|
@ -929,11 +1001,18 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
self.stringEncoding = encoding;
|
self.stringEncoding = encoding;
|
||||||
self.HTTPBodyParts = [NSMutableArray array];
|
self.HTTPBodyParts = [NSMutableArray array];
|
||||||
self.numberOfBytesInPacket = NSIntegerMax;
|
self.bufferLength = NSIntegerMax;
|
||||||
|
|
||||||
|
self.buffer = [[NSMutableData alloc] init];
|
||||||
|
self.bufferLength = AFMultipartBodyStreamProviderDefaultBufferLength;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
_outputStream.delegate = nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setInitialAndFinalBoundaries {
|
- (void)setInitialAndFinalBoundaries {
|
||||||
if ([self.HTTPBodyParts count] > 0) {
|
if ([self.HTTPBodyParts count] > 0) {
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
|
|
@ -950,80 +1029,95 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
[self.HTTPBodyParts addObject:bodyPart];
|
[self.HTTPBodyParts addObject:bodyPart];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSInputStream *)inputStream {
|
||||||
|
if (_inputStream == nil) {
|
||||||
|
CFReadStreamRef readStream;
|
||||||
|
CFWriteStreamRef writeStream;
|
||||||
|
CFStreamCreateBoundPair(NULL, &readStream, &writeStream, self.bufferLength);
|
||||||
|
_inputStream = CFBridgingRelease(readStream);
|
||||||
|
_outputStream = CFBridgingRelease(writeStream);
|
||||||
|
|
||||||
|
_outputStream.delegate = self;
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
|
} else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
[_outputStream open];
|
||||||
|
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)isEmpty {
|
- (BOOL)isEmpty {
|
||||||
return [self.HTTPBodyParts count] == 0;
|
return [self.HTTPBodyParts count] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSInputStream
|
#pragma mark - NSStreamDelegate
|
||||||
|
|
||||||
- (NSInteger)read:(uint8_t *)buffer
|
- (void)stream:(NSStream *)stream
|
||||||
maxLength:(NSUInteger)length
|
handleEvent:(NSStreamEvent)eventCode
|
||||||
{
|
{
|
||||||
if ([self streamStatus] == NSStreamStatusClosed) {
|
if (eventCode & NSStreamEventHasSpaceAvailable) {
|
||||||
return 0;
|
[self handleOutputStreamSpaceAvailable];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NSInteger bytesRead = 0;
|
|
||||||
|
|
||||||
while ((NSUInteger)bytesRead < MIN(length, self.numberOfBytesInPacket)) {
|
- (void)handleOutputStreamSpaceAvailable {
|
||||||
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
|
while ([_outputStream hasSpaceAvailable]) {
|
||||||
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
|
if ([_buffer length] > 0) {
|
||||||
break;
|
NSInteger numberOfBytesWritten = [_outputStream write:[_buffer bytes] maxLength:[_buffer length]];
|
||||||
|
if (numberOfBytesWritten < 0) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[_buffer replaceBytesInRange:NSMakeRange(0, numberOfBytesWritten) withBytes:NULL length:0];
|
||||||
} else {
|
} else {
|
||||||
bytesRead += [self.currentHTTPBodyPart read:&buffer[bytesRead] maxLength:(length - (NSUInteger)bytesRead)];
|
if (!self.currentHTTPBodyPart) {
|
||||||
|
if (!self.HTTPBodyPartEnumerator) {
|
||||||
|
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
|
||||||
|
}
|
||||||
|
self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.currentHTTPBodyPart) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_buffer setLength:self.bufferLength];
|
||||||
|
|
||||||
|
NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:[_buffer mutableBytes] maxLength:[_buffer length]];
|
||||||
|
if (numberOfBytesRead < 0) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_buffer setLength:numberOfBytesRead];
|
||||||
|
|
||||||
|
if(numberOfBytesRead == 0) {
|
||||||
|
self.currentHTTPBodyPart = nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.delay > 0.0f) {
|
if (self.delay > 0.0f) {
|
||||||
[NSThread sleepForTimeInterval:self.delay];
|
[NSThread sleepForTimeInterval:self.delay];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)getBuffer:(__unused uint8_t **)buffer
|
|
||||||
length:(__unused NSUInteger *)len
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (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 {
|
- (void)close {
|
||||||
self.streamStatus = NSStreamStatusClosed;
|
[_outputStream close];
|
||||||
|
_outputStream.delegate = nil;
|
||||||
|
|
||||||
|
_self = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)propertyForKey:(__unused NSString *)key {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)setProperty:(__unused id)property
|
|
||||||
forKey:(__unused NSString *)key
|
|
||||||
{
|
|
||||||
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)contentLength {
|
||||||
unsigned long long length = 0;
|
unsigned long long length = 0;
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
|
|
@ -1033,26 +1127,10 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
return length;
|
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
|
#pragma mark - NSCopying
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone *)zone {
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
|
AFMultipartBodyStreamProvider *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
|
||||||
|
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
[bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
|
[bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
|
||||||
|
|
@ -1068,10 +1146,12 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
AFInitialPhase = 0,
|
||||||
AFEncapsulationBoundaryPhase = 1,
|
AFEncapsulationBoundaryPhase = 1,
|
||||||
AFHeaderPhase = 2,
|
AFHeaderPhase = 2,
|
||||||
AFBodyPhase = 3,
|
AFBodyPhase = 3,
|
||||||
AFFinalBoundaryPhase = 4,
|
AFFinalBoundaryPhase = 4,
|
||||||
|
AFCompletedPhase = 5,
|
||||||
} AFHTTPBodyPartReadPhase;
|
} AFHTTPBodyPartReadPhase;
|
||||||
|
|
||||||
@interface AFHTTPBodyPart () <NSCopying> {
|
@interface AFHTTPBodyPart () <NSCopying> {
|
||||||
|
|
@ -1118,6 +1198,8 @@ typedef enum {
|
||||||
_inputStream = [NSInputStream inputStreamWithData:self.body];
|
_inputStream = [NSInputStream inputStreamWithData:self.body];
|
||||||
} else if ([self.body isKindOfClass:[NSURL class]]) {
|
} else if ([self.body isKindOfClass:[NSURL class]]) {
|
||||||
_inputStream = [NSInputStream inputStreamWithURL:self.body];
|
_inputStream = [NSInputStream inputStreamWithURL:self.body];
|
||||||
|
} else if ([self.body isKindOfClass:[NSInputStream class]]) {
|
||||||
|
_inputStream = self.body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1152,11 +1234,13 @@ typedef enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)hasBytesAvailable {
|
- (BOOL)hasBytesAvailable {
|
||||||
// Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the avaiable buffer
|
// Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the available buffer
|
||||||
if (_phase == AFFinalBoundaryPhase) {
|
if (_phase == AFFinalBoundaryPhase) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
switch (self.inputStream.streamStatus) {
|
switch (self.inputStream.streamStatus) {
|
||||||
case NSStreamStatusNotOpen:
|
case NSStreamStatusNotOpen:
|
||||||
case NSStreamStatusOpening:
|
case NSStreamStatusOpening:
|
||||||
|
|
@ -1170,6 +1254,8 @@ typedef enum {
|
||||||
default:
|
default:
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)read:(uint8_t *)buffer
|
- (NSInteger)read:(uint8_t *)buffer
|
||||||
|
|
@ -1227,7 +1313,12 @@ typedef enum {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
switch (_phase) {
|
switch (_phase) {
|
||||||
|
case AFInitialPhase:
|
||||||
|
_phase = AFEncapsulationBoundaryPhase;
|
||||||
|
break;
|
||||||
case AFEncapsulationBoundaryPhase:
|
case AFEncapsulationBoundaryPhase:
|
||||||
_phase = AFHeaderPhase;
|
_phase = AFHeaderPhase;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1241,10 +1332,13 @@ typedef enum {
|
||||||
_phase = AFFinalBoundaryPhase;
|
_phase = AFFinalBoundaryPhase;
|
||||||
break;
|
break;
|
||||||
case AFFinalBoundaryPhase:
|
case AFFinalBoundaryPhase:
|
||||||
_phase = AFEncapsulationBoundaryPhase;
|
case AFCompletedPhase:
|
||||||
|
default:
|
||||||
|
_phase = AFCompletedPhase;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_phaseReadOffset = 0;
|
_phaseReadOffset = 0;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#define AF_CAST_TO_BLOCK __bridge void *
|
#define AF_CAST_TO_BLOCK __bridge void *
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We do a little bit of duck typing in this file which can trigger this warning. Turn it off for this source file.
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wstrict-selector-match"
|
#pragma clang diagnostic ignored "-Wstrict-selector-match"
|
||||||
|
|
||||||
|
|
@ -108,18 +107,12 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
@property (readwrite, nonatomic, strong) NSURLRequest *request;
|
@property (readwrite, nonatomic, strong) NSURLRequest *request;
|
||||||
@property (readwrite, nonatomic, strong) NSHTTPURLResponse *response;
|
@property (readwrite, nonatomic, strong) NSHTTPURLResponse *response;
|
||||||
@property (readwrite, nonatomic, strong) NSError *HTTPError;
|
@property (readwrite, nonatomic, strong) NSError *HTTPError;
|
||||||
@property (readwrite, nonatomic, copy) NSString *HTTPResponseString;
|
|
||||||
@property (readwrite, nonatomic, assign) long long totalContentLength;
|
|
||||||
@property (readwrite, nonatomic, assign) long long offsetContentLength;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFHTTPRequestOperation
|
@implementation AFHTTPRequestOperation
|
||||||
@synthesize HTTPError = _HTTPError;
|
@synthesize HTTPError = _HTTPError;
|
||||||
@synthesize HTTPResponseString = _HTTPResponseString;
|
|
||||||
@synthesize successCallbackQueue = _successCallbackQueue;
|
@synthesize successCallbackQueue = _successCallbackQueue;
|
||||||
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
||||||
@synthesize totalContentLength = _totalContentLength;
|
|
||||||
@synthesize offsetContentLength = _offsetContentLength;
|
|
||||||
@dynamic request;
|
@dynamic request;
|
||||||
@dynamic response;
|
@dynamic response;
|
||||||
|
|
||||||
|
|
@ -169,23 +162,19 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)responseString {
|
- (NSStringEncoding)responseStringEncoding {
|
||||||
// When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value.
|
// When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value.
|
||||||
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4.1
|
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4.1
|
||||||
if (!self.HTTPResponseString && self.response && !self.response.textEncodingName && self.responseData) {
|
if (self.response && !self.response.textEncodingName && self.responseData) {
|
||||||
NSString *type = nil;
|
NSString *type = nil;
|
||||||
AFGetMediaTypeAndSubtypeWithString([[self.response allHeaderFields] valueForKey:@"Content-Type"], &type, nil);
|
AFGetMediaTypeAndSubtypeWithString([[self.response allHeaderFields] valueForKey:@"Content-Type"], &type, nil);
|
||||||
|
|
||||||
if ([type isEqualToString:@"text"]) {
|
if ([type isEqualToString:@"text"]) {
|
||||||
self.HTTPResponseString = [[NSString alloc] initWithData:self.responseData encoding:NSISOLatin1StringEncoding];
|
return NSISOLatin1StringEncoding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.HTTPResponseString) {
|
return [super responseStringEncoding];
|
||||||
return self.HTTPResponseString;
|
|
||||||
} else {
|
|
||||||
return [super responseString];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pause {
|
- (void)pause {
|
||||||
|
|
@ -324,46 +313,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
return [[self acceptableContentTypes] intersectsSet:AFContentTypesFromHTTPHeader([request valueForHTTPHeaderField:@"Accept"])];
|
return [[self acceptableContentTypes] intersectsSet:AFContentTypesFromHTTPHeader([request valueForHTTPHeaderField:@"Accept"])];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSURLConnectionDelegate
|
|
||||||
|
|
||||||
- (void)connection:(__unused NSURLConnection *)connection
|
|
||||||
didReceiveResponse:(NSURLResponse *)response
|
|
||||||
{
|
|
||||||
self.response = (NSHTTPURLResponse *)response;
|
|
||||||
|
|
||||||
// Set Content-Range header if status code of response is 206 (Partial Content)
|
|
||||||
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7
|
|
||||||
long long totalContentLength = self.response.expectedContentLength;
|
|
||||||
long long fileOffset = 0;
|
|
||||||
NSUInteger statusCode = ([self.response isKindOfClass:[NSHTTPURLResponse class]]) ? (NSUInteger)[self.response statusCode] : 200;
|
|
||||||
if (statusCode == 206) {
|
|
||||||
NSString *contentRange = [self.response.allHeaderFields valueForKey:@"Content-Range"];
|
|
||||||
if ([contentRange hasPrefix:@"bytes"]) {
|
|
||||||
NSArray *byteRanges = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];
|
|
||||||
if ([byteRanges count] == 4) {
|
|
||||||
fileOffset = [[byteRanges objectAtIndex:1] longLongValue];
|
|
||||||
totalContentLength = [[byteRanges objectAtIndex:2] longLongValue] ?: -1; // if this is "*", it's converted to 0, but -1 is default.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
|
|
||||||
[self.outputStream setProperty:[NSNumber numberWithInteger:0] forKey:NSStreamFileCurrentOffsetKey];
|
|
||||||
} else {
|
|
||||||
if ([[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length] > 0) {
|
|
||||||
self.outputStream = [NSOutputStream outputStreamToMemory];
|
|
||||||
|
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
|
||||||
for (NSString *runLoopMode in self.runLoopModes) {
|
|
||||||
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.offsetContentLength = MAX(fileOffset, 0);
|
|
||||||
self.totalContentLength = totalContentLength;
|
|
||||||
|
|
||||||
[self.outputStream open];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFImageRequestOperation.h"
|
#import "AFImageRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_image_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t image_request_operation_processing_queue() {
|
static dispatch_queue_t image_request_operation_processing_queue() {
|
||||||
if (af_image_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_image_request_operation_processing_queue;
|
||||||
af_image_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.image-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_image_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.image-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_image_request_operation_processing_queue;
|
return af_image_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFJSONRequestOperation.h"
|
#import "AFJSONRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_json_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t json_request_operation_processing_queue() {
|
static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
if (af_json_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_json_request_operation_processing_queue;
|
||||||
af_json_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.json-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_json_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.json-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_json_request_operation_processing_queue;
|
return af_json_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
@ -34,12 +35,14 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
@interface AFJSONRequestOperation ()
|
@interface AFJSONRequestOperation ()
|
||||||
@property (readwrite, nonatomic, strong) id responseJSON;
|
@property (readwrite, nonatomic, strong) id responseJSON;
|
||||||
@property (readwrite, nonatomic, strong) NSError *JSONError;
|
@property (readwrite, nonatomic, strong) NSError *JSONError;
|
||||||
|
@property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFJSONRequestOperation
|
@implementation AFJSONRequestOperation
|
||||||
@synthesize responseJSON = _responseJSON;
|
@synthesize responseJSON = _responseJSON;
|
||||||
@synthesize JSONReadingOptions = _JSONReadingOptions;
|
@synthesize JSONReadingOptions = _JSONReadingOptions;
|
||||||
@synthesize JSONError = _JSONError;
|
@synthesize JSONError = _JSONError;
|
||||||
|
@dynamic lock;
|
||||||
|
|
||||||
+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
|
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
|
||||||
|
|
@ -61,6 +64,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
|
|
||||||
|
|
||||||
- (id)responseJSON {
|
- (id)responseJSON {
|
||||||
|
[self.lock lock];
|
||||||
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
|
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
|
||||||
|
|
@ -77,6 +81,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
|
|
||||||
self.JSONError = error;
|
self.JSONError = error;
|
||||||
}
|
}
|
||||||
|
[self.lock unlock];
|
||||||
|
|
||||||
return _responseJSON;
|
return _responseJSON;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incrementActivityCount) name:AFNetworkingOperationDidStartNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidStart:) name:AFNetworkingOperationDidStartNotification object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(decrementActivityCount) name:AFNetworkingOperationDidFinishNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidFinish:) name:AFNetworkingOperationDidFinishNotification object:nil];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -126,6 +126,20 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17;
|
||||||
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)networkingOperationDidStart:(NSNotification *)notification {
|
||||||
|
AFURLConnectionOperation *connectionOperation = [notification object];
|
||||||
|
if (connectionOperation.request.URL) {
|
||||||
|
[self incrementActivityCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)networkingOperationDidFinish:(NSNotification *)notification {
|
||||||
|
AFURLConnectionOperation *connectionOperation = [notification object];
|
||||||
|
if (connectionOperation.request.URL) {
|
||||||
|
[self decrementActivityCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFPropertyListRequestOperation.h"
|
#import "AFPropertyListRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_property_list_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t property_list_request_operation_processing_queue() {
|
static dispatch_queue_t property_list_request_operation_processing_queue() {
|
||||||
if (af_property_list_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_property_list_request_operation_processing_queue;
|
||||||
af_property_list_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.property-list-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_property_list_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.property-list-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_property_list_request_operation_processing_queue;
|
return af_property_list_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,14 @@
|
||||||
|
|
||||||
Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/).
|
Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/).
|
||||||
|
|
||||||
|
## SSL Pinning
|
||||||
|
|
||||||
|
Relying on the CA trust model to validate SSL certificates exposes your app to security vulnerabilities, such as man-in-the-middle attacks. For applications that connect to known servers, SSL certificate pinning provides an increased level of security, by checking server certificate validity against those specified in the app bundle.
|
||||||
|
|
||||||
|
SSL with certificate pinning is strongly recommended for any application that transmits sensitive information to an external webservice.
|
||||||
|
|
||||||
|
When `_AFNETWORKING_PIN_SSL_CERTIFICATES_` is defined and the Security framework is linked, connections will be validated on all matching certificates with a `.cer` extension in the bundle root.
|
||||||
|
|
||||||
## NSCoding & NSCopying Conformance
|
## NSCoding & NSCopying Conformance
|
||||||
|
|
||||||
`AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind:
|
`AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind:
|
||||||
|
|
@ -75,7 +83,21 @@
|
||||||
- A copy of an operation will not include the `outputStream` of the original.
|
- A copy of an operation will not include the `outputStream` of the original.
|
||||||
- Operation copies do not include `completionBlock`. `completionBlock` often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied.
|
- Operation copies do not include `completionBlock`. `completionBlock` often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied.
|
||||||
*/
|
*/
|
||||||
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSCoding, NSCopying>
|
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
typedef enum {
|
||||||
|
AFSSLPinningModeNone,
|
||||||
|
AFSSLPinningModePublicKey,
|
||||||
|
AFSSLPinningModeCertificate,
|
||||||
|
} AFURLConnectionOperationSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate,
|
||||||
|
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0) || \
|
||||||
|
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8)
|
||||||
|
NSURLConnectionDataDelegate,
|
||||||
|
#endif
|
||||||
|
NSCoding, NSCopying>
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
/// @name Accessing Run Loop Modes
|
/// @name Accessing Run Loop Modes
|
||||||
|
|
@ -131,7 +153,6 @@
|
||||||
*/
|
*/
|
||||||
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding;
|
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding;
|
||||||
|
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
/// @name Managing URL Credentials
|
/// @name Managing URL Credentials
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
|
|
@ -150,6 +171,15 @@
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, strong) NSURLCredential *credential;
|
@property (nonatomic, strong) NSURLCredential *credential;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The pinning mode which will be used for SSL connections. `AFSSLPinningModePublicKey` by default.
|
||||||
|
|
||||||
|
@discussion To enable SSL Pinning, `#define _AFNETWORKING_PIN_SSL_CERTIFICATES_` in `Prefix.pch`. Also, make sure that the Security framework is linked with the binary. See the "SSL Pinning" section in the `AFURLConnectionOperation`" header for more information.
|
||||||
|
*/
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode SSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
///------------------------
|
///------------------------
|
||||||
/// @name Accessing Streams
|
/// @name Accessing Streams
|
||||||
///------------------------
|
///------------------------
|
||||||
|
|
@ -290,6 +320,25 @@
|
||||||
///----------------
|
///----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
## SSL Pinning Options
|
||||||
|
|
||||||
|
The following constants are provided by `AFURLConnectionOperation` as possible SSL Pinning options.
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AFSSLPinningModeNone,
|
||||||
|
AFSSLPinningModePublicKey,
|
||||||
|
AFSSLPinningModeCertificate,
|
||||||
|
}
|
||||||
|
|
||||||
|
`AFSSLPinningModeNone`
|
||||||
|
Do not pin SSL connections
|
||||||
|
|
||||||
|
`AFSSLPinningModePublicKey`
|
||||||
|
Pin SSL connections to certificate public key (SPKI).
|
||||||
|
|
||||||
|
`AFSSLPinningModeCertificate`
|
||||||
|
Pin SSL connections to exact certificate. This may cause problems when your certificate expires and needs re-issuance.
|
||||||
|
|
||||||
## User info dictionary keys
|
## User info dictionary keys
|
||||||
|
|
||||||
These keys may exist in the user info dictionary, in addition to those defined for NSError.
|
These keys may exist in the user info dictionary, in addition to those defined for NSError.
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
@dynamic inputStream;
|
@dynamic inputStream;
|
||||||
@synthesize outputStream = _outputStream;
|
@synthesize outputStream = _outputStream;
|
||||||
@synthesize credential = _credential;
|
@synthesize credential = _credential;
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@synthesize SSLPinningMode = _SSLPinningMode;
|
||||||
|
#endif
|
||||||
@synthesize shouldUseCredentialStorage = _shouldUseCredentialStorage;
|
@synthesize shouldUseCredentialStorage = _shouldUseCredentialStorage;
|
||||||
@synthesize userInfo = _userInfo;
|
@synthesize userInfo = _userInfo;
|
||||||
@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier;
|
@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier;
|
||||||
|
|
@ -167,7 +170,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
+ (NSThread *)networkRequestThread {
|
+ (NSThread *)networkRequestThread {
|
||||||
static NSThread *_networkRequestThread = nil;
|
static NSThread *_networkRequestThread = nil;
|
||||||
static dispatch_once_t oncePredicate;
|
static dispatch_once_t oncePredicate;
|
||||||
|
|
||||||
dispatch_once(&oncePredicate, ^{
|
dispatch_once(&oncePredicate, ^{
|
||||||
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
|
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
|
||||||
[_networkRequestThread start];
|
[_networkRequestThread start];
|
||||||
|
|
@ -176,24 +178,61 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
return _networkRequestThread;
|
return _networkRequestThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
+ (NSArray *)pinnedCertificates {
|
+ (NSArray *)pinnedCertificates {
|
||||||
static NSArray *_pinnedCertificates = nil;
|
static NSArray *_pinnedCertificates = nil;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
|
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||||
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
|
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
|
||||||
NSMutableArray *certificates = [NSMutableArray array];
|
|
||||||
|
NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]];
|
||||||
for (NSString *path in paths) {
|
for (NSString *path in paths) {
|
||||||
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
||||||
[certificates addObject:certificateData];
|
[certificates addObject:certificateData];
|
||||||
}
|
}
|
||||||
|
|
||||||
_pinnedCertificates = [[NSArray alloc] initWithArray:certificates];
|
_pinnedCertificates = [[NSArray alloc] initWithArray:certificates];
|
||||||
});
|
});
|
||||||
|
|
||||||
return _pinnedCertificates;
|
return _pinnedCertificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSArray *)pinnedPublicKeys {
|
||||||
|
static NSArray *_pinnedPublicKeys = nil;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSArray *pinnedCertificates = [self pinnedCertificates];
|
||||||
|
NSMutableArray *publicKeys = [NSMutableArray arrayWithCapacity:[pinnedCertificates count]];
|
||||||
|
|
||||||
|
for (NSData *data in pinnedCertificates) {
|
||||||
|
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
|
||||||
|
NSCParameterAssert(allowedCertificate);
|
||||||
|
|
||||||
|
SecCertificateRef allowedCertificates[] = {allowedCertificate};
|
||||||
|
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
|
||||||
|
|
||||||
|
SecPolicyRef policy = SecPolicyCreateBasicX509();
|
||||||
|
SecTrustRef allowedTrust = NULL;
|
||||||
|
OSStatus status = SecTrustCreateWithCertificates(certificates, policy, &allowedTrust);
|
||||||
|
NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
|
||||||
|
|
||||||
|
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust);
|
||||||
|
[publicKeys addObject:(__bridge_transfer id)allowedPublicKey];
|
||||||
|
|
||||||
|
CFRelease(allowedTrust);
|
||||||
|
CFRelease(policy);
|
||||||
|
CFRelease(certificates);
|
||||||
|
CFRelease(allowedCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys];
|
||||||
|
});
|
||||||
|
|
||||||
|
return _pinnedPublicKeys;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
- (id)initWithRequest:(NSURLRequest *)urlRequest {
|
- (id)initWithRequest:(NSURLRequest *)urlRequest {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
|
|
@ -344,19 +383,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self didChangeValueForKey:oldStateKey];
|
[self didChangeValueForKey:oldStateKey];
|
||||||
[self didChangeValueForKey:newStateKey];
|
[self didChangeValueForKey:newStateKey];
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
switch (state) {
|
|
||||||
case AFOperationExecutingState:
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
|
||||||
break;
|
|
||||||
case AFOperationFinishedState:
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)responseString {
|
- (NSString *)responseString {
|
||||||
|
|
@ -371,7 +397,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
- (NSStringEncoding)responseStringEncoding {
|
- (NSStringEncoding)responseStringEncoding {
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
if (!_responseStringEncoding) {
|
if (!_responseStringEncoding && self.response) {
|
||||||
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
|
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
|
||||||
if (self.response.textEncodingName) {
|
if (self.response.textEncodingName) {
|
||||||
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
|
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
|
||||||
|
|
@ -398,7 +424,8 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
|
[notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,9 +480,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
- (void)operationDidStart {
|
- (void)operationDidStart {
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
if ([self isCancelled]) {
|
if (! [self isCancelled]) {
|
||||||
[self finish];
|
|
||||||
} else {
|
|
||||||
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
|
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
|
||||||
|
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||||
|
|
@ -467,10 +492,22 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self.connection start];
|
[self.connection start];
|
||||||
}
|
}
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
||||||
|
});
|
||||||
|
|
||||||
|
if ([self isCancelled]) {
|
||||||
|
[self finish];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)finish {
|
- (void)finish {
|
||||||
self.state = AFOperationFinishedState;
|
self.state = AFOperationFinishedState;
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancel {
|
- (void)cancel {
|
||||||
|
|
@ -516,13 +553,58 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
|
||||||
if ([[[self class] pinnedCertificates] containsObject:certificateData]) {
|
if ([[[self class] pinnedCertificates] containsObject:certificateData]) {
|
||||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
switch (self.SSLPinningMode) {
|
||||||
|
case AFSSLPinningModePublicKey: {
|
||||||
|
id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust);
|
||||||
|
|
||||||
|
if ([[self.class pinnedPublicKeys] containsObject:publicKey]) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
} else {
|
} else {
|
||||||
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AFSSLPinningModeCertificate: {
|
||||||
|
SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
|
||||||
|
NSData *serverCertificateData = (__bridge_transfer NSData *)SecCertificateCopyData(serverCertificate);
|
||||||
|
|
||||||
|
if ([[[self class] pinnedCertificates] containsObject:serverCertificateData]) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AFSSLPinningModeNone: {
|
||||||
|
#ifdef _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
#else
|
||||||
|
SecTrustResultType result = 0;
|
||||||
|
OSStatus status = SecTrustEvaluate(serverTrust, &result);
|
||||||
|
NSAssert(status == noErr, @"SecTrustEvaluate error: %ld", (long int)status);
|
||||||
|
|
||||||
|
if (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)connection:(NSURLConnection *)connection
|
- (BOOL)connection:(NSURLConnection *)connection
|
||||||
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
|
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
|
||||||
{
|
{
|
||||||
|
|
@ -631,18 +713,18 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
- (void)connection:(NSURLConnection __unused *)connection
|
- (void)connection:(NSURLConnection __unused *)connection
|
||||||
didReceiveData:(NSData *)data
|
didReceiveData:(NSData *)data
|
||||||
{
|
{
|
||||||
self.totalBytesRead += [data length];
|
|
||||||
|
|
||||||
if ([self.outputStream hasSpaceAvailable]) {
|
if ([self.outputStream hasSpaceAvailable]) {
|
||||||
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
|
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
|
||||||
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
|
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.downloadProgress) {
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
self.totalBytesRead += [data length];
|
||||||
|
|
||||||
|
if (self.downloadProgress) {
|
||||||
self.downloadProgress([data length], self.totalBytesRead, self.response.expectedContentLength);
|
self.downloadProgress([data length], self.totalBytesRead, self.response.expectedContentLength);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
|
- (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,12 @@
|
||||||
|
|
||||||
#include <Availability.h>
|
#include <Availability.h>
|
||||||
|
|
||||||
static dispatch_queue_t af_xml_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t xml_request_operation_processing_queue() {
|
static dispatch_queue_t xml_request_operation_processing_queue() {
|
||||||
if (af_xml_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_xml_request_operation_processing_queue;
|
||||||
af_xml_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.xml-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_xml_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.xml-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_xml_request_operation_processing_queue;
|
return af_xml_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
placeholderImage:(UIImage *)placeholderImage
|
placeholderImage:(UIImage *)placeholderImage
|
||||||
{
|
{
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||||
[request setHTTPShouldHandleCookies:NO];
|
|
||||||
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
||||||
|
|
||||||
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
||||||
|
|
@ -102,21 +101,22 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
|
|
||||||
UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest];
|
UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest];
|
||||||
if (cachedImage) {
|
if (cachedImage) {
|
||||||
self.image = cachedImage;
|
|
||||||
self.af_imageRequestOperation = nil;
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
success(nil, nil, cachedImage);
|
success(nil, nil, cachedImage);
|
||||||
|
} else {
|
||||||
|
self.image = cachedImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.af_imageRequestOperation = nil;
|
||||||
} else {
|
} else {
|
||||||
self.image = placeholderImage;
|
self.image = placeholderImage;
|
||||||
|
|
||||||
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
|
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
|
||||||
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
|
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
|
||||||
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
|
if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) {
|
||||||
if (success) {
|
if (success) {
|
||||||
success(operation.request, operation.response, responseObject);
|
success(operation.request, operation.response, responseObject);
|
||||||
} else {
|
} else if (responseObject) {
|
||||||
self.image = responseObject;
|
self.image = responseObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
|
|
||||||
[[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
|
[[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
|
||||||
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
||||||
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
|
if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
failure(operation.request, operation.response, error);
|
failure(operation.request, operation.response, error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
178
CHANGES
178
CHANGES
|
|
@ -1,67 +1,195 @@
|
||||||
|
= 1.2.0 (2013-03-24)
|
||||||
|
|
||||||
|
* Add `SSLPinningMode` property to `AFHTTPClient` (Oliver Letterer, Kevin
|
||||||
|
Harwood, Adam Becevello, Dustin Barker, Mattt Thompson)
|
||||||
|
|
||||||
|
* Add single quote ("'"), comma (","), and asterix ("*") to escaped URL
|
||||||
|
encoding characters (Eric Florenzano, Marc Nijdam, Garrett Murray)
|
||||||
|
|
||||||
|
* Add `credential` property to `AFURLConnectionOperation` (Mattt Thompson)
|
||||||
|
|
||||||
|
* Add `-setDefaultCredential:` to `AFHTTPClient`
|
||||||
|
|
||||||
|
* Add `shouldUseCredentialStorage` property to `AFURLConnectionOperation`
|
||||||
|
(Mattt Thompson)
|
||||||
|
|
||||||
|
* Add support for repeated key value pairs in `AFHTTPClient` URL query string
|
||||||
|
(Nick Dawson)
|
||||||
|
|
||||||
|
* Add `AFMultipartFormData -
|
||||||
|
appendPartWithFileURL:name:fileName:mimeType:error` (Daniel Rodríguez Troitiño)
|
||||||
|
|
||||||
|
* Add `AFMultipartFormData -
|
||||||
|
appendPartWithInputStream:name:fileName:mimeType:` (@joein3d)
|
||||||
|
|
||||||
|
* Change SSL pinning to be runtime property on `AFURLConnectionOperation`
|
||||||
|
rather than defined by macro (Oliver Letterer)
|
||||||
|
|
||||||
|
* Change `AFMultipartBodyStream` to `AFMultipartBodyStreamProvider`, vending
|
||||||
|
one side of a bound CFStream pair rather than subclassing `NSInputStream` (Mike
|
||||||
|
Ash)
|
||||||
|
|
||||||
|
* Change default `Accept-Language` header in `AFHTTPClient` (@therigu, Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
|
* Change `AFHTTPClient` operation cancellation to be based on request URL path
|
||||||
|
rather than absolute URL string (Mattt Thompson)
|
||||||
|
|
||||||
|
* Change request operation subclass processing queues to use
|
||||||
|
`DISPATCH_QUEUE_CONCURRENT` (Mattt Thompson)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to resolve asymmetry in cached image case
|
||||||
|
between success block provided and not provided (@Eveets, Mattt Thompson)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to compare `NSURLRequest` instead of
|
||||||
|
`NSURL` to determine if previous request was equivalent (Cédric Luthi)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to only set image if non-`nil` (Sean
|
||||||
|
Kovacs)
|
||||||
|
|
||||||
|
* Change indentation settings to four spaces at the project level (Cédric
|
||||||
|
Luthi)
|
||||||
|
|
||||||
|
* Change `AFNetworkActivityIndicatorManager` to only update if requests have a
|
||||||
|
non-`nil` URL (Cédric Luthi)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to not do `setHTTPShouldHandleCookies`
|
||||||
|
(Konstantinos Vaggelakos)
|
||||||
|
|
||||||
|
* Fix request stream exhaustion error on authentication challenges (Alex
|
||||||
|
Burgel)
|
||||||
|
|
||||||
|
* Fix implementation to use `NSURL` methods instead of `CFURL` functions where
|
||||||
|
applicable (Cédric Luthi)
|
||||||
|
|
||||||
|
* Fix race condition in `UIImageView+AFNetworking` (Peyman)
|
||||||
|
|
||||||
|
* Fix `responseJSON`, `responseString`, and `responseStringEncoding` to be
|
||||||
|
threadsafe (Jon Parise, Mattt Thompson)
|
||||||
|
|
||||||
|
* Fix `AFContentTypeForPathExtension` to ensure non-`NULL` content return
|
||||||
|
value (Zach Waugh)
|
||||||
|
|
||||||
|
* Fix documentation for `appendPartWithFileURL:name:error:`
|
||||||
|
(Daniel Rodríguez Troitiño)
|
||||||
|
|
||||||
|
* Fix request operation subclass processing queues to initialize with
|
||||||
|
`dispatch_once` (Sasmito Adibowo)
|
||||||
|
|
||||||
|
* Fix posting of `AFNetworkingOperationDidStartNotification` and
|
||||||
|
`AFNetworkingOperationDidFinishNotification` to avoid crashes when logging in
|
||||||
|
response to notifications (Blake Watters)
|
||||||
|
|
||||||
|
* Fix ordering of registered operation consultation in `AFHTTPClient` (Joel
|
||||||
|
Parsons)
|
||||||
|
|
||||||
|
* Fix warning: multiple methods named 'postNotificationName:object:' found
|
||||||
|
[-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: multiple methods named 'objectForKey:' found
|
||||||
|
[-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: weak receiver may be unpredictably set to nil
|
||||||
|
[-Wreceiver-is-weak] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix missing #pragma clang diagnostic pop (Steven Fisher)
|
||||||
|
|
||||||
= 1.1.0 (2012-12-27)
|
= 1.1.0 (2012-12-27)
|
||||||
|
|
||||||
* Add optional SSL certificate pinning with `#define _AFNETWORKING_PIN_SSL_CERTIFICATES_` (Dustin Barker)
|
* Add optional SSL certificate pinning with `#define
|
||||||
|
_AFNETWORKING_PIN_SSL_CERTIFICATES_` (Dustin Barker)
|
||||||
|
|
||||||
* Add `responseStringEncoding` property to `AFURLConnectionOperation` (Mattt Thompson)
|
* Add `responseStringEncoding` property to `AFURLConnectionOperation` (Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
* Add `userInfo` property to `AFURLConnectionOperation` (Mattt Thompson, Steven Fisher)
|
* Add `userInfo` property to `AFURLConnectionOperation` (Mattt Thompson,
|
||||||
|
Steven Fisher)
|
||||||
|
|
||||||
* Change behavior to cause a failure when an operation is cancelled (Daniel Tull)
|
* Change behavior to cause a failure when an operation is cancelled (Daniel
|
||||||
|
Tull)
|
||||||
|
|
||||||
* Change return type of class constructors to `instancetype` (@guykogus)
|
* Change return type of class constructors to `instancetype` (@guykogus)
|
||||||
|
|
||||||
* Change notifications to always being posted on an asynchronously-dispatched block run on the main queue (Evadne Wu, Mattt Thompson)
|
* Change notifications to always being posted on an asynchronously-dispatched
|
||||||
|
block run on the main queue (Evadne Wu, Mattt Thompson)
|
||||||
|
|
||||||
* Change from NSLocalizedString to NSLocalizedStringFromTable with AFNetworking.strings table for localized strings (Cédric Luthi)
|
* Change from NSLocalizedString to NSLocalizedStringFromTable with
|
||||||
|
AFNetworking.strings table for localized strings (Cédric Luthi)
|
||||||
|
|
||||||
* Change `-appendPartWithHeaders:body:` to add assertion handler for existence of body data parameter (Jonathan Beilin)
|
* Change `-appendPartWithHeaders:body:` to add assertion handler for existence
|
||||||
|
of body data parameter (Jonathan Beilin)
|
||||||
|
|
||||||
* Change `AFHTTPRequestOperation -responseString` to follow guidelines from RFC 2616 regarding the use of string encoding when none is specified in the response (Jorge Bernal)
|
* Change `AFHTTPRequestOperation -responseString` to follow guidelines from
|
||||||
|
RFC 2616 regarding the use of string encoding when none is specified in the
|
||||||
|
response (Jorge Bernal)
|
||||||
|
|
||||||
* Change AFHTTPClient parameter serialization dictionary keys with `caseInsensitiveCompare:` to ensure
|
* Change AFHTTPClient parameter serialization dictionary keys with
|
||||||
|
`caseInsensitiveCompare:` to ensure
|
||||||
deterministic ordering of query string parameters, which may otherwise
|
deterministic ordering of query string parameters, which may otherwise
|
||||||
cause ambiguous representations of nested parameters (James Coleman,
|
cause ambiguous representations of nested parameters (James Coleman,
|
||||||
Mattt Thompson)
|
Mattt Thompson)
|
||||||
|
|
||||||
* Fix -Wstrict-selector-match warnings raised by Xcode 4.6DP3 (Jesse Collis, Cédric Luthi)
|
* Fix -Wstrict-selector-match warnings raised by Xcode 4.6DP3 (Jesse Collis,
|
||||||
|
Cédric Luthi)
|
||||||
|
|
||||||
* Fix NSJSONSerialization crash with Unicode character escapes in JSON response (Mathijs Kadijk)
|
* Fix NSJSONSerialization crash with Unicode character escapes in JSON
|
||||||
|
response (Mathijs Kadijk)
|
||||||
|
|
||||||
* Fix issue with early return in -startMonitoringNetworkReachability if network reachability object could not be created (i.e. invalid hostnames) (Basil Shkara)
|
* Fix issue with early return in -startMonitoringNetworkReachability if
|
||||||
|
network reachability object could not be created (i.e. invalid hostnames)
|
||||||
|
(Basil Shkara)
|
||||||
|
|
||||||
* Fix retain cycles in AFImageRequestOperation.m and AFHTTPClient.m caused by strong references within blocks (Nick Forge)
|
* Fix retain cycles in AFImageRequestOperation.m and AFHTTPClient.m caused by
|
||||||
|
strong references within blocks (Nick Forge)
|
||||||
|
|
||||||
* Fix issue caused by Rails behavior of returning a single space in head :ok responses, which is interpreted as invalid (Sebastian Ludwig)
|
* Fix issue caused by Rails behavior of returning a single space in head :ok
|
||||||
|
responses, which is interpreted as invalid (Sebastian Ludwig)
|
||||||
|
|
||||||
* Fix issue in streaming multipart upload, where final encapsulation boundary would not be appended if it was larger than the available buffer, causing a potential timeout (Tomohisa Takaoka, David Kasper)
|
* Fix issue in streaming multipart upload, where final encapsulation boundary
|
||||||
|
would not be appended if it was larger than the available buffer, causing a
|
||||||
|
potential timeout (Tomohisa Takaoka, David Kasper)
|
||||||
|
|
||||||
* Fix memory leak of network reachability callback block (Mattt Thompson)
|
* Fix memory leak of network reachability callback block (Mattt Thompson)
|
||||||
|
|
||||||
* Fix `-initWithCoder:` for `AFURLConnectionOperation` and `AFHTTPClient` to cast scalar types (Mattt Thompson)
|
* Fix `-initWithCoder:` for `AFURLConnectionOperation` and `AFHTTPClient` to
|
||||||
|
cast scalar types (Mattt Thompson)
|
||||||
|
|
||||||
* Fix bug in `-enqueueBatchOfHTTPRequestOperations:...` to by using `addOperations:waitUntilFinished:` instead of adding each operation individually. (Mattt Thompson)
|
* Fix bug in `-enqueueBatchOfHTTPRequestOperations:...` to by using
|
||||||
|
`addOperations:waitUntilFinished:` instead of adding each operation
|
||||||
|
individually. (Mattt Thompson)
|
||||||
|
|
||||||
* Change `#warning` messages of checks for `CoreServices` and `MobileCoreServices` to message according to the build target platform (Mattt Thompson)
|
* Change `#warning` messages of checks for `CoreServices` and
|
||||||
|
`MobileCoreServices` to message according to the build target platform (Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
* Change `AFQueryStringFromParametersWithEncoding` to create keys string representations using the description method as specified in documentation (Cédric Luthi)
|
* Change `AFQueryStringFromParametersWithEncoding` to create keys string
|
||||||
|
representations using the description method as specified in documentation
|
||||||
|
(Cédric Luthi)
|
||||||
|
|
||||||
* Fix __unused keywords for better Xcode indexing (Christian Rasmussen)
|
* Fix __unused keywords for better Xcode indexing (Christian Rasmussen)
|
||||||
|
|
||||||
* Fix warning: unused parameter 'x' [-Werror,-Wunused-parameter] (Oliver Jones)
|
* Fix warning: unused parameter 'x' [-Werror,-Wunused-parameter] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: property is assumed atomic by default [-Werror,-Wimplicit-atomic-properties] (Oliver Jones)
|
* Fix warning: property is assumed atomic by default
|
||||||
|
[-Werror,-Wimplicit-atomic-properties] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: weak receiver may be unpredictably null in ARC mode [-Werror,-Wreceiver-is-weak] (Oliver Jones)
|
* Fix warning: weak receiver may be unpredictably null in ARC mode
|
||||||
|
[-Werror,-Wreceiver-is-weak] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: multiple methods named 'selector' found [-Werror,-Wstrict-selector-match] (Oliver Jones)
|
* Fix warning: multiple methods named 'selector' found
|
||||||
|
[-Werror,-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: 'macro' is not defined, evaluates to 0 (Oliver Jones)
|
* Fix warning: 'macro' is not defined, evaluates to 0 (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: atomic by default property 'X' has a user (Oliver Jones)defined getter (property should be marked 'atomic' if this is intended) [-Werror, -Wcustom-atomic-properties] (Oliver Jones)
|
* Fix warning: atomic by default property 'X' has a user (Oliver Jones)defined
|
||||||
|
getter (property should be marked 'atomic' if this is intended) [-Werror,
|
||||||
|
-Wcustom-atomic-properties] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: 'response' was marked unused but was used [-Werror,-Wused-but-marked-unused] (Oliver Jones)
|
* Fix warning: 'response' was marked unused but was used
|
||||||
|
[-Werror,-Wused-but-marked-unused] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: enumeration value 'AFFinalBoundaryPhase' not explicitly handled in switch [-Werror,-Wswitch-enum] (Oliver Jones)
|
* Fix warning: enumeration value 'AFFinalBoundaryPhase' not explicitly handled
|
||||||
|
in switch [-Werror,-Wswitch-enum] (Oliver Jones)
|
||||||
|
|
||||||
= 1.0.1 / 2012-11-01
|
= 1.0.1 / 2012-11-01
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
F82EB080159A172000B10B56 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB077159A172000B10B56 /* AFPropertyListRequestOperation.m */; };
|
F82EB080159A172000B10B56 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB077159A172000B10B56 /* AFPropertyListRequestOperation.m */; };
|
||||||
F82EB081159A172000B10B56 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB079159A172000B10B56 /* AFURLConnectionOperation.m */; };
|
F82EB081159A172000B10B56 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB079159A172000B10B56 /* AFURLConnectionOperation.m */; };
|
||||||
F82EB082159A172000B10B56 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */; };
|
F82EB082159A172000B10B56 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */; };
|
||||||
|
F88812F216C533E9003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F88812F116C533E9003C8B8C /* Security.framework */; };
|
||||||
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847CE161F55A500940F39 /* CoreServices.framework */; };
|
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847CE161F55A500940F39 /* CoreServices.framework */; };
|
||||||
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */; };
|
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
@ -57,6 +58,7 @@
|
||||||
F82EB07A159A172000B10B56 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFXMLRequestOperation.h; path = ../AFNetworking/AFXMLRequestOperation.h; sourceTree = "<group>"; };
|
F82EB07A159A172000B10B56 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFXMLRequestOperation.h; path = ../AFNetworking/AFXMLRequestOperation.h; sourceTree = "<group>"; };
|
||||||
F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFXMLRequestOperation.m; path = ../AFNetworking/AFXMLRequestOperation.m; sourceTree = "<group>"; };
|
F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFXMLRequestOperation.m; path = ../AFNetworking/AFXMLRequestOperation.m; sourceTree = "<group>"; };
|
||||||
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AFNetworking Example.entitlements"; sourceTree = "<group>"; };
|
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AFNetworking Example.entitlements"; sourceTree = "<group>"; };
|
||||||
|
F88812F116C533E9003C8B8C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
F8A847CE161F55A500940F39 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
F8A847CE161F55A500940F39 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||||
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
@ -66,6 +68,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F88812F216C533E9003C8B8C /* Security.framework in Frameworks */,
|
||||||
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */,
|
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */,
|
||||||
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */,
|
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */,
|
||||||
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
|
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
|
||||||
|
|
@ -78,6 +81,7 @@
|
||||||
F8129BF01591061B009BFE23 = {
|
F8129BF01591061B009BFE23 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
F88812F116C533E9003C8B8C /* Security.framework */,
|
||||||
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */,
|
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */,
|
||||||
F8A847CE161F55A500940F39 /* CoreServices.framework */,
|
F8A847CE161F55A500940F39 /* CoreServices.framework */,
|
||||||
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */,
|
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */,
|
||||||
|
|
@ -86,7 +90,10 @@
|
||||||
F8129BFE1591061B009BFE23 /* Frameworks */,
|
F8129BFE1591061B009BFE23 /* Frameworks */,
|
||||||
F8129BFC1591061B009BFE23 /* Products */,
|
F8129BFC1591061B009BFE23 /* Products */,
|
||||||
);
|
);
|
||||||
|
indentWidth = 4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 4;
|
||||||
|
usesTabs = 0;
|
||||||
};
|
};
|
||||||
F8129BFC1591061B009BFE23 /* Products */ = {
|
F8129BFC1591061B009BFE23 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
@ -206,7 +213,7 @@
|
||||||
F8129BF21591061B009BFE23 /* Project object */ = {
|
F8129BF21591061B009BFE23 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0450;
|
LastUpgradeCheck = 0460;
|
||||||
};
|
};
|
||||||
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
|
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
|
@ -265,6 +272,10 @@
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
|
@ -292,6 +303,10 @@
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
||||||
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
||||||
|
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; };
|
||||||
F8A847C1161F51A300940F39 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C0161F51A300940F39 /* Default-568h@2x.png */; };
|
F8A847C1161F51A300940F39 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C0161F51A300940F39 /* Default-568h@2x.png */; };
|
||||||
F8A847C3161F523E00940F39 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C2161F523E00940F39 /* Default.png */; };
|
F8A847C3161F523E00940F39 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C2161F523E00940F39 /* Default.png */; };
|
||||||
F8A847C5161F524200940F39 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C4161F524200940F39 /* Default@2x.png */; };
|
F8A847C5161F524200940F39 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C4161F524200940F39 /* Default@2x.png */; };
|
||||||
|
|
@ -95,6 +96,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */,
|
||||||
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
||||||
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
||||||
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
||||||
|
|
@ -152,7 +154,10 @@
|
||||||
F8E469631395739D00DB05C8 /* Frameworks */,
|
F8E469631395739D00DB05C8 /* Frameworks */,
|
||||||
F8E469611395739C00DB05C8 /* Products */,
|
F8E469611395739C00DB05C8 /* Products */,
|
||||||
);
|
);
|
||||||
|
indentWidth = 4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 4;
|
||||||
|
usesTabs = 0;
|
||||||
};
|
};
|
||||||
F8E469611395739C00DB05C8 /* Products */ = {
|
F8E469611395739C00DB05C8 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ extern NSString * const kUserProfileImageDidLoadNotification;
|
||||||
|
|
||||||
@interface User : NSObject
|
@interface User : NSObject
|
||||||
|
|
||||||
@property (readonly) NSUInteger userID;
|
@property (readonly, nonatomic) NSUInteger userID;
|
||||||
@property (readonly) NSString *username;
|
@property (readonly, nonatomic) NSString *username;
|
||||||
@property (unsafe_unretained, readonly) NSURL *avatarImageURL;
|
@property (readonly, nonatomic, unsafe_unretained) NSURL *avatarImageURL;
|
||||||
|
|
||||||
- (id)initWithAttributes:(NSDictionary *)attributes;
|
- (id)initWithAttributes:(NSDictionary *)attributes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
#ifndef __IPHONE_3_0
|
#ifndef __IPHONE_3_0
|
||||||
#warning "This project uses features only available in iPhone SDK 3.0 and later."
|
#warning "This project uses features only available in iPhone SDK 3.0 and later."
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue