Compare commits

..

19 Commits

Author SHA1 Message Date
Sefa Ilkimen
314314d7f9 release v2.0.6 2019-03-11 14:20:57 +01:00
Sefa Ilkimen
a8e3637f27 Merge branch 'chrisjdev-master' 2019-03-11 14:01:37 +01:00
Sefa Ilkimen
56272b9a5d Update changelog 2019-03-11 13:59:17 +01:00
Sefa Ilkimen
8f859db57f Merge branch 'master' of https://github.com/chrisjdev/cordova-plugin-advanced-http into chrisjdev-master 2019-03-11 11:34:10 +01:00
Sefa Ilkimen
e673754b13 Test for #184 2019-03-01 18:12:46 +01:00
Sefa Ilkimen
a0f376233c Fix #187: setSSLCertMode with "default" throws an error on Android 2019-03-01 18:12:06 +01:00
Sefa Ilkimen
fcd142a70b release v2.0.5 2019-02-25 13:08:25 +01:00
Sefa Ilkimen
807400bc63 Fix #185: need more detailed SSL error message 2019-02-22 19:20:12 +01:00
Sefa Ilkimen
1fd857f1d9 release v2.0.4 2019-01-17 17:30:43 +01:00
Sefa Ilkimen
f801d2a283 Update changelog 2019-01-17 17:26:24 +01:00
Sefa Ilkimen
6033ea4b76 Fix #179: Can't send empty string with utf8 serializer 2019-01-17 17:03:12 +01:00
Sefa Ilkimen
dadbf97d0c release v2.0.3 2019-01-15 17:00:54 +01:00
Sefa Ilkimen
f06788d199 Update cordova to fix peer dependency issues 2019-01-15 16:58:00 +01:00
Sefa Ilkimen
a195de409d Fix #172: plugin does not respect user installed CA certs on Android 2018-12-23 19:00:51 +01:00
Chris J
0fade8351d Merge pull request #1 from chrisjdev/keepSessionManager
Keep AFHTTPSessionManager instance with the plugin
2018-12-20 10:49:05 -05:00
Chris J
ebd6ae9793 Keep AFHTTPSessionManager instance with the plugin
Persist the AFHTTPSessionManager instance for the life of the plugin to allow reusing the underlying sockets, for example, with "Connection: keep-alive" headers.
2018-12-20 10:47:13 -05:00
Sefa Ilkimen
49f219723d Fix test scripts for linux bash 2018-12-12 19:46:58 +01:00
Sefa Ilkimen
f1bb4f36d0 Fix android test suite 2018-12-12 15:29:27 +01:00
Sefa Ilkimen
e2a869bbd2 Running android tests based on android image instead of xcode image (travis config) 2018-12-12 15:23:05 +01:00
19 changed files with 6532 additions and 83 deletions

View File

@@ -1,12 +1,6 @@
sudo: false
language: objective-c
os: osx
osx_image: xcode9.3
env:
- TARGET_PLATFORM=ios
- TARGET_PLATFORM=android ANDROID_API_LEVEL=27 ANDROID_BUILD_TOOLS_VERSION=28.0.3
notifications:
slack:
secure: lXE+2AgsxZU5G5dI91LkMAIgo8MAWfdM7DB5UOtn5LpuNln+2FmJo1gOI7tkdmLOqpXTGYnpI2VyQN3H4nOF21YhuouzD1Sh8n2wtQg1iTm353kuQpqiVhSBX8ZJ7Be1e1G8OsnxoYOxbs4Zo9qI40EruwkvqLCBHWM5MRGyd4M7EFWwb9Z29VZN0y1Nt5g/c3bT76kdKmF+JCLur2OeEKxAity7sIKgZekSqeIMwEVLSxXnda6Dbjc/cg0MJ0iDArkD7iu6fz/Fcrrxgm/pUxjcgvqze7Gy5i31mjEfspnrglWV1cshMd48BTDKCJ2AMmxH8O3GPSWE2txjIvGRWUve7iViNylvmQCVz3Eyf99+4EuuVGa+5PSodQ/CqODx/65EwtcN3PE1tNz2puKOK8nrOJcFkcbG8KTHKUlQtHCkjitbykUnj/hvhLK5/oWlQYVOLWWrHwdGUh8FI8aFPVGjRjWbHbhdayjEIqxwr1ns+6mYrP1EFNXbaeZxnLNC59XpJl1ifuezqYAk7YEiU5j4rtC7YKgyQ3ueb7anOHTJoTMyDn8mpZXgwuyhoBaeEYytQVgRyMtL6Y5cP98Jn2kv0+vdne3rkk9/JEBTo32HOjvoij6rsqEvXC0LhUDJSNadOVdHht0jjoN6zBH37HIE5/3zysLlPcAcHAS83ow=
cache:
directories:
@@ -15,30 +9,51 @@ cache:
addons:
sauce_connect: true
before_install:
- export LANG=en_US.UTF-8
matrix:
include:
- name: "iOS Build & Test"
language: objective-c
sudo: false
os: osx
osx_image: xcode10.1
install:
- npm install
- if [ $TARGET_PLATFORM = "android" ]; then
brew update &&
brew install gradle &&
scripts/setup-android-sdk.sh -a $ANDROID_API_LEVEL -b $ANDROID_BUILD_TOOLS_VERSION &&
export ANDROID_HOME=$(pwd)/android-sdk-macosx &&
export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION;
fi
before_install:
- export LANG=en_US.UTF-8
script:
- npm run testjs
- npm run updatecert
- travis_wait scripts/build-test-app.sh --$TARGET_PLATFORM --emulator &&
scripts/upload-artifact.sh --$TARGET_PLATFORM &&
scripts/test-app.sh --$TARGET_PLATFORM --emulator;
install:
- npm install
after_success:
script:
- npm run testjs &&
npm run updatecert &&
scripts/build-test-app.sh --ios --emulator &&
scripts/upload-artifact.sh --ios &&
scripts/test-app.sh --ios --emulator;
deploy:
- name: "Android Build & Test"
language: android
sudo : required
notifications:
slack:
secure: lXE+2AgsxZU5G5dI91LkMAIgo8MAWfdM7DB5UOtn5LpuNln+2FmJo1gOI7tkdmLOqpXTGYnpI2VyQN3H4nOF21YhuouzD1Sh8n2wtQg1iTm353kuQpqiVhSBX8ZJ7Be1e1G8OsnxoYOxbs4Zo9qI40EruwkvqLCBHWM5MRGyd4M7EFWwb9Z29VZN0y1Nt5g/c3bT76kdKmF+JCLur2OeEKxAity7sIKgZekSqeIMwEVLSxXnda6Dbjc/cg0MJ0iDArkD7iu6fz/Fcrrxgm/pUxjcgvqze7Gy5i31mjEfspnrglWV1cshMd48BTDKCJ2AMmxH8O3GPSWE2txjIvGRWUve7iViNylvmQCVz3Eyf99+4EuuVGa+5PSodQ/CqODx/65EwtcN3PE1tNz2puKOK8nrOJcFkcbG8KTHKUlQtHCkjitbykUnj/hvhLK5/oWlQYVOLWWrHwdGUh8FI8aFPVGjRjWbHbhdayjEIqxwr1ns+6mYrP1EFNXbaeZxnLNC59XpJl1ifuezqYAk7YEiU5j4rtC7YKgyQ3ueb7anOHTJoTMyDn8mpZXgwuyhoBaeEYytQVgRyMtL6Y5cP98Jn2kv0+vdne3rkk9/JEBTo32HOjvoij6rsqEvXC0LhUDJSNadOVdHht0jjoN6zBH37HIE5/3zysLlPcAcHAS83ow=
android:
components:
- platform-tools
- build-tools-28.0.3
- android-27
- extra-android-support
- extra-android-m2repository
- extra-google-m2repository
before_install:
- export LANG=en_US.UTF-8 &&
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - &&
sudo apt-get install -y nodejs
install:
- npm install
script:
- npm run testjs &&
npm run updatecert &&
scripts/build-test-app.sh --android --emulator &&
scripts/upload-artifact.sh --android &&
scripts/test-app.sh --android --emulator;

View File

@@ -1,5 +1,26 @@
# Changelog
## 2.0.6
- Fixed #187: setSSLCertMode with "default" throws an error on Android
- Fixed #115: HTTP connections are not kept alive on iOS (thanks MorpheusDe97)
## 2.0.5
- Fixed #185: need more detailed SSL error message
## 2.0.4
- Fixed #179: sending empty string with utf8 serializer throws an exception
## 2.0.3
- Fixed #172: plugin does not respect user installed CA certs on Android
#### Important information
We've changed a default behavior on Android. User installed CA certs are respected now.
If you don't want this for your needs, you can switch back to old behavior by setting SSL cert mode to `legacy`.
## 2.0.2
- Fixed #142: Plugin affected by REDoS Issue of tough-cookie

View File

@@ -132,12 +132,13 @@ These functions all take success and error callbacks as their last 2 arguments.
Set SSL Cert handling mode, being one of the following values:
* `default`: default SSL cert handling using system's CA certs
* `legacy`: use legacy default behavior (< 2.0.3), excluding user installed CA certs (only for Android)
* `nocheck`: disable SSL cert checking, trusting all certs (meant to be used only for testing purposes)
* `pinned`: trust only provided certs
To use SSL pinning you must include at least one `.cer` SSL certificate in your app project. You can pin to your server certificate or to one of the issuing CA certificates. Include your certificate in the `www/certificates` folder. All `.cer` files found there will be loaded automatically.
:warning: Your certificate must be DER encoded! If you only have a PEM enoceded certificate see this [stackoverflow answer](http://stackoverflow.com/a/16583429/3182729). You want to convert it to a DER encoded certificate with a .cer extension.
:warning: Your certificate must be DER encoded! If you only have a PEM encoded certificate read this [stackoverflow answer](http://stackoverflow.com/a/16583429/3182729). You want to convert it to a DER encoded certificate with a .cer extension.
```js
// enable SSL pinning

6345
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-advanced-http",
"version": "2.0.2",
"version": "2.0.6",
"description": "Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning",
"scripts": {
"updatecert": "node ./scripts/update-test-cert.js",
@@ -59,7 +59,7 @@
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"colors": "1.1.2",
"cordova": "7.1.0",
"cordova": "8.1.2",
"mocha": "4.0.0",
"mock-require": "2.0.2",
"mz": "2.7.0",

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-advanced-http" version="2.0.2">
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-advanced-http" version="2.0.6">
<name>Advanced HTTP plugin</name>
<description>
Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ..; pwd )"
WORKINGCOPY=$ROOT/temp/workingcopy
CDV=$ROOT/node_modules/.bin/cordova
@@ -37,9 +37,9 @@ done
rm -rf $ROOT/temp
mkdir $ROOT/temp
cp -r $ROOT/test/app-template/ $ROOT/temp/
cp -r $ROOT/test/app-template/. $ROOT/temp/
cp $ROOT/test/app-test-definitions.js $ROOT/temp/www/
rsync -ax --exclude node_modules --exclude scripts --exclude temp --exclude test $ROOT $WORKINGCOPY
rsync -ax --exclude node_modules --exclude scripts --exclude temp --exclude test $ROOT/. $WORKINGCOPY
cd $ROOT/temp
$CDV prepare
$CDV plugins add $WORKINGCOPY

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ..; pwd )"
pushd $ROOT
VERSION=$(node -e "console.log(require('./package.json').version)")

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ..; pwd )"
if [ $CI == "true" ] && ([ -z $SAUCE_USERNAME ] || [ -z $SAUCE_ACCESS_KEY ]); then
echo "Skipping CI tests, because Saucelabs credentials are not set.";

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ..; pwd )"
cd $ROOT
npm i

View File

@@ -2,7 +2,7 @@
set -e
PLATFORM=$([[ "${@#--android}" = "$@" ]] && echo "ios" || echo "android")
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ..; pwd )"
TEMP=$ROOT/temp
if [ -z $SAUCE_USERNAME ] || [ -z $SAUCE_ACCESS_KEY ]; then

View File

@@ -523,6 +523,13 @@ public class HttpRequest {
}
}
/**
* Clear certs which were added to test against when using ssl pinning.
*/
public static void clearCerts() {
PINNED_CERTS = null;
}
/**
* Callback interface for reporting upload progress for a request.
*/

View File

@@ -270,11 +270,11 @@ abstract class CordovaHttp {
protected void handleHttpRequestException(HttpRequestException e) {
if (e.getCause() instanceof UnknownHostException) {
this.respondWithError(0, "The host could not be resolved");
this.respondWithError(0, "The host could not be resolved: " + e.getMessage());
} else if (e.getCause() instanceof SocketTimeoutException) {
this.respondWithError(1, "The request timed out");
this.respondWithError(1, "The request timed out: " + e.getMessage());
} else if (e.getCause() instanceof SSLHandshakeException) {
this.respondWithError("SSL handshake failed");
this.respondWithError(-2, "SSL handshake failed: " + e.getMessage());
} else {
this.respondWithError("There was an error with the request: " + e.getMessage());
}

View File

@@ -8,8 +8,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStore.TrustedCertificateEntry;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
@@ -30,6 +34,14 @@ public class CordovaHttpPlugin extends CordovaPlugin {
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
try {
HttpRequest.clearCerts();
this.pinSSLCertsFromCAStore();
} catch (Exception e) {
e.printStackTrace();
System.err.println("There was an error loading system's CA certificates");
}
}
@Override
@@ -89,7 +101,9 @@ public class CordovaHttpPlugin extends CordovaPlugin {
} else if (action.equals("setSSLCertMode")) {
String mode = args.getString(0);
if (mode.equals("default")) {
HttpRequest.clearCerts();
if (mode.equals("legacy")) {
HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_DEFAULT);
callbackContext.success();
} else if (mode.equals("nocheck")) {
@@ -97,13 +111,21 @@ public class CordovaHttpPlugin extends CordovaPlugin {
callbackContext.success();
} else if (mode.equals("pinned")) {
try {
this.loadSSLCerts();
this.loadSSLCertsFromBundle();
HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_PINNED);
callbackContext.success();
} catch(Exception e) {
} catch (Exception e) {
e.printStackTrace();
callbackContext.error("There was an error setting up ssl pinning");
}
} else if (mode.equals("default")) {
try {
this.pinSSLCertsFromCAStore();
callbackContext.success();
} catch (Exception e) {
e.printStackTrace();
callbackContext.error("There was an error loading system's CA certificates");
}
}
} else if (action.equals("uploadFile")) {
String urlString = args.getString(0);
@@ -134,7 +156,25 @@ public class CordovaHttpPlugin extends CordovaPlugin {
return true;
}
private void loadSSLCerts() throws GeneralSecurityException, IOException {
private void pinSSLCertsFromCAStore() throws GeneralSecurityException, IOException {
this.loadSSLCertsFromKeyStore("AndroidCAStore");
HttpRequest.setSSLCertMode(HttpRequest.CERT_MODE_PINNED);
}
private void loadSSLCertsFromKeyStore(String storeType) throws GeneralSecurityException, IOException {
KeyStore ks = KeyStore.getInstance(storeType);
ks.load(null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
TrustedCertificateEntry certEntry = (TrustedCertificateEntry) ks.getEntry(alias, null);
Certificate cert = certEntry.getTrustedCertificate();
HttpRequest.addCert(cert);
}
}
private void loadSSLCertsFromBundle() throws GeneralSecurityException, IOException {
AssetManager assetManager = cordova.getActivity().getAssets();
String[] files = assetManager.list("www/certificates");
ArrayList<String> cerFiles = new ArrayList<String>();

View File

@@ -392,11 +392,11 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
- On iOS 7, `__NSCFLocalSessionTask` and `__NSCFURLSessionTask` are the only two classes that have their own implementations of `resume` and `suspend`, and `__NSCFLocalSessionTask` DOES NOT CALL SUPER. This means both classes need to be swizzled.
- On iOS 8, `NSURLSessionTask` is the only class that implements `resume` and `suspend`. This means this is the only class that needs to be swizzled.
- Because `NSURLSessionTask` is not involved in the class hierarchy for every version of iOS, its easier to add the swizzled methods to a dummy class and manage them there.
Some Assumptions:
- No implementations of `resume` or `suspend` call super. If this were to change in a future version of iOS, we'd need to handle it.
- No background task classes override `resume` or `suspend`
The current solution:
1) Grab an instance of `__NSCFLocalDataTask` by asking an instance of `NSURLSession` for a data task.
2) Grab a pointer to the original implementation of `af_resume`
@@ -415,7 +415,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
#pragma clang diagnostic pop
IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume)));
Class currentClass = [localDataTask class];
while (class_getInstanceMethod(currentClass, @selector(resume))) {
Class superClass = [currentClass superclass];
IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume)));
@@ -426,7 +426,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
}
currentClass = [currentClass superclass];
}
[localDataTask cancel];
[session finishTasksAndInvalidate];
}
@@ -454,7 +454,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
NSURLSessionTaskState state = [self state];
[self af_resume];
if (state != NSURLSessionTaskStateRunning) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self];
}
@@ -464,7 +464,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
NSURLSessionTaskState state = [self state];
[self af_suspend];
if (state != NSURLSessionTaskStateSuspended) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self];
}
@@ -978,7 +978,7 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
disposition = NSURLSessionAuthChallengeRejectProtectionSpace;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
@@ -1025,7 +1025,7 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
disposition = NSURLSessionAuthChallengeRejectProtectionSpace;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;

View File

@@ -20,10 +20,12 @@
@implementation CordovaHttpPlugin {
AFSecurityPolicy *securityPolicy;
bool redirect;
AFHTTPSessionManager *manager;
}
- (void)pluginInitialize {
securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
manager = [AFHTTPSessionManager manager];
redirect = true;
}
@@ -104,6 +106,9 @@
case -1009:
// no connection
return [NSNumber numberWithInt:3];
case -1202:
// untrusted SSL certificate
return [NSNumber numberWithInt:-2];
default:
return [NSNumber numberWithInt:-1];
}
@@ -124,7 +129,7 @@
- (void)setSSLCertMode:(CDVInvokedUrlCommand*)command {
NSString *certMode = [command.arguments objectAtIndex:0];
if ([certMode isEqualToString: @"default"]) {
if ([certMode isEqualToString: @"default"] || [certMode isEqualToString: @"legacy"]) {
securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = NO;
securityPolicy.validatesDomainName = YES;
@@ -157,7 +162,6 @@
}
- (void)post:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -199,7 +203,6 @@
}
- (void)get:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -241,7 +244,6 @@
}
- (void)put:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -283,7 +285,6 @@
}
- (void)patch:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -325,7 +326,6 @@
}
- (void)delete:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -366,7 +366,6 @@
}
- (void)head:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
NSDictionary *parameters = [command.arguments objectAtIndex:1];
@@ -406,7 +405,6 @@
}
- (void)uploadFile:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];
@@ -463,7 +461,6 @@
- (void)downloadFile:(CDVInvokedUrlCommand*)command {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
NSString *url = [command.arguments objectAtIndex:0];

View File

@@ -18,6 +18,7 @@ const local = {
platformVersion: '5.1',
deviceName: 'Android Emulator',
autoWebview: true,
fullReset: true,
app: undefined // will be set later
}
};

View File

@@ -37,46 +37,51 @@ const helpers = {
}
};
const messageFactory = {
sslTrustAnchor: function() { return 'SSL handshake failed: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.' },
invalidCertificate: function(domain) { return 'The certificate for this server is invalid. You might be connecting to a server that is pretending to be “' + domain + '” which could put your confidential information at risk.' }
}
const tests = [
{
description: 'should reject self signed cert (GET)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
expected: 'rejected: {"status":-2, ...',
func: function(resolve, reject) { cordova.plugin.http.get('https://self-signed.badssl.com/', {}, {}, resolve, reject); },
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('self-signed.badssl.com') });
}
},{
description: 'should reject self signed cert (PUT)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
expected: 'rejected: {"status":-2, ...',
func: function(resolve, reject) { cordova.plugin.http.put('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('self-signed.badssl.com') });
}
},{
description: 'should reject self signed cert (POST)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
expected: 'rejected: {"status":-2, ...',
func: function(resolve, reject) { cordova.plugin.http.post('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('self-signed.badssl.com') });
}
},{
description: 'should reject self signed cert (PATCH)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
expected: 'rejected: {"status":-2, ...',
func: function(resolve, reject) { cordova.plugin.http.patch('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('self-signed.badssl.com') });
}
},{
description: 'should reject self signed cert (DELETE)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
expected: 'rejected: {"status":-2, ...',
func: function(resolve, reject) { cordova.plugin.http.delete('https://self-signed.badssl.com/', {}, {}, resolve, reject); },
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('self-signed.badssl.com') });
}
},{
description: 'should accept bad cert (GET)',
@@ -284,7 +289,7 @@ const tests = [
JSON
.parse(result.data.data)
.url
.should.be.equal('http://httpbin.org/get?myArray[]=val1&myArray[]=val2&myArray[]=val3&myString=testString');
.should.include('httpbin.org/get?myArray[]=val1&myArray[]=val2&myArray[]=val3&myString=testString');
}
},{
description: 'should throw on non-string values in local header object #54',
@@ -439,14 +444,14 @@ const tests = [
}
},{
description: 'should reject when pinned cert does not match received server cert (GET)',
expected: 'rejected: {"status": -1 ...',
expected: 'rejected: {"status": -2 ...',
before: helpers.setPinnedCertMode,
func: function(resolve, reject) {
cordova.plugin.http.get('https://sha512.badssl.com/', {}, {}, resolve, reject);
},
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
result.data.should.be.eql({ status: -2, error: targetInfo.isAndroid ? messageFactory.sslTrustAnchor() : messageFactory.invalidCertificate('sha512.badssl.com') });
}
},{
description: 'should send deeply structured JSON object correctly (POST) #65',
@@ -484,6 +489,25 @@ const tests = [
result.data.status.should.be.equal(200);
JSON.parse(result.data.data).gzipped.should.be.equal(true);
}
},{
description: 'should send empty string correctly',
expected: 'resolved: {"status": 200, "data": "{\\"json\\":\\"\\" ...',
before: helpers.setUtf8StringSerializer,
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', '', {}, resolve, reject); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
JSON.parse(result.data.data).data.should.be.equal('');
}
},{
description: 'shouldn\'t escape forward slashes #184',
expected: 'resolved: {"status": 200, "data": "{\\"json\\":\\"/\\" ...',
before: helpers.setJsonSerializer,
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', { testString: '/' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
console.log(result.data.data);
JSON.parse(result.data.data).json.testString.should.be.equal('/');
}
}
];

View File

@@ -3,7 +3,7 @@ var cookieHandler = require(pluginId + '.cookie-handler');
var messages = require(pluginId + '.messages');
var validSerializers = [ 'urlencoded', 'json', 'utf8' ];
var validCertModes = [ 'default', 'nocheck', 'pinned' ];
var validCertModes = [ 'default', 'nocheck', 'pinned', 'legacy' ];
var validHttpMethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download' ];
module.exports = {
@@ -213,8 +213,6 @@ function getAllowedDataTypes(dataSerializer) {
}
function getProcessedData(data, dataSerializer) {
data = data || {};
var currentDataType = getTypeOf(data);
var allowedDataTypes = getAllowedDataTypes(dataSerializer);
@@ -248,7 +246,7 @@ function handleMissingOptions(options, globals) {
timeout: checkTimeoutValue(options.timeout || globals.timeout),
headers: checkHeadersObject(options.headers || {}),
params: checkParamsObject(options.params || {}),
data: options.data || null,
data: getTypeOf(options.data) === 'Undefined' ? null : options.data,
filePath: options.filePath || '',
name: options.name || ''
};