From b1f9598ed24b1ec1b6f24b004578e6736590998b Mon Sep 17 00:00:00 2001 From: Oliver Letterer Date: Fri, 28 Dec 2012 11:48:42 +0100 Subject: [PATCH 01/69] Adds SSLPinningMode to AFURLConnectionOperation and defaultSSLPinMode to AFHTTPClient. --- AFNetworking/AFHTTPClient.h | 8 ++++ AFNetworking/AFHTTPClient.m | 4 ++ AFNetworking/AFURLConnectionOperation.h | 14 ++++++ AFNetworking/AFURLConnectionOperation.m | 64 ++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 7 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 68c6de8..79234b2 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -23,6 +23,7 @@ #import #import +#import "AFURLConnectionOperation.h" /** `AFHTTPClient` captures the common patterns of communicating with an web application over HTTP. It encapsulates information like base URL, authorization credentials, and HTTP headers, and uses them to construct and manage the execution of HTTP request operations. @@ -137,6 +138,13 @@ typedef enum { @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; #endif +/** + Default SSL pinning mode for each `AFHTTPRequestOperation` which will be enqueued with `enqueueHTTPRequestOperation:`. + */ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ +@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinMode; +#endif + ///--------------------------------------------- /// @name Creating and Initializing HTTP Clients ///--------------------------------------------- diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 3fec759..ceda84d 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -524,6 +524,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { #pragma mark - - (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation { +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ + operation.SSLPinningMode = self.defaultSSLPinMode; +#endif + [self.operationQueue addOperation:operation]; } diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index 94c07e8..47139ac 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -24,6 +24,13 @@ #import +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ +typedef enum { + AFURLConnectionOperationSSLPinningModeCertificate = 0, + AFURLConnectionOperationSSLPinningModePublicKey +} AFURLConnectionOperationSSLPinningMode; +#endif + /** `AFURLConnectionOperation` is a subclass of `NSOperation` that implements `NSURLConnection` delegate methods. @@ -124,6 +131,13 @@ */ @property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding; +/** + The pinning mode which will be used for SSL connections. + */ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ +@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode SSLPinningMode; +#endif + ///------------------------ /// @name Accessing Streams ///------------------------ diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 0d27490..0a590a2 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -192,6 +192,36 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat return _pinnedCertificates; } ++ (NSArray *)pinnedPublicKeys { + static NSArray *_pinnedPublicKeys = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + NSArray *pinnedCertificates = [self pinnedCertificates]; + NSMutableArray *publicKeys = [NSMutableArray array]; + + for (NSData *data in pinnedCertificates) { + SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); + NSParameterAssert(allowedCertificate); + + SecPolicyRef policy = SecPolicyCreateBasicX509(); + SecTrustRef allowedTrust = NULL; + OSStatus status = SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust); + NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", status); + + SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust); + [publicKeys addObject:(__bridge_transfer id)allowedPublicKey]; + + CFRelease(allowedTrust); + CFRelease(allowedCertificate); + } + + _pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys]; + }); + + return _pinnedPublicKeys; +} + - (id)initWithRequest:(NSURLRequest *)urlRequest { self = [super init]; if (!self) { @@ -499,14 +529,34 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; - SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); - NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(certificate); - if ([[[self class] pinnedCertificates] containsObject:certificateData]) { - NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; - [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; - } else { - [[challenge sender] cancelAuthenticationChallenge:challenge]; + switch (self.SSLPinningMode) { + case AFURLConnectionOperationSSLPinningModeCertificate: { + SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0); + NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(serverCertificate); + + if ([[[self class] pinnedCertificates] containsObject:certificateData]) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + } else { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + } + break; + } case AFURLConnectionOperationSSLPinningModePublicKey: { + id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust); + + for (id allowedPublicKey in [self.class pinnedPublicKeys]) { + if ([allowedPublicKey isEqual:publicKey]) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + + return; + } + } + + [[challenge sender] cancelAuthenticationChallenge:challenge]; + break; + } } } } From 3b1a09870165a04179e6e63b9c1f0fed1e145a27 Mon Sep 17 00:00:00 2001 From: Oliver Letterer Date: Sat, 29 Dec 2012 13:06:52 +0100 Subject: [PATCH 02/69] Fixes memory leak. --- AFNetworking/AFURLConnectionOperation.m | 1 + 1 file changed, 1 insertion(+) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 0a590a2..4633b8b 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -214,6 +214,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat CFRelease(allowedTrust); CFRelease(allowedCertificate); + CFRelease(policy); } _pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys]; From 80bb2ea52730e16f70456919ff9f587740662647 Mon Sep 17 00:00:00 2001 From: Oliver Letterer Date: Sat, 29 Dec 2012 13:10:14 +0100 Subject: [PATCH 03/69] Gets rid of for loop to check if public key is present. --- AFNetworking/AFURLConnectionOperation.m | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 4633b8b..c8d411c 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -546,16 +546,12 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe } case AFURLConnectionOperationSSLPinningModePublicKey: { id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust); - for (id allowedPublicKey in [self.class pinnedPublicKeys]) { - if ([allowedPublicKey isEqual:publicKey]) { - NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; - [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; - - return; - } + if ([[self.class pinnedPublicKeys] containsObject:publicKey]) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + } else { + [[challenge sender] cancelAuthenticationChallenge:challenge]; } - - [[challenge sender] cancelAuthenticationChallenge:challenge]; break; } } From 317dd753d9d97f74adefbd1a420ef45af72e2d75 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sat, 26 Jan 2013 11:32:13 -0500 Subject: [PATCH 04/69] [Issue #737] Updating default Accept-Language header value in AFHTTPClient --- AFNetworking/AFHTTPClient.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index d9a066b..f787805 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -234,8 +234,13 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { self.defaultHeaders = [NSMutableDictionary dictionary]; // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 - NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "]; - [self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]]; + NSMutableArray *acceptLanguagesComponents = [NSMutableArray array]; + [[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.0f; + }]; + [self setDefaultHeader:@"Accept-Language" value:[acceptLanguagesComponents componentsJoinedByString:@", "]]; #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 From eac6ffbb6ef1fc16b27706bc848a5e6f5796125d Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 30 Jan 2013 16:25:56 +0000 Subject: [PATCH 05/69] Revert "Fixing warning caused by default statement in switch statement that covered all enumeration values" This reverts commit b5c48f13a1d42952da78ab3027b7d804048f525b. --- AFNetworking/AFHTTPClient.m | 1 + 1 file changed, 1 insertion(+) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index c13a524..a7b9569 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1241,6 +1241,7 @@ typedef enum { _phase = AFFinalBoundaryPhase; break; case AFFinalBoundaryPhase: + default: _phase = AFEncapsulationBoundaryPhase; break; } From d998515d24e475c0697bc83f648db09b066ef802 Mon Sep 17 00:00:00 2001 From: flop Date: Wed, 30 Jan 2013 21:52:13 +0300 Subject: [PATCH 06/69] Fix [Issue #751] --- AFNetworking/AFURLConnectionOperation.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index ff4130d..d300653 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -75,7 +75,14 @@ - 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. */ -@interface AFURLConnectionOperation : NSOperation +@interface AFURLConnectionOperation : NSOperation = __IPHONE_5_0 +NSURLConnectionDataDelegate, +#endif +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 +NSURLConnectionDataDelegate, +#endif +NSCoding, NSCopying> ///------------------------------- /// @name Accessing Run Loop Modes From 0dbff8387b0f2137bff9e868790a14ef9718eb25 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Wed, 30 Jan 2013 12:25:22 -0800 Subject: [PATCH 07/69] Serialize calls to responseJSON using a lock. AFJSONRequestOperation's completion path calls `responseJSON` from a processing queue. Because `responseJSON` "lazily" deserializes the response data into a JSON object, it needs to be protected against concurrent access from other queues (threads). For example, `AFNetworkingOperationDidFinishNotification` is posted when the operation finishes but perhaps before that processing queue has finishing executing. Notification observers who also access `responseJSON` end up in a race with that queue that often leads to a crash. We reuse the existing lock from our AFURLConnectionOperation base class. --- AFNetworking/AFJSONRequestOperation.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index bb893b5..c46a8f0 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -31,6 +31,10 @@ static dispatch_queue_t json_request_operation_processing_queue() { return af_json_request_operation_processing_queue; } +@interface AFURLConnectionOperation () +@property (readwrite, nonatomic, strong) NSRecursiveLock *lock; +@end + @interface AFJSONRequestOperation () @property (readwrite, nonatomic, strong) id responseJSON; @property (readwrite, nonatomic, strong) NSError *JSONError; @@ -61,6 +65,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { - (id)responseJSON { + [self.lock lock]; if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) { NSError *error = nil; @@ -77,6 +82,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { self.JSONError = error; } + [self.lock unlock]; return _responseJSON; } From 0f794ccfc95fcdc445f4c23f3440b0125aafaf8f Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 31 Jan 2013 06:54:45 +0000 Subject: [PATCH 08/69] [Issue #769] Resolving asymmetry in cached image case for UIImageView category --- AFNetworking/UIImageView+AFNetworking.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 2e8b9c1..74bac53 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -102,12 +102,13 @@ static char kAFImageRequestOperationObjectKey; UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { - self.image = cachedImage; - self.af_imageRequestOperation = nil; - if (success) { success(nil, nil, cachedImage); + } else { + self.image = cachedImage; } + + self.af_imageRequestOperation = nil; } else { self.image = placeholderImage; From c790135fd4b8ae4653119bdb8ac9fff9a9d2fd94 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 31 Jan 2013 06:55:04 +0000 Subject: [PATCH 09/69] Updating OS X project settings --- .../AFNetworking Mac Example.xcodeproj/project.pbxproj | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj index 59617d1..c679d72 100644 --- a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj @@ -206,7 +206,7 @@ F8129BF21591061B009BFE23 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0460; }; buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */; compatibilityVersion = "Xcode 3.2"; @@ -265,6 +265,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 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; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -292,6 +296,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 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; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; From e969fcd90417d9ad67d45a838bdaf93481d219a3 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 31 Jan 2013 07:00:03 +0000 Subject: [PATCH 10/69] Cleaning up formatting from pull request Adding @dynamic for lock property --- AFNetworking/AFJSONRequestOperation.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index c46a8f0..a078e52 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -31,19 +31,17 @@ static dispatch_queue_t json_request_operation_processing_queue() { return af_json_request_operation_processing_queue; } -@interface AFURLConnectionOperation () -@property (readwrite, nonatomic, strong) NSRecursiveLock *lock; -@end - @interface AFJSONRequestOperation () @property (readwrite, nonatomic, strong) id responseJSON; @property (readwrite, nonatomic, strong) NSError *JSONError; +@property (readwrite, nonatomic, strong) NSRecursiveLock *lock; @end @implementation AFJSONRequestOperation @synthesize responseJSON = _responseJSON; @synthesize JSONReadingOptions = _JSONReadingOptions; @synthesize JSONError = _JSONError; +@dynamic lock; + (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success From be72f5fe1f4fe18abb4febce4ab8a92c8ee07e59 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 31 Jan 2013 07:06:26 +0000 Subject: [PATCH 11/69] [Issue #767] Consolidating macros --- AFNetworking/AFURLConnectionOperation.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index d300653..233627d 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -76,11 +76,9 @@ - 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 = __IPHONE_5_0 -NSURLConnectionDataDelegate, -#endif -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 -NSURLConnectionDataDelegate, +#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> From 74da4493f2f8ec8739621ce6cacacd348869e27d Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 1 Feb 2013 02:39:02 +0000 Subject: [PATCH 12/69] Wrapping AFHTTPBodyPart switch statement with #pragma to ignore -Wcovered-switch-default --- AFNetworking/AFHTTPClient.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index a7b9569..8795ae3 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1227,6 +1227,8 @@ typedef enum { return YES; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcovered-switch-default" switch (_phase) { case AFEncapsulationBoundaryPhase: _phase = AFHeaderPhase; @@ -1246,6 +1248,7 @@ typedef enum { break; } _phaseReadOffset = 0; +#pragma clang diagnostic pop return YES; } From 6b8cdf15819d1d7c7b8d7d21020bb283e9458c7c Mon Sep 17 00:00:00 2001 From: Oliver Jones Date: Wed, 30 Jan 2013 11:22:15 +1100 Subject: [PATCH 13/69] Fixes warning: multiple methods named 'postNotificationName:object:' found [-Wstrict-selector-match] --- AFNetworking/AFHTTPClient.m | 3 ++- AFNetworking/AFURLConnectionOperation.m | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 8795ae3..bf26305 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -304,7 +304,8 @@ static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused targ } 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]]; }); } diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 122ec36..bb8bf55 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -341,12 +341,13 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self.lock unlock]; dispatch_async(dispatch_get_main_queue(), ^{ + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; switch (state) { case AFOperationExecutingState: - [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self]; + [notificationCenter postNotificationName:AFNetworkingOperationDidStartNotification object:self]; break; case AFOperationFinishedState: - [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; + [notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; break; default: break; @@ -393,7 +394,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]]; dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; }); } From 8558d4d5f0d21174e3c785efa47e53ae3a2c8b35 Mon Sep 17 00:00:00 2001 From: Oliver Jones Date: Wed, 30 Jan 2013 11:44:33 +1100 Subject: [PATCH 14/69] Fixes warning: multiple methods named 'objectForKey:' found [-Wstrict-selector-match] --- AFNetworking/AFHTTPClient.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index bf26305..b9736e2 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -146,10 +146,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { NSMutableArray *mutableQueryStringComponents = [NSMutableArray array]; if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(caseInsensitiveCompare:)]; - [[[value allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) { - id nestedValue = [value objectForKey:nestedKey]; + [[[dictionary allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) { + id nestedValue = [dictionary objectForKey:nestedKey]; if (nestedValue) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; } From 22c7d4ec9637b2d56ee36b88330daee62751e56d Mon Sep 17 00:00:00 2001 From: Oliver Jones Date: Fri, 1 Feb 2013 02:45:13 +0000 Subject: [PATCH 15/69] Fixes warning: weak receiver may be unpredictably set to nil [-Wreceiver-is-weak] Signed-off-by: Mattt Thompson --- AFNetworking/AFHTTPClient.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index b9736e2..2ba4d23 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -583,9 +583,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { for (AFHTTPRequestOperation *operation in operations) { AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy]; - __weak AFHTTPRequestOperation *weakOperation = operation; + __weak __typeof(&*operation)weakOperation = operation; 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, ^{ if (originalCompletionBlock) { originalCompletionBlock(); From 4b17ec6b51cc3e434f7cd4a2399f7543314e2dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Fri, 1 Feb 2013 12:23:26 +0100 Subject: [PATCH 16/69] Compare NSURLRequest rather than NSURL If you inadvertently load a nil URL in UIImageView+AFNetworking, the failure block of the image request operation is bypassed because [nil isEqual:nil] == NO. By comparing the URL request instead of the URL, the `isEqual:` test passes and the error is properly forwarded to the failure block parameter. --- AFNetworking/UIImageView+AFNetworking.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 74bac53..fd0e071 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -114,7 +114,7 @@ static char kAFImageRequestOperationObjectKey; AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest]; [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { + if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) { if (success) { success(operation.request, operation.response, responseObject); } else { @@ -128,7 +128,7 @@ static char kAFImageRequestOperationObjectKey; [[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { + if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) { if (failure) { failure(operation.request, operation.response, error); } From 9ae534b94f75ea047e5ca55faff2e5f4bddc91a4 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 1 Feb 2013 22:43:30 +0000 Subject: [PATCH 17/69] Limiting default Accept-Language header to 6 languages --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index f787805..7193c81 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -238,7 +238,7 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { [[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.0f; + *stop = q <= 0.5f; }]; [self setDefaultHeader:@"Accept-Language" value:[acceptLanguagesComponents componentsJoinedByString:@", "]]; From 9b16005f4ea6fdbb0dc8767eca0c475a24636647 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Mon, 4 Feb 2013 00:00:25 +0100 Subject: [PATCH 18/69] Adding lock around AFHTTPRequestOperation -responseString --- AFNetworking/AFHTTPRequestOperation.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index d9cca8e..f7601c0 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -111,6 +111,7 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL @property (readwrite, nonatomic, copy) NSString *HTTPResponseString; @property (readwrite, nonatomic, assign) long long totalContentLength; @property (readwrite, nonatomic, assign) long long offsetContentLength; +@property (readwrite, nonatomic, strong) NSRecursiveLock *lock; @end @implementation AFHTTPRequestOperation @@ -122,6 +123,7 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL @synthesize offsetContentLength = _offsetContentLength; @dynamic request; @dynamic response; +@dynamic lock; - (void)dealloc { if (_successCallbackQueue) { @@ -170,6 +172,7 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL } - (NSString *)responseString { + [self.lock lock]; // 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 if (!self.HTTPResponseString && self.response && !self.response.textEncodingName && self.responseData) { @@ -180,6 +183,7 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL self.HTTPResponseString = [[NSString alloc] initWithData:self.responseData encoding:NSISOLatin1StringEncoding]; } } + [self.lock unlock]; if (self.HTTPResponseString) { return self.HTTPResponseString; From 447fb3a9139dfda864da81dcf08c3b47463b7795 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Mon, 4 Feb 2013 00:01:14 +0100 Subject: [PATCH 19/69] Adding lock around AFURLConnectionOperation -responseStringEncoding Adding check for self.response in AFURLConnectionOperation -responseStringEncoding --- AFNetworking/AFURLConnectionOperation.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index bb8bf55..1fc61db 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -367,7 +367,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat - (NSStringEncoding)responseStringEncoding { [self.lock lock]; - if (!_responseStringEncoding) { + if (!_responseStringEncoding && self.response) { NSStringEncoding stringEncoding = NSUTF8StringEncoding; if (self.response.textEncodingName) { CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName); From 321a2af79df41b647b8f4e6de48adc28e146349c Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Mon, 4 Feb 2013 00:20:56 +0100 Subject: [PATCH 20/69] Fixing warnings caused by implicit property attributes --- Example/Classes/Models/User.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/Classes/Models/User.h b/Example/Classes/Models/User.h index 99d973b..20cd5de 100644 --- a/Example/Classes/Models/User.h +++ b/Example/Classes/Models/User.h @@ -26,9 +26,9 @@ extern NSString * const kUserProfileImageDidLoadNotification; @interface User : NSObject -@property (readonly) NSUInteger userID; -@property (readonly) NSString *username; -@property (unsafe_unretained, readonly) NSURL *avatarImageURL; +@property (readonly, nonatomic) NSUInteger userID; +@property (readonly, nonatomic) NSString *username; +@property (readonly, nonatomic, unsafe_unretained) NSURL *avatarImageURL; - (id)initWithAttributes:(NSDictionary *)attributes; From fa3a77544f8331a5647b2c9b8d78063ba80a81f1 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Mon, 4 Feb 2013 00:21:42 +0100 Subject: [PATCH 21/69] Ignoring -Wcovered-switch-default in AFHTTPBodyPart -hasBytesAvailable --- AFNetworking/AFHTTPClient.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index dfdf4f9..a48d73d 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1165,6 +1165,8 @@ typedef enum { return YES; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcovered-switch-default" switch (self.inputStream.streamStatus) { case NSStreamStatusNotOpen: case NSStreamStatusOpening: @@ -1178,6 +1180,8 @@ typedef enum { default: return NO; } +#pragma clang diagnostic pop + } - (NSInteger)read:(uint8_t *)buffer From 87c8c776d9ab1fa3b7f459366430514a2e283863 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Mon, 4 Feb 2013 00:41:13 +0100 Subject: [PATCH 22/69] Using DISPATCH_QUEUE_CONCURRENT for all calls to dispatch_queue_create for media type processing queues --- AFNetworking/AFImageRequestOperation.m | 2 +- AFNetworking/AFJSONRequestOperation.m | 2 +- AFNetworking/AFPropertyListRequestOperation.m | 2 +- AFNetworking/AFXMLRequestOperation.m | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index e39c9d6..7fb166d 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -25,7 +25,7 @@ static dispatch_queue_t af_image_request_operation_processing_queue; static dispatch_queue_t image_request_operation_processing_queue() { if (af_image_request_operation_processing_queue == NULL) { - af_image_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.image-request.processing", 0); + 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; diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index a078e52..3d713b7 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -25,7 +25,7 @@ static dispatch_queue_t af_json_request_operation_processing_queue; static dispatch_queue_t json_request_operation_processing_queue() { if (af_json_request_operation_processing_queue == NULL) { - af_json_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.json-request.processing", 0); + 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; diff --git a/AFNetworking/AFPropertyListRequestOperation.m b/AFNetworking/AFPropertyListRequestOperation.m index 38229ce..d9612f7 100644 --- a/AFNetworking/AFPropertyListRequestOperation.m +++ b/AFNetworking/AFPropertyListRequestOperation.m @@ -25,7 +25,7 @@ static dispatch_queue_t af_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) { - af_property_list_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.property-list-request.processing", 0); + 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; diff --git a/AFNetworking/AFXMLRequestOperation.m b/AFNetworking/AFXMLRequestOperation.m index 7e6b352..8ebd4ed 100644 --- a/AFNetworking/AFXMLRequestOperation.m +++ b/AFNetworking/AFXMLRequestOperation.m @@ -27,7 +27,7 @@ static dispatch_queue_t af_xml_request_operation_processing_queue; static dispatch_queue_t xml_request_operation_processing_queue() { if (af_xml_request_operation_processing_queue == NULL) { - af_xml_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.xml-request.processing", 0); + 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; From ba60cab1bef8dcb953f3d4d9ce27dfcb23d9fccc Mon Sep 17 00:00:00 2001 From: Sasmito Adibowo Date: Mon, 4 Feb 2013 00:45:35 +0100 Subject: [PATCH 23/69] Use dispatch_once to initialize content-type-specific processing queues Signed-off-by: Mattt Thompson --- AFNetworking/AFImageRequestOperation.m | 7 ++++--- AFNetworking/AFJSONRequestOperation.m | 7 ++++--- AFNetworking/AFPropertyListRequestOperation.m | 7 ++++--- AFNetworking/AFXMLRequestOperation.m | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index 7fb166d..0a0390f 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -22,11 +22,12 @@ #import "AFImageRequestOperation.h" -static dispatch_queue_t af_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; + 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; } diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index 3d713b7..008aacc 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -22,11 +22,12 @@ #import "AFJSONRequestOperation.h" -static dispatch_queue_t af_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; + 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; } diff --git a/AFNetworking/AFPropertyListRequestOperation.m b/AFNetworking/AFPropertyListRequestOperation.m index d9612f7..4d6123b 100644 --- a/AFNetworking/AFPropertyListRequestOperation.m +++ b/AFNetworking/AFPropertyListRequestOperation.m @@ -22,11 +22,12 @@ #import "AFPropertyListRequestOperation.h" -static dispatch_queue_t af_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; + 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; } diff --git a/AFNetworking/AFXMLRequestOperation.m b/AFNetworking/AFXMLRequestOperation.m index 8ebd4ed..30a76b9 100644 --- a/AFNetworking/AFXMLRequestOperation.m +++ b/AFNetworking/AFXMLRequestOperation.m @@ -24,11 +24,12 @@ #include -static dispatch_queue_t af_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; + 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; } From 5698ab3768b334bca0ebb5091634f89dc8e7a9b5 Mon Sep 17 00:00:00 2001 From: Nick Dawson Date: Tue, 5 Feb 2013 12:46:03 +0000 Subject: [PATCH 24/69] Added support for repeated key value pairs through use of NSSet --- AFNetworking/AFHTTPClient.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index a48d73d..e2fd452 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -160,6 +160,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { [array enumerateObjectsUsingBlock:^(id nestedValue, __unused NSUInteger idx, __unused BOOL *stop) { [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 { [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]]; } From b3625ebcd0ca889a52602b92e071aaf9253359f3 Mon Sep 17 00:00:00 2001 From: Steven Fisher Date: Thu, 7 Feb 2013 14:19:54 -0800 Subject: [PATCH 25/69] Fixed comment typo Minor typo. --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index e2fd452..c990e13 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1165,7 +1165,7 @@ typedef enum { } - (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) { return YES; } From 0e18f85bfb8ce731ff3d347e5b28a421f4cc6e5b Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 14:21:52 +0100 Subject: [PATCH 26/69] Replacing #ifdef macro check for Security to _AFNETWORKING_PIN_SSL_CERTIFICATES_ --- AFNetworking/AFURLConnectionOperation.h | 4 ++-- AFNetworking/AFURLConnectionOperation.m | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index ef2a87a..16f815f 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -76,7 +76,7 @@ - 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. */ -#ifdef _SECURITY_SECBASE_H_ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ typedef enum { AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, @@ -162,7 +162,7 @@ NSCoding, NSCopying> /** The pinning mode which will be used for SSL connections. */ -#ifdef _SECURITY_SECBASE_H_ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ @property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode SSLPinningMode; #endif diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index f4c7832..e273498 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -145,7 +145,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @dynamic inputStream; @synthesize outputStream = _outputStream; @synthesize credential = _credential; -#ifdef _SECURITY_SECBASE_H_ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ @synthesize SSLPinningMode = _SSLPinningMode; #endif @synthesize shouldUseCredentialStorage = _shouldUseCredentialStorage; @@ -178,7 +178,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat return _networkRequestThread; } -#ifdef _SECURITY_SECBASE_H_ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ + (NSArray *)pinnedCertificates { static NSArray *_pinnedCertificates = nil; static dispatch_once_t onceToken; @@ -535,7 +535,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat #pragma mark - NSURLConnectionDelegate -#ifdef _SECURITY_SECBASE_H_ +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { From 1053e00fff1fc8e03137f3d4a362330f7a989781 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 14:22:27 +0100 Subject: [PATCH 27/69] Removing #warning about Security framework --- AFNetworking/AFURLConnectionOperation.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index 16f815f..c702f21 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -81,8 +81,6 @@ typedef enum { AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, } AFURLConnectionOperationSSLPinningMode; -#else -#warning Security framework not found in project, or not included in precompiled header. SSL Certificate Pinning functionality will not be available. #endif @interface AFURLConnectionOperation : NSOperation Date: Fri, 8 Feb 2013 14:37:17 +0100 Subject: [PATCH 28/69] Fixing compiler warnings in SSL pinning initializers Minor refactoring --- AFNetworking/AFURLConnectionOperation.m | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index e273498..3d538e0 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -186,11 +186,12 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; - NSMutableArray *certificates = [NSMutableArray array]; + NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]]; for (NSString *path in paths) { NSData *certificateData = [NSData dataWithContentsOfFile:path]; [certificates addObject:certificateData]; } + _pinnedCertificates = [[NSArray alloc] initWithArray:certificates]; }); @@ -202,25 +203,29 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSArray *pinnedCertificates = [self pinnedCertificates]; - NSMutableArray *publicKeys = [NSMutableArray array]; + NSMutableArray *publicKeys = [NSMutableArray arrayWithCapacity:[pinnedCertificates count]]; for (NSData *data in pinnedCertificates) { SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); - NSParameterAssert(allowedCertificate); + NSCParameterAssert(allowedCertificate); + + SecCertificateRef allowedCertificates[] = {allowedCertificate}; + CFArrayRef certificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); SecPolicyRef policy = SecPolicyCreateBasicX509(); SecTrustRef allowedTrust = NULL; - OSStatus status = SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust); - NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", status); + 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(allowedCertificate); CFRelease(policy); + CFRelease(certificates); + CFRelease(allowedCertificate); } - + _pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys]; }); From 35c6f996c09f75e1534e09a923c8b03b3cc913f0 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 14:38:49 +0100 Subject: [PATCH 29/69] Adding Security framework to example projects and adding #define for _AFNETWORKING_PIN_SSL_CERTIFICATES_ --- Example/AFNetworking Mac Example.xcodeproj/project.pbxproj | 4 ++++ Example/AFNetworking iOS Example.xcodeproj/project.pbxproj | 2 ++ Example/Prefix.pch | 2 ++ 3 files changed, 8 insertions(+) diff --git a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj index c679d72..55a77a5 100644 --- a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ F82EB080159A172000B10B56 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB077159A172000B10B56 /* AFPropertyListRequestOperation.m */; }; F82EB081159A172000B10B56 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB079159A172000B10B56 /* AFURLConnectionOperation.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 */; }; F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */; }; /* 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 = ""; }; F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFXMLRequestOperation.m; path = ../AFNetworking/AFXMLRequestOperation.m; sourceTree = ""; }; F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AFNetworking Example.entitlements"; sourceTree = ""; }; + 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; }; F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -66,6 +68,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F88812F216C533E9003C8B8C /* Security.framework in Frameworks */, F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */, F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */, F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */, @@ -78,6 +81,7 @@ F8129BF01591061B009BFE23 = { isa = PBXGroup; children = ( + F88812F116C533E9003C8B8C /* Security.framework */, F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */, F8A847CE161F55A500940F39 /* CoreServices.framework */, F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */, diff --git a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj index 16afe14..6467315 100644 --- a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; }; 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 */; }; F8A847C3161F523E00940F39 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C2161F523E00940F39 /* Default.png */; }; F8A847C5161F524200940F39 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C4161F524200940F39 /* Default@2x.png */; }; @@ -95,6 +96,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F88812F016C533D6003C8B8C /* Security.framework in Frameworks */, F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */, F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */, F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */, diff --git a/Example/Prefix.pch b/Example/Prefix.pch index 18b984d..df78b3c 100644 --- a/Example/Prefix.pch +++ b/Example/Prefix.pch @@ -1,5 +1,7 @@ #import +#define _AFNETWORKING_PIN_SSL_CERTIFICATES_ + #if __IPHONE_OS_VERSION_MIN_REQUIRED #ifndef __IPHONE_3_0 #warning "This project uses features only available in iPhone SDK 3.0 and later." From d609df5321964ed99f7f0c1bf708810fc840a1b8 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 15:08:26 +0100 Subject: [PATCH 30/69] Adding documentation about SSL Pinning --- AFNetworking/AFURLConnectionOperation.h | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index c702f21..f8f9874 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -59,6 +59,14 @@ The built-in `completionBlock` provided by `NSOperation` allows for custom behavior to be executed after the request finishes. It is a common pattern for class constructors in subclasses to take callback block parameters, and execute them conditionally in the body of its `completionBlock`. Make sure to handle cancelled operations appropriately when setting a `completionBlock` (i.e. returning early before parsing response data). See the implementation of any of the `AFHTTPRequestOperation` subclasses for an example of this. 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 @@ -158,7 +166,9 @@ NSCoding, NSCopying> @property (nonatomic, strong) NSURLCredential *credential; /** - The pinning mode which will be used for SSL connections. + 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; @@ -304,6 +314,21 @@ NSCoding, NSCopying> ///---------------- /** + ## Network Reachability + + The following constants are provided by `AFURLConnectionOperation` as possible SSL Pinning options. + + enum { + AFSSLPinningModePublicKey, + AFSSLPinningModeCertificate, + } + + `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 These keys may exist in the user info dictionary, in addition to those defined for NSError. From 8215c43680243097806250da2a88b396e3b3bf5f Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 15:08:41 +0100 Subject: [PATCH 31/69] Minor reformatting of AFHTTPClient constants documentation --- AFNetworking/AFHTTPClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index bf8418f..1f58203 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -448,7 +448,7 @@ typedef enum { ///---------------- /** - ### Network Reachability + ## Network Reachability The following constants are provided by `AFHTTPClient` as possible network reachability statuses. @@ -479,7 +479,7 @@ typedef enum { 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. - ### Parameter Encoding + ## Parameter Encoding The following constants are provided by `AFHTTPClient` as possible methods for serializing parameters into query string or message body values. From effd1136d2100d5acb555f2144568d54708434fe Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 8 Feb 2013 15:11:06 +0100 Subject: [PATCH 32/69] Adding Security frameworks to podspec, and defining _AFNETWORKING_PIN_SSL_CERTIFICATES_ --- AFNetworking.podspec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/AFNetworking.podspec b/AFNetworking.podspec index 8c6affc..b7e836b 100644 --- a/AFNetworking.podspec +++ b/AFNetworking.podspec @@ -10,13 +10,16 @@ Pod::Spec.new do |s| s.requires_arc = true 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.frameworks = 'CoreServices', 'SystemConfiguration' + s.osx.frameworks = 'CoreServices', 'SystemConfiguration', 'Security' s.prefix_header_contents = <<-EOS #import + +#define _AFNETWORKING_PIN_SSL_CERTIFICATES_ + #if __IPHONE_OS_VERSION_MIN_REQUIRED #import #import From a563b61a347f7aa0ea7757fcc37f23ad77f1778d Mon Sep 17 00:00:00 2001 From: Zach Waugh Date: Sat, 9 Feb 2013 11:49:06 -0500 Subject: [PATCH 33/69] Ensure content type for path extension doesn't return null --- AFNetworking/AFHTTPClient.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index c990e13..d745143 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -742,7 +742,12 @@ static inline NSString * AFMultipartFormFinalBoundary() { static inline NSString * AFContentTypeForPathExtension(NSString *extension) { #ifdef __UTTYPE__ 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 return @"application/octet-stream"; #endif From caa9551ae422a01c53d890a219f620954b6f6764 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sat, 9 Feb 2013 19:36:37 +0100 Subject: [PATCH 34/69] [Issue #791] Matching operations on request URL path rather than absolute URL string --- AFNetworking/AFHTTPClient.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index e2fd452..8f49be3 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -546,7 +546,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { - (void)cancelAllHTTPOperationsWithMethod:(NSString *)method 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]) { if (![operation isKindOfClass:[AFHTTPRequestOperation class]]) { @@ -554,9 +554,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { } 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]; } } From 574792d9cbb7b0d8d330d92ae3aa97bc6072ddbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Fri, 15 Feb 2013 21:09:31 +0100 Subject: [PATCH 35/69] Fix documentation for appendPartWithFileURL:name:error:. The documentation said that the values for filename and the Content-Type header was being obtained from a NSURLResponse, but since this is a request, no response is available yet. The documentation has been changed to reflect better where those values really come from. --- AFNetworking/AFHTTPClient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index d1c6f73..f2a6323 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -543,7 +543,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; @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 name:(NSString *)name From 53abb542915a39df2500d5e02cd8bb99d941d118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Fri, 15 Feb 2013 21:13:09 +0100 Subject: [PATCH 36/69] Add method to allow custom file name and content type for multiparts. The previous method was selecting the file name and the MIME type automatically depending on the given file URL. The new method allows specifying a custom file name and a custom MIME type for the those parts. --- AFNetworking/AFHTTPClient.h | 17 +++++++++++++++++ AFNetworking/AFHTTPClient.m | 20 ++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index f2a6323..eb6fb7c 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -549,6 +549,23 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; name:(NSString *)name 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 encoded file data and the multipart form boundary. diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 3af22a2..e86fbe3 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -819,6 +819,22 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; NSParameterAssert(fileURL); 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]) { NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey]; if (error != NULL) { @@ -836,8 +852,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; } NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; - [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, [fileURL lastPathComponent]] forKey:@"Content-Disposition"]; - [mutableHeaders setValue:AFContentTypeForPathExtension([fileURL pathExtension]) forKey:@"Content-Type"]; + [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; From 63e5f0b57ae124d94852c38294a8178c4a2d83ae Mon Sep 17 00:00:00 2001 From: Marc Nijdam Date: Tue, 19 Feb 2013 16:01:01 -0800 Subject: [PATCH 37/69] Adding comma (,) as a percent escaped character since it's in the reserved words per the RFC --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 3af22a2..f9d2166 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -81,7 +81,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) { } static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~'"; + static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',"; static NSString * const kAFCharactersToLeaveUnescaped = @"[]."; return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)); From 01b206071b547e599bc9bdb80fc1a7b1469f3bde Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Thu, 21 Feb 2013 14:35:41 -0500 Subject: [PATCH 38/69] Reimplement AFMultipartBodyStream as AFMultipartBodyStreamProvider vending one side of a bound CFStream pair, to avoid subclassing NSInputStream and fix #781 --- AFNetworking/AFHTTPClient.m | 187 ++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 82 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 3af22a2..fec1c77 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -773,7 +773,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; maxLength:(NSUInteger)length; @end -@interface AFMultipartBodyStream : NSInputStream +@interface AFMultipartBodyStreamProvider : NSObject @property (nonatomic, assign) NSUInteger numberOfBytesInPacket; @property (nonatomic, assign) NSTimeInterval delay; @property (nonatomic, readonly) unsigned long long contentLength; @@ -782,13 +782,15 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; - (id)initWithStringEncoding:(NSStringEncoding)encoding; - (void)setInitialAndFinalBoundaries; - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart; + +- (NSInputStream *)inputStream; @end #pragma mark - @interface AFStreamingMultipartFormData () @property (readwrite, nonatomic, copy) NSMutableURLRequest *request; -@property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream; +@property (readwrite, nonatomic, strong) AFMultipartBodyStreamProvider *bodyStream; @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding; @end @@ -807,7 +809,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; self.request = urlRequest; self.stringEncoding = encoding; - self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding]; + self.bodyStream = [[AFMultipartBodyStreamProvider alloc] initWithStringEncoding:encoding]; return self; } @@ -910,7 +912,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; [self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"]; [self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"]; - [self.request setHTTPBodyStream:self.bodyStream]; + [self.request setHTTPBodyStream:self.bodyStream.inputStream]; return self.request; } @@ -919,7 +921,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; #pragma mark - -@interface AFMultipartBodyStream () +@interface AFMultipartBodyStreamProvider () @property (nonatomic, assign) NSStreamStatus streamStatus; @property (nonatomic, strong) NSError *streamError; @@ -929,7 +931,15 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; @property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart; @end -@implementation AFMultipartBodyStream +static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; + +@implementation AFMultipartBodyStreamProvider { + NSInputStream *_inputStream; + NSOutputStream *_outputStream; + NSMutableData *_buffer; + + id _keepalive; +} @synthesize streamStatus = _streamStatus; @synthesize streamError = _streamError; @synthesize stringEncoding = _stringEncoding; @@ -948,10 +958,16 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; self.stringEncoding = encoding; self.HTTPBodyParts = [NSMutableArray array]; self.numberOfBytesInPacket = NSIntegerMax; - + + _buffer = [[NSMutableData alloc] init]; + return self; } +- (void)dealloc { + _outputStream.delegate = nil; +} + - (void)setInitialAndFinalBoundaries { if ([self.HTTPBodyParts count] > 0) { for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { @@ -968,80 +984,96 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; [self.HTTPBodyParts addObject:bodyPart]; } +- (NSInputStream *)inputStream { + if(_inputStream == nil) { + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + CFStreamCreateBoundPair(NULL, &readStream, &writeStream, AFMultipartBodyStreamProviderBufferSize); + _inputStream = CFBridgingRelease(readStream); + _outputStream = CFBridgingRelease(writeStream); + + _outputStream.delegate = self; + dispatch_sync(dispatch_get_main_queue(), ^{ + [_outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; + }); + [_outputStream open]; + _keepalive = self; + //[self handleOutputStreamSpaceAvailable]; + } + + return _inputStream; +} + - (BOOL)isEmpty { return [self.HTTPBodyParts count] == 0; } -#pragma mark - NSInputStream +#pragma mark - NSStreamDelegate -- (NSInteger)read:(uint8_t *)buffer - maxLength:(NSUInteger)length -{ - if ([self streamStatus] == NSStreamStatusClosed) { - return 0; +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { + if(eventCode | NSStreamEventHasSpaceAvailable) { + [self handleOutputStreamSpaceAvailable]; } - NSInteger bytesRead = 0; +} - while ((NSUInteger)bytesRead < MIN(length, self.numberOfBytesInPacket)) { - if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) { - if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) { - break; +- (void)handleOutputStreamSpaceAvailable { + while([_outputStream hasSpaceAvailable]) { + if([_buffer length] > 0) { + NSInteger ret = [_outputStream write: [_buffer bytes] maxLength: [_buffer length]]; + if(ret < 0) { + /* I don't think an error should ever actually happen with a bound pair. + * If it does, we'll just close the stream and give up. */ + [self close]; + return; + } else { + /* Delete the written bytes from the buffer. */ + [_buffer replaceBytesInRange: NSMakeRange(0, ret) withBytes: NULL length: 0]; } } else { - bytesRead += [self.currentHTTPBodyPart read:&buffer[bytesRead] maxLength:(length - (NSUInteger)bytesRead)]; - if (self.delay > 0.0f) { - [NSThread sleepForTimeInterval:self.delay]; + /* Refill the buffer. */ + + /* Make sure the current body part is valid. */ + if(self.currentHTTPBodyPart == nil) { + if(self.HTTPBodyPartEnumerator == nil) { + self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator]; + } + self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject]; } + + /* If the current part is still nil, then it's the end of the road: close the stream and bail. */ + if(self.currentHTTPBodyPart == nil) { + [self close]; + return; + } + + /* Read some data. */ + [_buffer setLength: AFMultipartBodyStreamProviderBufferSize]; + NSInteger ret = [self.currentHTTPBodyPart read: [_buffer mutableBytes] maxLength: [_buffer length]]; + if(ret < 0) { + /* Not sure how to handle an error currently. Close the output stream and bail out. */ + [self close]; + return; + } + + /* Resize the buffer to how much was actually read. */ + [_buffer setLength: ret]; + + /* If we hit EOF, invalidate the current body part so the next pass through will find a new one. */ + if(ret == 0) { + self.currentHTTPBodyPart = nil; + } + + /* Fall off the end. The next loop through will get data out of the buffer. */ } } - 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 { - self.streamStatus = NSStreamStatusClosed; + [_outputStream close]; + _outputStream.delegate = nil; + _keepalive = 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 length = 0; for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { @@ -1051,26 +1083,10 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; return length; } -#pragma mark - Undocumented CFReadStream Bridged Methods - -- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop - forMode:(__unused CFStringRef)aMode -{} - -- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop - forMode:(__unused CFStringRef)aMode -{} - -- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags - callback:(__unused CFReadStreamClientCallBack)inCallback - context:(__unused CFStreamClientContext *)inContext { - return NO; -} - #pragma mark - NSCopying -(id)copyWithZone:(NSZone *)zone { - AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding]; + AFMultipartBodyStreamProvider *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding]; for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { [bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]]; @@ -1086,10 +1102,12 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; #pragma mark - typedef enum { + AFInitialPhase = 0, AFEncapsulationBoundaryPhase = 1, AFHeaderPhase = 2, AFBodyPhase = 3, AFFinalBoundaryPhase = 4, + AFCompletedPhase = 5, } AFHTTPBodyPartReadPhase; @interface AFHTTPBodyPart () { @@ -1118,6 +1136,7 @@ typedef enum { return nil; } + _phase = AFInitialPhase; [self transitionToNextPhase]; return self; @@ -1252,6 +1271,9 @@ typedef enum { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcovered-switch-default" switch (_phase) { + case AFInitialPhase: + _phase = AFEncapsulationBoundaryPhase; + break; case AFEncapsulationBoundaryPhase: _phase = AFHeaderPhase; break; @@ -1265,8 +1287,9 @@ typedef enum { _phase = AFFinalBoundaryPhase; break; case AFFinalBoundaryPhase: + case AFCompletedPhase: default: - _phase = AFEncapsulationBoundaryPhase; + _phase = AFCompletedPhase; break; } _phaseReadOffset = 0; From 1e0bce2ba92ae8b468ea775e614a8bb1240dc3f3 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Thu, 21 Feb 2013 15:01:20 -0500 Subject: [PATCH 39/69] Delete useless commented-out call to handleOutputStreamSpaceAvailable, and fix the stream:handleEvent: bit flag check --- AFNetworking/AFHTTPClient.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index fec1c77..07e813d 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -998,7 +998,6 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; }); [_outputStream open]; _keepalive = self; - //[self handleOutputStreamSpaceAvailable]; } return _inputStream; @@ -1011,7 +1010,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; #pragma mark - NSStreamDelegate - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { - if(eventCode | NSStreamEventHasSpaceAvailable) { + if(eventCode & NSStreamEventHasSpaceAvailable) { [self handleOutputStreamSpaceAvailable]; } } From bea04f497883f8a93cfee31375becc4d4a7c5093 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Fri, 22 Feb 2013 17:36:57 -0500 Subject: [PATCH 40/69] Fix deadlock from trying to do a dispatch_sync on the main queue when already on the main thread --- AFNetworking/AFHTTPClient.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 07e813d..58123bc 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -993,9 +993,14 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; _outputStream = CFBridgingRelease(writeStream); _outputStream.delegate = self; - dispatch_sync(dispatch_get_main_queue(), ^{ + if([NSThread isMainThread]) { [_outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; - }); + } + else { + dispatch_sync(dispatch_get_main_queue(), ^{ + [_outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; + }); + } [_outputStream open]; _keepalive = self; } From 580c5476168284abe5e53590d9536e063edddb81 Mon Sep 17 00:00:00 2001 From: Oliver Letterer Date: Tue, 26 Feb 2013 08:37:18 +0100 Subject: [PATCH 41/69] Fixes -[AFURLConnectionOperation totalBytesRead] threading issue. --- AFNetworking/AFURLConnectionOperation.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 1fc61db..5503e68 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -628,18 +628,18 @@ didReceiveResponse:(NSURLResponse *)response - (void)connection:(NSURLConnection __unused *)connection didReceiveData:(NSData *)data { - self.totalBytesRead += [data length]; - if ([self.outputStream hasSpaceAvailable]) { const uint8_t *dataBuffer = (uint8_t *) [data bytes]; [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); - }); - } + } + }); } - (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection { From dbd5fc3220c9069274a8b8562818a8b429604ad1 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 27 Feb 2013 09:24:18 -0800 Subject: [PATCH 42/69] Adding missing #pragma clang diagnostic pop (/thanks @tewha) --- AFNetworking/AFHTTPRequestOperation.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index f7601c0..b8bec28 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -30,7 +30,6 @@ #define AF_CAST_TO_BLOCK __bridge void * #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 ignored "-Wstrict-selector-match" @@ -371,3 +370,5 @@ didReceiveResponse:(NSURLResponse *)response } @end + +#pragma clang diagnostic pop From 7673c3e1d0ac85683c42262dab158055b7a45af1 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 27 Feb 2013 09:55:07 -0800 Subject: [PATCH 43/69] [Issue #817] Removing unused totalContentLength and offsetContentLength properties, and implementation of -connection:didReceiveResponse: --- AFNetworking/AFHTTPRequestOperation.m | 46 --------------------------- 1 file changed, 46 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index b8bec28..1adea2b 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -108,8 +108,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response; @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; @property (readwrite, nonatomic, strong) NSRecursiveLock *lock; @end @@ -118,8 +116,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL @synthesize HTTPResponseString = _HTTPResponseString; @synthesize successCallbackQueue = _successCallbackQueue; @synthesize failureCallbackQueue = _failureCallbackQueue; -@synthesize totalContentLength = _totalContentLength; -@synthesize offsetContentLength = _offsetContentLength; @dynamic request; @dynamic response; @dynamic lock; @@ -327,48 +323,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL 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 #pragma clang diagnostic pop From b42ea1fdb6cb9032e16ee1a798eebcbf202ec0b2 Mon Sep 17 00:00:00 2001 From: Sean Kovacs Date: Wed, 27 Feb 2013 11:11:49 -0800 Subject: [PATCH 44/69] [Issue #803] Only set image in UIImageView category if non-nil Signed-off-by: Mattt Thompson --- AFNetworking/UIImageView+AFNetworking.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index fd0e071..8e7f4b7 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -117,7 +117,7 @@ static char kAFImageRequestOperationObjectKey; if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) { if (success) { success(operation.request, operation.response, responseObject); - } else { + } else if (responseObject) { self.image = responseObject; } From 61188e2dad22d235a7c684312a07e5ef4f8ab77a Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 5 Mar 2013 14:42:23 -0800 Subject: [PATCH 45/69] [Issue #837] Refactoring implementation of HTTP string encoding edge case to -responseStringEncoding to fix potential inconsistency in effective value --- AFNetworking/AFHTTPRequestOperation.m | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index 1adea2b..98aa07c 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -107,18 +107,14 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL @property (readwrite, nonatomic, strong) NSURLRequest *request; @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response; @property (readwrite, nonatomic, strong) NSError *HTTPError; -@property (readwrite, nonatomic, copy) NSString *HTTPResponseString; -@property (readwrite, nonatomic, strong) NSRecursiveLock *lock; @end @implementation AFHTTPRequestOperation @synthesize HTTPError = _HTTPError; -@synthesize HTTPResponseString = _HTTPResponseString; @synthesize successCallbackQueue = _successCallbackQueue; @synthesize failureCallbackQueue = _failureCallbackQueue; @dynamic request; @dynamic response; -@dynamic lock; - (void)dealloc { if (_successCallbackQueue) { @@ -166,25 +162,19 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL } } -- (NSString *)responseString { - [self.lock lock]; +- (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. // 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; AFGetMediaTypeAndSubtypeWithString([[self.response allHeaderFields] valueForKey:@"Content-Type"], &type, nil); if ([type isEqualToString:@"text"]) { - self.HTTPResponseString = [[NSString alloc] initWithData:self.responseData encoding:NSISOLatin1StringEncoding]; + return NSISOLatin1StringEncoding; } } - [self.lock unlock]; - if (self.HTTPResponseString) { - return self.HTTPResponseString; - } else { - return [super responseString]; - } + return [super responseStringEncoding]; } - (void)pause { From db305db733da040974c12f5fc6653db4388ac230 Mon Sep 17 00:00:00 2001 From: Blake Watters Date: Wed, 6 Mar 2013 21:40:56 -0500 Subject: [PATCH 46/69] Rework delivery of AFNetworkingOperationDidStartNotification and AFNetworkingOperationDidFinishNotification to avoid crashes when logging in response to notifications --- AFNetworking/AFURLConnectionOperation.m | 34 +++++++++++-------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 5503e68..f4196ce 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -339,20 +339,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self didChangeValueForKey:oldStateKey]; [self didChangeValueForKey:newStateKey]; [self.lock unlock]; - - dispatch_async(dispatch_get_main_queue(), ^{ - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - switch (state) { - case AFOperationExecutingState: - [notificationCenter postNotificationName:AFNetworkingOperationDidStartNotification object:self]; - break; - case AFOperationFinishedState: - [notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; - break; - default: - break; - } - }); } - (NSString *)responseString { @@ -450,24 +436,34 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat - (void)operationDidStart { [self.lock lock]; - if ([self isCancelled]) { - [self finish]; - } else { + if (! [self isCancelled]) { self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; - + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; for (NSString *runLoopMode in self.runLoopModes) { [self.connection scheduleInRunLoop:runLoop forMode:runLoopMode]; [self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode]; } - + [self.connection start]; } [self.lock unlock]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self]; + }); + + if ([self isCancelled]) { + [self finish]; + } } - (void)finish { self.state = AFOperationFinishedState; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; + }); } - (void)cancel { From 95b4f6c97977ed463d0d145806028e16d1a0f66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Thu, 7 Mar 2013 12:53:47 +0100 Subject: [PATCH 47/69] Set indentation settings to four spaces at the project level --- Example/AFNetworking Mac Example.xcodeproj/project.pbxproj | 3 +++ Example/AFNetworking iOS Example.xcodeproj/project.pbxproj | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj index c679d72..7b6a013 100644 --- a/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Mac Example.xcodeproj/project.pbxproj @@ -86,7 +86,10 @@ F8129BFE1591061B009BFE23 /* Frameworks */, F8129BFC1591061B009BFE23 /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; + usesTabs = 0; }; F8129BFC1591061B009BFE23 /* Products */ = { isa = PBXGroup; diff --git a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj index 16afe14..37fcb17 100644 --- a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj @@ -152,7 +152,10 @@ F8E469631395739D00DB05C8 /* Frameworks */, F8E469611395739C00DB05C8 /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; + usesTabs = 0; }; F8E469611395739C00DB05C8 /* Products */ = { isa = PBXGroup; From 9c3530060c5619dc93abd872206c15ee3de41771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20Luthi?= Date: Thu, 7 Mar 2013 13:07:53 +0100 Subject: [PATCH 48/69] Update network activity indicator only if requests have a non nil URL --- .../AFNetworkActivityIndicatorManager.m | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFNetworkActivityIndicatorManager.m b/AFNetworking/AFNetworkActivityIndicatorManager.m index 5b9ec82..b7e4256 100644 --- a/AFNetworking/AFNetworkActivityIndicatorManager.m +++ b/AFNetworking/AFNetworkActivityIndicatorManager.m @@ -62,8 +62,8 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17; return nil; } - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incrementActivityCount) name:AFNetworkingOperationDidStartNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(decrementActivityCount) name:AFNetworkingOperationDidFinishNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidStart:) name:AFNetworkingOperationDidStartNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidFinish:) name:AFNetworkingOperationDidFinishNotification object:nil]; return self; } @@ -126,6 +126,20 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17; [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 #endif From 953b8623d8b8dab095819dc89126d922330b12fd Mon Sep 17 00:00:00 2001 From: Garrett Murray Date: Thu, 7 Mar 2013 20:42:16 -0800 Subject: [PATCH 49/69] Add asterisk (*) as a percent escaped character since it's in the reserved words per the RFC --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index f9d2166..fbcee09 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -81,7 +81,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) { } static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',"; + static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',*"; static NSString * const kAFCharactersToLeaveUnescaped = @"[]."; return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)); From 6a46815eafdb3e8b5f46f94502756cd9b226d7ef Mon Sep 17 00:00:00 2001 From: Joel Parsons Date: Mon, 11 Mar 2013 13:15:19 +0000 Subject: [PATCH 50/69] The documentations states registered operation classes are consulted to the reverse order in which they are registered. New registrations are added to the beginning of the array in the register implementation. Fixed using the reverseObjectEnumerator when iterating the array which produced the opposite of documented behaviour. fixes #794 --- AFNetworking/AFHTTPClient.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index f9d2166..d4bba2f 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -517,12 +517,12 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { AFHTTPRequestOperation *operation = nil; - NSString *className = nil; - NSEnumerator *enumerator = [self.registeredHTTPOperationClassNames reverseObjectEnumerator]; - while (!operation && (className = [enumerator nextObject])) { + + for (NSString * className in self.registeredHTTPOperationClassNames) { Class op_class = NSClassFromString(className); if (op_class && [op_class canProcessRequest:urlRequest]) { operation = [(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest]; + break; } } From 1bd7faf9644337905b217506158a6e95166634e8 Mon Sep 17 00:00:00 2001 From: Joel Parsons Date: Tue, 12 Mar 2013 10:47:45 +0000 Subject: [PATCH 51/69] changed op_class variable to more objective-c style variable name operationClass --- AFNetworking/AFHTTPClient.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index d4bba2f..d250397 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -519,9 +519,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { AFHTTPRequestOperation *operation = nil; for (NSString * className in self.registeredHTTPOperationClassNames) { - Class op_class = NSClassFromString(className); - if (op_class && [op_class canProcessRequest:urlRequest]) { - operation = [(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest]; + Class operationClass = NSClassFromString(className); + if (operationClass && [operationClass canProcessRequest:urlRequest]) { + operation = [(AFHTTPRequestOperation *)[operationClass alloc] initWithRequest:urlRequest]; break; } } From f9a0cbff3f8fff6c4a4dcc0145dd3af59bece9ff Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 14 Mar 2013 12:46:16 -0700 Subject: [PATCH 52/69] Minor formatting fix --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 9c7fc48..be0de71 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -518,7 +518,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { { AFHTTPRequestOperation *operation = nil; - for (NSString * className in self.registeredHTTPOperationClassNames) { + for (NSString *className in self.registeredHTTPOperationClassNames) { Class operationClass = NSClassFromString(className); if (operationClass && [operationClass canProcessRequest:urlRequest]) { operation = [(AFHTTPRequestOperation *)[operationClass alloc] initWithRequest:urlRequest]; From 167aeb1be0364f6b49e55093216fb90d7100d878 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 14 Mar 2013 12:48:05 -0700 Subject: [PATCH 53/69] Minor formatting fixes --- AFNetworking/AFHTTPClient.h | 2 +- AFNetworking/AFHTTPClient.m | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index eb6fb7c..bbf575d 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -564,7 +564,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType - 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. diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index be0de71..bcd3a67 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -821,6 +821,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; NSString *fileName = [fileURL lastPathComponent]; NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]); + return [self appendPartWithFileURL:fileURL name:name fileName:fileName mimeType:mimeType error:error]; } @@ -828,7 +829,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType - error:(NSError *__autoreleasing *)error + error:(NSError * __autoreleasing *)error { NSParameterAssert(fileURL); NSParameterAssert(name); From 29c87a3c92433bf82bfeb7c7ca4fd8e0ac0360d4 Mon Sep 17 00:00:00 2001 From: Konstantinos Vaggelakos Date: Thu, 14 Mar 2013 12:56:38 -0700 Subject: [PATCH 54/69] UIImageView+AFNetworking not using setHTTPShouldHandleCookies Signed-off-by: Mattt Thompson --- AFNetworking/UIImageView+AFNetworking.m | 1 - 1 file changed, 1 deletion(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 8e7f4b7..f340997 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -87,7 +87,6 @@ static char kAFImageRequestOperationObjectKey; placeholderImage:(UIImage *)placeholderImage { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setHTTPShouldHandleCookies:NO]; [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; From ac30ff95448b8489607c9b35609f48756d4cb129 Mon Sep 17 00:00:00 2001 From: joein3d Date: Mon, 18 Mar 2013 17:02:41 -0400 Subject: [PATCH 55/69] Add ability to appendPartWithInputStream to AFMultipartFormData. --- AFNetworking/AFHTTPClient.h | 16 ++++++++++++++++ AFNetworking/AFHTTPClient.m | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index d1c6f73..87caab4 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -572,6 +572,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; - (void)appendPartWithFormData:(NSData *)data name:(NSString *)name; + /** Appends HTTP headers, followed by the encoded data and the multipart form boundary. @@ -581,6 +582,21 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body; +/** + 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; + /** Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream. diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index f9d2166..8b58a22 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -893,6 +893,31 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; [self.bodyStream appendHTTPBodyPart:bodyPart]; } +- (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)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay { @@ -1136,6 +1161,8 @@ typedef enum { _inputStream = [NSInputStream inputStreamWithData:self.body]; } else if ([self.body isKindOfClass:[NSURL class]]) { _inputStream = [NSInputStream inputStreamWithURL:self.body]; + } else if ( [self.body isKindOfClass:[NSInputStream class]] ) { + _inputStream = self.body; } } From 1bfed80989d984b35b6fac6439a7a7c8294d58fc Mon Sep 17 00:00:00 2001 From: Oliver Letterer Date: Fri, 8 Feb 2013 19:41:59 +0100 Subject: [PATCH 56/69] Adds `AFSSLPinningModeNone`. --- AFNetworking/AFURLConnectionOperation.h | 1 + AFNetworking/AFURLConnectionOperation.m | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index f8f9874..f4c3b0e 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -86,6 +86,7 @@ #ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ typedef enum { + AFSSLPinningModeNone, AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, } AFURLConnectionOperationSSLPinningMode; diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 3d538e0..24818de 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -579,6 +579,24 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe 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; + } } } } From 8a642a26988486ef888a77c0459f52cea56584e4 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 00:57:04 -0400 Subject: [PATCH 57/69] Minor formatting and documentation edits --- AFNetworking/AFHTTPClient.h | 2 +- AFNetworking/AFURLConnectionOperation.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 1f58203..cecaced 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -21,9 +21,9 @@ // THE SOFTWARE. #import +#import "AFURLConnectionOperation.h" #import -#import "AFURLConnectionOperation.h" /** `AFHTTPClient` captures the common patterns of communicating with an web application over HTTP. It encapsulates information like base URL, authorization credentials, and HTTP headers, and uses them to construct and manage the execution of HTTP request operations. diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index f4c3b0e..1a54a5c 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -169,7 +169,7 @@ NSCoding, NSCopying> /** 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. + @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; From 327cc7cea3a85ff425da1082be5111302ff67473 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 01:23:38 -0400 Subject: [PATCH 58/69] Minor refactoring / reformatting after merge --- AFNetworking/AFHTTPClient.m | 91 ++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index e38ad81..452d498 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -943,30 +943,29 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; #pragma mark - @interface AFMultipartBodyStreamProvider () -@property (nonatomic, assign) NSStreamStatus streamStatus; -@property (nonatomic, strong) NSError *streamError; - @property (nonatomic, assign) NSStringEncoding stringEncoding; @property (nonatomic, strong) NSMutableArray *HTTPBodyParts; @property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator; @property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart; +@property (nonatomic, strong) NSInputStream *inputStream; +@property (nonatomic, strong) NSOutputStream *outputStream; +@property (nonatomic, strong) NSMutableData *buffer; @end static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; @implementation AFMultipartBodyStreamProvider { - NSInputStream *_inputStream; - NSOutputStream *_outputStream; - NSMutableData *_buffer; - - id _keepalive; +@private + // Workaround for stream delegates being weakly referenced, but otherwise unowned + __strong id _self; } -@synthesize streamStatus = _streamStatus; -@synthesize streamError = _streamError; @synthesize stringEncoding = _stringEncoding; @synthesize HTTPBodyParts = _HTTPBodyParts; @synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator; @synthesize currentHTTPBodyPart = _currentHTTPBodyPart; +@synthesize inputStream = _inputStream; +@synthesize outputStream = _outputStream; +@synthesize buffer = _buffer; @synthesize numberOfBytesInPacket = _numberOfBytesInPacket; @synthesize delay = _delay; @@ -980,7 +979,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; self.HTTPBodyParts = [NSMutableArray array]; self.numberOfBytesInPacket = NSIntegerMax; - _buffer = [[NSMutableData alloc] init]; + self.buffer = [[NSMutableData alloc] init]; return self; } @@ -1006,7 +1005,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; } - (NSInputStream *)inputStream { - if(_inputStream == nil) { + if (_inputStream == nil) { CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreateBoundPair(NULL, &readStream, &writeStream, AFMultipartBodyStreamProviderBufferSize); @@ -1014,16 +1013,16 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; _outputStream = CFBridgingRelease(writeStream); _outputStream.delegate = self; - if([NSThread isMainThread]) { - [_outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; - } - else { + if ([NSThread isMainThread]) { + [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + } else { dispatch_sync(dispatch_get_main_queue(), ^{ - [_outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; + [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; }); } [_outputStream open]; - _keepalive = self; + + _self = self; } return _inputStream; @@ -1035,60 +1034,50 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; #pragma mark - NSStreamDelegate -- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { - if(eventCode & NSStreamEventHasSpaceAvailable) { +- (void)stream:(NSStream *)stream + handleEvent:(NSStreamEvent)eventCode +{ + if (eventCode & NSStreamEventHasSpaceAvailable) { [self handleOutputStreamSpaceAvailable]; } } - (void)handleOutputStreamSpaceAvailable { - while([_outputStream hasSpaceAvailable]) { - if([_buffer length] > 0) { - NSInteger ret = [_outputStream write: [_buffer bytes] maxLength: [_buffer length]]; - if(ret < 0) { - /* I don't think an error should ever actually happen with a bound pair. - * If it does, we'll just close the stream and give up. */ + while ([_outputStream hasSpaceAvailable]) { + if ([_buffer length] > 0) { + NSInteger numberOfBytesWritten = [_outputStream write:[_buffer bytes] maxLength:[_buffer length]]; + if (numberOfBytesWritten < 0) { [self close]; return; - } else { - /* Delete the written bytes from the buffer. */ - [_buffer replaceBytesInRange: NSMakeRange(0, ret) withBytes: NULL length: 0]; } + + [_buffer replaceBytesInRange:NSMakeRange(0, numberOfBytesWritten) withBytes:NULL length:0]; } else { - /* Refill the buffer. */ - - /* Make sure the current body part is valid. */ - if(self.currentHTTPBodyPart == nil) { - if(self.HTTPBodyPartEnumerator == nil) { + if (!self.currentHTTPBodyPart) { + if (!self.HTTPBodyPartEnumerator) { self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator]; } self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject]; } - /* If the current part is still nil, then it's the end of the road: close the stream and bail. */ - if(self.currentHTTPBodyPart == nil) { + if (!self.currentHTTPBodyPart) { [self close]; return; } - /* Read some data. */ - [_buffer setLength: AFMultipartBodyStreamProviderBufferSize]; - NSInteger ret = [self.currentHTTPBodyPart read: [_buffer mutableBytes] maxLength: [_buffer length]]; - if(ret < 0) { - /* Not sure how to handle an error currently. Close the output stream and bail out. */ + [_buffer setLength:AFMultipartBodyStreamProviderBufferSize]; + + NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:[_buffer mutableBytes] maxLength:[_buffer length]]; + if (numberOfBytesRead < 0) { [self close]; return; } - /* Resize the buffer to how much was actually read. */ - [_buffer setLength: ret]; + [_buffer setLength:numberOfBytesRead]; - /* If we hit EOF, invalidate the current body part so the next pass through will find a new one. */ - if(ret == 0) { + if(numberOfBytesRead == 0) { self.currentHTTPBodyPart = nil; - } - - /* Fall off the end. The next loop through will get data out of the buffer. */ + } } } } @@ -1096,7 +1085,8 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; - (void)close { [_outputStream close]; _outputStream.delegate = nil; - _keepalive = nil; + + _self = nil; } - (unsigned long long)contentLength { @@ -1110,7 +1100,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; #pragma mark - NSCopying --(id)copyWithZone:(NSZone *)zone { +- (id)copyWithZone:(NSZone *)zone { AFMultipartBodyStreamProvider *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding]; for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { @@ -1161,7 +1151,6 @@ typedef enum { return nil; } - _phase = AFInitialPhase; [self transitionToNextPhase]; return self; From 48d05e215fc70dfbb5bb8af8696ebda3a370b253 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 01:30:46 -0400 Subject: [PATCH 59/69] Re-implementing throttling in stream provider architecture --- AFNetworking/AFHTTPClient.m | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 452d498..0dd6874 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -778,7 +778,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; @end @interface AFMultipartBodyStreamProvider : NSObject -@property (nonatomic, assign) NSUInteger numberOfBytesInPacket; +@property (nonatomic, assign) NSUInteger bufferLength; @property (nonatomic, assign) NSTimeInterval delay; @property (nonatomic, readonly) unsigned long long contentLength; @property (nonatomic, readonly, getter = isEmpty) BOOL empty; @@ -919,7 +919,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay { - self.bodyStream.numberOfBytesInPacket = numberOfBytes; + self.bodyStream.bufferLength = numberOfBytes; self.bodyStream.delay = delay; } @@ -952,7 +952,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; @property (nonatomic, strong) NSMutableData *buffer; @end -static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; +static const NSUInteger AFMultipartBodyStreamProviderDefaultBufferLength = 4096; @implementation AFMultipartBodyStreamProvider { @private @@ -966,7 +966,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; @synthesize inputStream = _inputStream; @synthesize outputStream = _outputStream; @synthesize buffer = _buffer; -@synthesize numberOfBytesInPacket = _numberOfBytesInPacket; +@synthesize bufferLength = _numberOfBytesInPacket; @synthesize delay = _delay; - (id)initWithStringEncoding:(NSStringEncoding)encoding { @@ -977,9 +977,10 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; self.stringEncoding = encoding; self.HTTPBodyParts = [NSMutableArray array]; - self.numberOfBytesInPacket = NSIntegerMax; + self.bufferLength = NSIntegerMax; self.buffer = [[NSMutableData alloc] init]; + self.bufferLength = AFMultipartBodyStreamProviderDefaultBufferLength; return self; } @@ -1008,7 +1009,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; if (_inputStream == nil) { CFReadStreamRef readStream; CFWriteStreamRef writeStream; - CFStreamCreateBoundPair(NULL, &readStream, &writeStream, AFMultipartBodyStreamProviderBufferSize); + CFStreamCreateBoundPair(NULL, &readStream, &writeStream, self.bufferLength); _inputStream = CFBridgingRelease(readStream); _outputStream = CFBridgingRelease(writeStream); @@ -1065,7 +1066,7 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; return; } - [_buffer setLength:AFMultipartBodyStreamProviderBufferSize]; + [_buffer setLength:self.bufferLength]; NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:[_buffer mutableBytes] maxLength:[_buffer length]]; if (numberOfBytesRead < 0) { @@ -1074,10 +1075,14 @@ static const NSUInteger AFMultipartBodyStreamProviderBufferSize = 4096; } [_buffer setLength:numberOfBytesRead]; - + if(numberOfBytesRead == 0) { self.currentHTTPBodyPart = nil; - } + } + + if (self.delay > 0.0f) { + [NSThread sleepForTimeInterval:self.delay]; + } } } } From 7211755d9cd8538b91296cdee2fe30e818d79712 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 01:42:29 -0400 Subject: [PATCH 60/69] Minor reformatting --- AFNetworking/AFHTTPClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index fafe0d9..b915d6f 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1199,7 +1199,7 @@ typedef enum { _inputStream = [NSInputStream inputStreamWithData:self.body]; } else if ([self.body isKindOfClass:[NSURL class]]) { _inputStream = [NSInputStream inputStreamWithURL:self.body]; - } else if ( [self.body isKindOfClass:[NSInputStream class]] ) { + } else if ([self.body isKindOfClass:[NSInputStream class]]) { _inputStream = self.body; } } From edebae2de672c0651a1f964dbcd806a34a70f5b2 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 01:42:50 -0400 Subject: [PATCH 61/69] Replacing getter method definition with readonly property --- AFNetworking/AFHTTPClient.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index b915d6f..d4c4042 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -780,14 +780,13 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; @interface AFMultipartBodyStreamProvider : NSObject @property (nonatomic, assign) NSUInteger bufferLength; @property (nonatomic, assign) NSTimeInterval delay; +@property (nonatomic, readonly) NSInputStream *inputStream; @property (nonatomic, readonly) unsigned long long contentLength; @property (nonatomic, readonly, getter = isEmpty) BOOL empty; - (id)initWithStringEncoding:(NSStringEncoding)encoding; - (void)setInitialAndFinalBoundaries; - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart; - -- (NSInputStream *)inputStream; @end #pragma mark - From 45c05caaa9799a64c9d64988ad035f329dd5c5e0 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:09:08 -0400 Subject: [PATCH 62/69] Renaming defaultPinMode -> defaultPinningMode, to match AFURLConnectionOperation Moving setting of pinning mode to creation of operation rather than -enqueueHTTPRequestOperation --- AFNetworking/AFHTTPClient.h | 2 +- AFNetworking/AFHTTPClient.m | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 398bb10..4c27c93 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -142,7 +142,7 @@ typedef enum { Default SSL pinning mode for each `AFHTTPRequestOperation` which will be enqueued with `enqueueHTTPRequestOperation:`. */ #ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ -@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinMode; +@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinningMode; #endif ///--------------------------------------------- diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index d4c4042..88ec1cb 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -533,6 +533,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { [operation setCompletionBlockWithSuccess:success failure:failure]; operation.credential = self.defaultCredential; +#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ + operation.SSLPinningMode = self.defaultSSLPinningMode; +#endif return operation; } @@ -540,10 +543,6 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { #pragma mark - - (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation { -#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ - operation.SSLPinningMode = self.defaultSSLPinMode; -#endif - [self.operationQueue addOperation:operation]; } From e8d55c8896150fa888257f45eb397f934697b922 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:09:39 -0400 Subject: [PATCH 63/69] Adding documentation for AFSSLPinningModeNone --- AFNetworking/AFURLConnectionOperation.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index 1a54a5c..b3a94db 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -320,9 +320,13 @@ NSCoding, NSCopying> 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). From 59039d6a8348c2591b1a6ecb0bfcb9b49f3036e8 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:13:37 -0400 Subject: [PATCH 64/69] Re-ordering AFHTTPClient multipart proxy methods --- AFNetworking/AFHTTPClient.h | 30 +++++++++++----------- AFNetworking/AFHTTPClient.m | 51 +++++++++++++++++++------------------ 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 4c27c93..5551f5d 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -574,6 +574,21 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; 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. @@ -607,21 +622,6 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body; -/** - 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; - /** Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream. diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 88ec1cb..bd0cab2 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -873,6 +873,32 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; return YES; } + +- (void)appendPartWithInputStream:(NSInputStream *)inputStream + name:(NSString *)name + fileName:(NSString *)fileName + length:(unsigned long long)length + mimeType:(NSString *)mimeType +{ + NSParameterAssert(name); + NSParameterAssert(fileName); + NSParameterAssert(mimeType); + + NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; + [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; + [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; + + + AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; + bodyPart.stringEncoding = self.stringEncoding; + bodyPart.headers = mutableHeaders; + bodyPart.body = inputStream; + + bodyPart.bodyContentLength = length; + + [self.bodyStream appendHTTPBodyPart:bodyPart]; +} + - (void)appendPartWithFileData:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName @@ -914,31 +940,6 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; [self.bodyStream appendHTTPBodyPart:bodyPart]; } -- (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)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay { From 90f84c7120dd786c302ce489ec894c10ffa429ca Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:22:28 -0400 Subject: [PATCH 65/69] Updating CHANGES to 1.2.0 release --- CHANGES | 203 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 135 insertions(+), 68 deletions(-) diff --git a/CHANGES b/CHANGES index 70f5a33..0e3c9a1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,70 @@ += 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` + + * Fix request stream exhaustion error on authentication challenges (Alex Burgel) + + * 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 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) * Add optional SSL certificate pinning with `#define _AFNETWORKING_PIN_SSL_CERTIFICATES_` (Dustin Barker) @@ -18,9 +85,9 @@ * 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 - deterministic ordering of query string parameters, which may otherwise - cause ambiguous representations of nested parameters (James Coleman, + * Change AFHTTPClient parameter serialization dictionary keys with `caseInsensitiveCompare:` to ensure + deterministic ordering of query string parameters, which may otherwise + cause ambiguous representations of nested parameters (James Coleman, Mattt Thompson) * Fix -Wstrict-selector-match warnings raised by Xcode 4.6DP3 (Jesse Collis, Cédric Luthi) @@ -48,19 +115,19 @@ * Fix __unused keywords for better Xcode indexing (Christian Rasmussen) * 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: 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: '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: '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) = 1.0.1 / 2012-11-01 @@ -72,7 +139,7 @@ was not correctly calculated (Stan Chang Khin Boon) placeholderImage:success:failure`:, it is now the responsibility of the block to set the image of the image view (Mattt Thompson) - * Add `JSONReadingOptions` property to `AFJSONRequestOperation` (Jeremy + * Add `JSONReadingOptions` property to `AFJSONRequestOperation` (Jeremy Foo, Mattt Thompson) * Using __weak self / __strong self pattern to break retain cycles in @@ -80,10 +147,10 @@ block to set the image of the image view (Mattt Thompson) * Fix parameter encoding to leave period (`.`) unescaped (Diego Torres) - * Fixing last file component in multipart form part creation (Sylver - Bruneau) - - * Remove executable permission on AFHTTPClient source files (Andrew + * Fixing last file component in multipart form part creation (Sylver + Bruneau) + + * Remove executable permission on AFHTTPClient source files (Andrew Sardone) * Fix warning (error with -Werror) on implicit 64 to 32 conversion (Dan @@ -96,144 +163,144 @@ block to set the image of the image view (Mattt Thompson) = 1.0 / 2012-10-15 * AFNetworking now requires iOS 5 / Mac OSX 10.7 or higher (Mattt Thompson) - + * AFNetworking now uses Automatic Reference Counting (ARC) (Mattt Thompson) - * AFNetworking raises compiler warnings for missing features when -SystemConfiguration or CoreServices / MobileCoreServices frameworks are not -included in the project and imported in the precompiled headers (Mattt + * AFNetworking raises compiler warnings for missing features when +SystemConfiguration or CoreServices / MobileCoreServices frameworks are not +included in the project and imported in the precompiled headers (Mattt Thompson) - * AFNetworking now raises compiler error when not compiled with ARC (Steven + * AFNetworking now raises compiler error when not compiled with ARC (Steven Fisher) - * Add `NSCoding` and `NSCopying` protocol conformance to + * Add `NSCoding` and `NSCopying` protocol conformance to `AFURLConnectionOperation` and `AFHTTPClient` (Mattt Thompson) - * Add substantial improvements HTTP multipart streaming support, having -files streamed directly from disk and read sequentially from a custom input + * Add substantial improvements HTTP multipart streaming support, having +files streamed directly from disk and read sequentially from a custom input stream (Max Lansing, Stan Chang Khin Boon, Mattt Thompson) - - * Add `AFMultipartFormData -throttleBandwidthWithPacketSize:delay:` as + + * Add `AFMultipartFormData -throttleBandwidthWithPacketSize:delay:` as workaround to issues when uploading over 3G (Mattt Thompson) - * Add request and response to `userInfo` of errors returned from failing + * Add request and response to `userInfo` of errors returned from failing `AFHTTPRequestOperation` (Mattt Thompson) - * Add `userInfo` dictionary with current status in reachability changes + * Add `userInfo` dictionary with current status in reachability changes (Mattt Thompson) - * Add `Accept` header for image requests in `UIImageView` category (Bratley + * Add `Accept` header for image requests in `UIImageView` category (Bratley Lower) - * Add explicit declaration of `NSURLConnection` delegate methods so that + * Add explicit declaration of `NSURLConnection` delegate methods so that they can be overridden in subclasses (Mattt Thompson, Evan Grim) - * Add parameter validation to match conditions specified in documentation + * Add parameter validation to match conditions specified in documentation (Jason Brennan, Mattt Thompson) - * Add import to `UIKit` to avoid build errors from `UIDevice` references in + * Add import to `UIKit` to avoid build errors from `UIDevice` references in `User-Agent` default header (Blake Watters) * Remove `AFJSONUtilities` in favor of `NSJSONSerialization` (Mattt Thompson) - * Remove `extern` declaration of `AFURLEncodedStringFromStringWithEncoding` -function (`CFURLCreateStringByAddingPercentEscapes` should be used instead) + * Remove `extern` declaration of `AFURLEncodedStringFromStringWithEncoding` +function (`CFURLCreateStringByAddingPercentEscapes` should be used instead) (Mattt Thompson) - * Remove `setHTTPShouldHandleCookies:NO` from `AFHTTPClient` (@phamsonha, + * Remove `setHTTPShouldHandleCookies:NO` from `AFHTTPClient` (@phamsonha, Mattt Thompson) - - * Remove `dispatch_retain` / `dispatch_release` with ARC in iOS 6 (Benoit + + * Remove `dispatch_retain` / `dispatch_release` with ARC in iOS 6 (Benoit Bourdon) - + * Fix threading issue with `AFNetworkActivityIndicatorManager` (Eric Patey) - * Fix issue where `AFNetworkActivityIndicatorManager` count could become + * Fix issue where `AFNetworkActivityIndicatorManager` count could become negative (@ap4y) - * Fix properties to explicitly set options to suppress warnings (Wen-Hao + * Fix properties to explicitly set options to suppress warnings (Wen-Hao Lue, Mattt Thompson) - * Fix compiler warning caused by mismatched types in upload / download + * Fix compiler warning caused by mismatched types in upload / download progress blocks (Gareth du Plooy, tomas.a) - - * Fix weak / strong variable relationships in `completionBlock` (Peter + + * Fix weak / strong variable relationships in `completionBlock` (Peter Steinberger) - * Fix string formatting syntax warnings caused by type mismatch (David + * Fix string formatting syntax warnings caused by type mismatch (David Keegan, Steven Fisher, George Cox) - * Fix minor potential security vulnerability by explicitly using string + * Fix minor potential security vulnerability by explicitly using string format in NSError localizedDescription value in userInfo (Steven Fisher) - * Fix `AFURLConnectionOperation -pause` by adding state checks to prevent + * Fix `AFURLConnectionOperation -pause` by adding state checks to prevent likely memory issues when resuming (Mattt Thompson) - - * Fix warning caused by miscast of type when + + * Fix warning caused by miscast of type when `CLANG_WARN_IMPLICIT_SIGN_CONVERSION` is set (Steven Fisher) * Fix incomplete implementation warning in example code (Steven Fisher) * Fix warning caused by using `==` comparator on floats (Steven Fisher) - * Fix iOS 4 bug where file URLs return `NSURLResponse` rather than + * Fix iOS 4 bug where file URLs return `NSURLResponse` rather than `NSHTTPURLResponse` objects (Leo Lobato) - * Fix calculation of finished operations in batch operation progress + * Fix calculation of finished operations in batch operation progress callback (Mattt Thompson) - * Fix documentation typos (Steven Fisher, Matthias Wessendorf, + * Fix documentation typos (Steven Fisher, Matthias Wessendorf, jorge@miv.uk.com) - * Fix `hasAcceptableStatusCode` to return true after a network failure (Tony + * Fix `hasAcceptableStatusCode` to return true after a network failure (Tony Million) - * Fix warning about missing prototype for private static method (Stephan + * Fix warning about missing prototype for private static method (Stephan Diederich) - * Fix issue where `nil` content type resulted in unacceptable content type + * Fix issue where `nil` content type resulted in unacceptable content type (Mattt Thompson) * Fix bug related to setup and scheduling of output stream (Stephen Tramer) - * Fix AFContentTypesFromHTTPHeader to correctly handle comma-delimited + * Fix AFContentTypesFromHTTPHeader to correctly handle comma-delimited content types (Peyman, Mattt Thompson, @jsm174) - * Fix crash caused by `_networkReachability` not being set to `NULL` after + * Fix crash caused by `_networkReachability` not being set to `NULL` after releasing (Blake Watters) - * Fix Podspec to correctly import required headers and use ARC (Eloy Durán, + * Fix Podspec to correctly import required headers and use ARC (Eloy Durán, Blake Watters) - * Fix query string parameter escaping to leave square brackets unescaped + * Fix query string parameter escaping to leave square brackets unescaped (Mattt Thompson) * Fix query string parameter encoding of `NSNull` values (Daniel Rinser) - * Fix error caused by referencing `__IPHONE_OS_VERSION_MIN_REQUIRED` without + * Fix error caused by referencing `__IPHONE_OS_VERSION_MIN_REQUIRED` without importing `Availability.h` (Blake Watters) - * Update example to use App.net API, as Twitter shut off its unauthorized + * Update example to use App.net API, as Twitter shut off its unauthorized access to the public timeline (Mattt Thompson) - * Update `AFURLConnectionOperation` to replace `NSAutoReleasePool` with + * Update `AFURLConnectionOperation` to replace `NSAutoReleasePool` with `@autoreleasepool` (Mattt Thompson) - * Update `AFHTTPClient` operation queue to specify -`NSOperationQueueDefaultMaxConcurrentOperationCount` rather than + * Update `AFHTTPClient` operation queue to specify +`NSOperationQueueDefaultMaxConcurrentOperationCount` rather than previously-defined constant (Mattt Thompson) - * Update `AFHTTPClient -initWithBaseURL` to automatically append trailing -slash, so as to fix common issue where default path is not respected without + * Update `AFHTTPClient -initWithBaseURL` to automatically append trailing +slash, so as to fix common issue where default path is not respected without trailing slash (Steven Fisher) - - * Update default `AFHTTPClient` `User-Agent` header strings (Mattt Thompson, + + * Update default `AFHTTPClient` `User-Agent` header strings (Mattt Thompson, Steven Fisher) - + * Update icons for iOS example application (Mattt Thompson) - * Update `numberOfCompletedOperations` variable in progress block to be + * Update `numberOfCompletedOperations` variable in progress block to be renamed to `numberOfFinishedOperations` (Mattt Thompson) From feb55db8599b43a65adffcf8013bd15a7aca7ecd Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:22:50 -0400 Subject: [PATCH 66/69] Bumping version to 1.2.0 --- AFNetworking.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking.podspec b/AFNetworking.podspec index b7e836b..c3a8dbb 100644 --- a/AFNetworking.podspec +++ b/AFNetworking.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'AFNetworking' - s.version = '1.1.0' + s.version = '1.2.0' s.license = 'MIT' s.summary = 'A delightful iOS and OS X networking framework.' s.homepage = 'https://github.com/AFNetworking/AFNetworking' 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.requires_arc = true From 7e8422f4d24944579377e80cfe79b62efcd26813 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:28:55 -0400 Subject: [PATCH 67/69] Reformatting CHANGES --- CHANGES | 83 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/CHANGES b/CHANGES index 0e3c9a1..db12304 100644 --- a/CHANGES +++ b/CHANGES @@ -1,67 +1,96 @@ = 1.2.0 (2013-03-24) - * Add `SSLPinningMode` property to `AFHTTPClient` (Oliver Letterer, Kevin Harwood, Adam Becevello, Dustin Barker, Mattt Thompson) + * 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 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` - * Fix request stream exhaustion error on authentication challenges (Alex Burgel) + * Add `shouldUseCredentialStorage` property to `AFURLConnectionOperation` +(Mattt Thompson) - * Add `shouldUseCredentialStorage` property to `AFURLConnectionOperation` (Mattt Thompson) + * Add support for repeated key value pairs in `AFHTTPClient` URL query string +(Nick Dawson) - * 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 - appendPartWithFileURL:name:fileName:mimeType:error` (Daniel Rodríguez Troitiño) + * Add `AFMultipartFormData - +appendPartWithInputStream:name:fileName:mimeType:` (@joein3d) - * Add `AFMultipartFormData - appendPartWithInputStream:name:fileName:mimeType:` (@joein3d) + * Change SSL pinning to be runtime property on `AFURLConnectionOperation` +rather than defined by macro (Oliver Letterer) - * 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 `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 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 `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 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 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 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 `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 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 `AFNetworkActivityIndicatorManager` to only update if requests have a non-`nil` URL (Cédric Luthi) + * Change `UIImageView+AFNetworking` to not do `setHTTPShouldHandleCookies` +(Konstantinos Vaggelakos) - * 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 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 `responseJSON`, `responseString`, and `responseStringEncoding` to be +threadsafe (Jon Parise, Mattt Thompson) - * Fix `AFContentTypeForPathExtension` to ensure non-`NULL` content return value (Zach Waugh) + * 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 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 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 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 'postNotificationName:object:' found +[-Wstrict-selector-match] (Oliver Jones) - * Fix warning: multiple methods named 'objectForKey:' 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 warning: weak receiver may be unpredictably set to nil +[-Wreceiver-is-weak] (Oliver Jones) * Fix missing #pragma clang diagnostic pop (Steven Fisher) From 566a40f469a07f88be5b4669fd750f98973fe852 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 24 Mar 2013 02:29:59 -0400 Subject: [PATCH 68/69] Reformatting CHANGES --- CHANGES | 82 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/CHANGES b/CHANGES index db12304..0767b58 100644 --- a/CHANGES +++ b/CHANGES @@ -96,68 +96,100 @@ Parsons) = 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 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 cause ambiguous representations of nested parameters (James Coleman, 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 `-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 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: 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 From 71157c90a0a9dc1a66b0d6bde7da23467134fa5c Mon Sep 17 00:00:00 2001 From: Kevin Harwood Date: Sun, 24 Mar 2013 08:45:36 -0500 Subject: [PATCH 69/69] Small correction to SSL Pinning documentation --- AFNetworking/AFURLConnectionOperation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index b3a94db..c50ce24 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -315,7 +315,7 @@ NSCoding, NSCopying> ///---------------- /** - ## Network Reachability + ## SSL Pinning Options The following constants are provided by `AFURLConnectionOperation` as possible SSL Pinning options.