mirror of
https://github.com/silkimen/cordova-plugin-advanced-http.git
synced 2026-04-24 00:00:03 +08:00
Now working for both ios and android with same api. Updated AFNetworking
This commit is contained in:
@@ -25,16 +25,16 @@
|
||||
#if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||
static NSData * AFSecKeyGetData(SecKeyRef key) {
|
||||
CFDataRef data = NULL;
|
||||
|
||||
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data);
|
||||
#else
|
||||
OSStatus status = SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data);
|
||||
NSCAssert(status == errSecSuccess, @"SecItemExport error: %ld", (long int)status);
|
||||
#endif
|
||||
|
||||
|
||||
NSCParameterAssert(data);
|
||||
|
||||
|
||||
return (__bridge_transfer NSData *)data;
|
||||
}
|
||||
#endif
|
||||
@@ -50,10 +50,10 @@ static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) {
|
||||
static id AFPublicKeyForCertificate(NSData *certificate) {
|
||||
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
|
||||
NSCParameterAssert(allowedCertificate);
|
||||
|
||||
|
||||
SecCertificateRef allowedCertificates[] = {allowedCertificate};
|
||||
CFArrayRef tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
|
||||
|
||||
|
||||
SecPolicyRef policy = SecPolicyCreateBasicX509();
|
||||
SecTrustRef allowedTrust = NULL;
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
@@ -62,49 +62,49 @@ static id AFPublicKeyForCertificate(NSData *certificate) {
|
||||
OSStatus status = SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust);
|
||||
NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
|
||||
#endif
|
||||
|
||||
|
||||
SecTrustResultType result = 0;
|
||||
|
||||
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
SecTrustEvaluate(allowedTrust, &result);
|
||||
#else
|
||||
status = SecTrustEvaluate(allowedTrust, &result);
|
||||
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
|
||||
#endif
|
||||
|
||||
|
||||
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust);
|
||||
NSCParameterAssert(allowedPublicKey);
|
||||
|
||||
|
||||
CFRelease(allowedTrust);
|
||||
CFRelease(policy);
|
||||
CFRelease(tempCertificates);
|
||||
CFRelease(allowedCertificate);
|
||||
|
||||
|
||||
return (__bridge_transfer id)allowedPublicKey;
|
||||
}
|
||||
|
||||
static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
|
||||
SecTrustResultType result = 0;
|
||||
|
||||
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
SecTrustEvaluate(serverTrust, &result);
|
||||
#else
|
||||
OSStatus status = SecTrustEvaluate(serverTrust, &result);
|
||||
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
|
||||
#endif
|
||||
|
||||
|
||||
return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
|
||||
}
|
||||
|
||||
static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) {
|
||||
CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
|
||||
NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
|
||||
|
||||
|
||||
for (CFIndex i = 0; i < certificateCount; i++) {
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
|
||||
[trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)];
|
||||
}
|
||||
|
||||
|
||||
return [NSArray arrayWithArray:trustChain];
|
||||
}
|
||||
|
||||
@@ -114,68 +114,36 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
|
||||
NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
|
||||
for (CFIndex i = 0; i < certificateCount; i++) {
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
|
||||
|
||||
|
||||
SecCertificateRef someCertificates[] = {certificate};
|
||||
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL);
|
||||
|
||||
|
||||
SecTrustRef trust = NULL;
|
||||
|
||||
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
SecTrustCreateWithCertificates(certificates, policy, &trust);
|
||||
|
||||
|
||||
SecTrustResultType result;
|
||||
SecTrustEvaluate(trust, &result);
|
||||
#else
|
||||
OSStatus status = SecTrustCreateWithCertificates(certificates, policy, &trust);
|
||||
NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
|
||||
|
||||
|
||||
SecTrustResultType result;
|
||||
status = SecTrustEvaluate(trust, &result);
|
||||
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
|
||||
#endif
|
||||
|
||||
|
||||
[trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)];
|
||||
|
||||
|
||||
CFRelease(trust);
|
||||
CFRelease(certificates);
|
||||
}
|
||||
CFRelease(policy);
|
||||
|
||||
|
||||
return [NSArray arrayWithArray:trustChain];
|
||||
}
|
||||
|
||||
static NSComparisonResult AFDomainComponentCompare(NSString *component1, NSString *component2) {
|
||||
if ([component1 isEqualToString:@"*"] || [component2 isEqualToString:@"*"]) {
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
return [component1 compare:component2];
|
||||
}
|
||||
|
||||
static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *domain) {
|
||||
certificateHost = [certificateHost lowercaseString];
|
||||
domain = [domain lowercaseString];
|
||||
|
||||
if ([certificateHost isEqualToString:domain]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSArray *certificateHostComponents = [certificateHost componentsSeparatedByString:@"."];
|
||||
NSArray *domainComponents = [domain componentsSeparatedByString:@"."];
|
||||
|
||||
if ([certificateHostComponents count] != [domainComponents count]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL certificateHostMatchesDomain = ([certificateHostComponents indexOfObjectPassingTest:^BOOL(NSString *certificateHostComponent, NSUInteger idx, __unused BOOL *stop) {
|
||||
NSString *domainComponent = [domainComponents objectAtIndex:idx];
|
||||
|
||||
return AFDomainComponentCompare(certificateHostComponent, domainComponent) != NSOrderedSame;
|
||||
}] == NSNotFound);
|
||||
|
||||
return certificateHostMatchesDomain;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface AFSecurityPolicy()
|
||||
@@ -190,23 +158,23 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
|
||||
|
||||
|
||||
NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]];
|
||||
for (NSString *path in paths) {
|
||||
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
||||
[certificates addObject:certificateData];
|
||||
}
|
||||
|
||||
|
||||
_defaultPinnedCertificates = [[NSArray alloc] initWithArray:certificates];
|
||||
});
|
||||
|
||||
|
||||
return _defaultPinnedCertificates;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultPolicy {
|
||||
AFSecurityPolicy *securityPolicy = [[self alloc] init];
|
||||
securityPolicy.SSLPinningMode = AFSSLPinningModeNone;
|
||||
|
||||
|
||||
return securityPolicy;
|
||||
}
|
||||
|
||||
@@ -215,7 +183,7 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
securityPolicy.SSLPinningMode = pinningMode;
|
||||
securityPolicy.validatesDomainName = YES;
|
||||
[securityPolicy setPinnedCertificates:[self defaultPinnedCertificates]];
|
||||
|
||||
|
||||
return securityPolicy;
|
||||
}
|
||||
|
||||
@@ -234,7 +202,7 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
|
||||
- (void)setPinnedCertificates:(NSArray *)pinnedCertificates {
|
||||
_pinnedCertificates = pinnedCertificates;
|
||||
|
||||
|
||||
if (self.pinnedCertificates) {
|
||||
NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]];
|
||||
for (NSData *certificate in self.pinnedCertificates) {
|
||||
@@ -255,12 +223,15 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
|
||||
forDomain:(NSString *)domain
|
||||
{
|
||||
BOOL shouldTrustServer = NO;
|
||||
|
||||
if (self.SSLPinningMode == AFSSLPinningModeNone && self.allowInvalidCertificates) {
|
||||
return YES;
|
||||
NSMutableArray *policies = [NSMutableArray array];
|
||||
if (self.validatesDomainName) {
|
||||
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
|
||||
} else {
|
||||
[policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
|
||||
}
|
||||
|
||||
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
|
||||
|
||||
if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {
|
||||
return NO;
|
||||
}
|
||||
@@ -270,6 +241,20 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
case AFSSLPinningModeNone:
|
||||
return YES;
|
||||
case AFSSLPinningModeCertificate: {
|
||||
NSMutableArray *pinnedCertificates = [NSMutableArray array];
|
||||
for (NSData *certificateData in self.pinnedCertificates) {
|
||||
[pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
|
||||
}
|
||||
SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
|
||||
|
||||
if (!AFServerTrustIsValid(serverTrust)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!self.validatesCertificateChain) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSUInteger trustedCertificateCount = 0;
|
||||
for (NSData *trustChainCertificate in serverCertificates) {
|
||||
if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
|
||||
@@ -277,12 +262,14 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
}
|
||||
}
|
||||
|
||||
shouldTrustServer = trustedCertificateCount > 0 && ((self.validatesCertificateChain && trustedCertificateCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedCertificateCount >= 1));
|
||||
return trustedCertificateCount == [serverCertificates count];
|
||||
}
|
||||
break;
|
||||
case AFSSLPinningModePublicKey: {
|
||||
NSUInteger trustedPublicKeyCount = 0;
|
||||
NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
|
||||
if (!self.validatesCertificateChain && [publicKeys count] > 0) {
|
||||
publicKeys = @[[publicKeys firstObject]];
|
||||
}
|
||||
|
||||
for (id trustChainPublicKey in publicKeys) {
|
||||
for (id pinnedPublicKey in self.pinnedPublicKeys) {
|
||||
@@ -292,22 +279,11 @@ static BOOL AFCertificateHostMatchesDomain(NSString *certificateHost, NSString *
|
||||
}
|
||||
}
|
||||
|
||||
shouldTrustServer = trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1));
|
||||
return trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (shouldTrustServer && domain && self.validatesDomainName) {
|
||||
NSData *serverCertificate = [serverCertificates firstObject];
|
||||
SecCertificateRef matchingCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)serverCertificate);
|
||||
NSParameterAssert(matchingCertificate);
|
||||
|
||||
shouldTrustServer = AFCertificateHostMatchesDomain((__bridge_transfer NSString *)SecCertificateCopySubjectSummary(matchingCertificate), domain);
|
||||
|
||||
CFRelease(matchingCertificate);
|
||||
}
|
||||
|
||||
return shouldTrustServer;
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - NSKeyValueObserving
|
||||
|
||||
@@ -191,7 +191,7 @@ forHTTPHeaderField:(NSString *)field;
|
||||
*/
|
||||
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
||||
URLString:(NSString *)URLString
|
||||
parameters:(NSDictionary *)parameters DEPRECATED_ATTRIBUTE;
|
||||
parameters:(id)parameters DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
Creates an `NSMutableURLRequest` object with the specified HTTP method and URL string.
|
||||
@@ -207,7 +207,7 @@ forHTTPHeaderField:(NSString *)field;
|
||||
*/
|
||||
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
||||
URLString:(NSString *)URLString
|
||||
parameters:(NSDictionary *)parameters
|
||||
parameters:(id)parameters
|
||||
error:(NSError * __autoreleasing *)error;
|
||||
|
||||
/**
|
||||
|
||||
@@ -212,8 +212,9 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||
if (userAgent) {
|
||||
if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
|
||||
NSMutableString *mutableUserAgent = [userAgent mutableCopy];
|
||||
CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false);
|
||||
userAgent = mutableUserAgent;
|
||||
if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
|
||||
userAgent = mutableUserAgent;
|
||||
}
|
||||
}
|
||||
[self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
|
||||
}
|
||||
@@ -262,14 +263,14 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||
|
||||
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
||||
URLString:(NSString *)URLString
|
||||
parameters:(NSDictionary *)parameters
|
||||
parameters:(id)parameters
|
||||
{
|
||||
return [self requestWithMethod:method URLString:URLString parameters:parameters error:nil];
|
||||
}
|
||||
|
||||
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
||||
URLString:(NSString *)URLString
|
||||
parameters:(NSDictionary *)parameters
|
||||
parameters:(id)parameters
|
||||
error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(method);
|
||||
|
||||
@@ -101,20 +101,11 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
|
||||
}
|
||||
|
||||
if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) {
|
||||
NSStringEncoding stringEncoding = self.stringEncoding;
|
||||
if (response.textEncodingName) {
|
||||
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||
if (encoding != kCFStringEncodingInvalidId) {
|
||||
stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: responseString,
|
||||
NSURLErrorFailingURLErrorKey:[response URL],
|
||||
AFNetworkingOperationFailingURLResponseErrorKey: response
|
||||
};
|
||||
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%lu)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (unsigned long)response.statusCode],
|
||||
NSURLErrorFailingURLErrorKey:[response URL],
|
||||
AFNetworkingOperationFailingURLResponseErrorKey: response
|
||||
};
|
||||
|
||||
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo], validationError);
|
||||
|
||||
@@ -220,33 +211,35 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
|
||||
}
|
||||
|
||||
id responseObject = nil;
|
||||
NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
|
||||
if (responseString && ![responseString isEqualToString:@" "]) {
|
||||
// Workaround for a bug in NSJSONSerialization when Unicode character escape codes are used instead of the actual character
|
||||
// See http://stackoverflow.com/a/12843465/157142
|
||||
data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *serializationError = nil;
|
||||
@autoreleasepool {
|
||||
NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
|
||||
if (responseString && ![responseString isEqualToString:@" "]) {
|
||||
// Workaround for a bug in NSJSONSerialization when Unicode character escape codes are used instead of the actual character
|
||||
// See http://stackoverflow.com/a/12843465/157142
|
||||
data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
NSError *serializationError = nil;
|
||||
if (data) {
|
||||
if ([data length] > 0) {
|
||||
responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
|
||||
if (data) {
|
||||
if ([data length] > 0) {
|
||||
responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
return nil;
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", nil, @"AFNetworking"),
|
||||
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", nil, @"AFNetworking"), responseString]
|
||||
};
|
||||
|
||||
serializationError = [NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
|
||||
}
|
||||
} else {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", nil, @"AFNetworking"),
|
||||
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", nil, @"AFNetworking"), responseString]
|
||||
};
|
||||
|
||||
serializationError = [NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
|
||||
}
|
||||
|
||||
if (error) {
|
||||
*error = AFErrorWithUnderlyingError(serializationError, *error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (error) {
|
||||
*error = AFErrorWithUnderlyingError(serializationError, *error);;
|
||||
}
|
||||
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user