summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2014-12-20 12:06:03 +0100
committerParménides GV <parmegv@sdf.org>2014-12-20 12:06:03 +0100
commit5f6cb652dbd2ef0879673cf7338520dc2be236b9 (patch)
treebc47c8ccbcd48bfc5aee6b404c8ef3f1d9a359cb /app/src
parent576b0c26baf9b5b1418650a572604325ca7fb3af (diff)
parentf347c871d0433ef3efb85beb5e386b58d700faad (diff)
Merge branch 'develop'
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java (renamed from app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java)4
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java32
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java52
-rw-r--r--app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java462
-rw-r--r--app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java73
-rw-r--r--app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java176
-rw-r--r--app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java37
-rw-r--r--app/src/main/AndroidManifest.xml24
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java38
-rw-r--r--app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java8
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java47
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java1
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java7
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java151
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/AboutActivity.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java400
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EIP.java524
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java362
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java424
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java227
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java104
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java234
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderManager.java179
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java57
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java25
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SessionDialog.java (renamed from app/src/main/java/se/leap/bitmaskclient/LogInDialog.java)90
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java39
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java142
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Constants.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java251
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java138
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java156
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java46
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java (renamed from app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java)6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java (renamed from app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java)31
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java60
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java (renamed from app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java)17
-rw-r--r--app/src/main/res/drawable-hdpi/ic_close_white_24dp.pngbin0 -> 324 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_delete_white_24dp.pngbin0 -> 246 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_edit_grey600_24dp.pngbin0 -> 341 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_edit_white_24dp.pngbin0 -> 339 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.pngbin0 -> 206 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_share_white_24dp.pngbin0 -> 506 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_close_white_24dp.pngbin0 -> 279 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_delete_white_24dp.pngbin0 -> 197 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_edit_grey600_24dp.pngbin0 -> 276 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_edit_white_24dp.pngbin0 -> 272 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.pngbin0 -> 181 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_share_white_24dp.pngbin0 -> 361 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_close_white_24dp.pngbin0 -> 402 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.pngbin0 -> 270 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_edit_grey600_24dp.pngbin0 -> 379 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_edit_white_24dp.pngbin0 -> 378 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.pngbin0 -> 200 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_share_white_24dp.pngbin0 -> 625 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.pngbin0 -> 492 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.pngbin0 -> 338 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_edit_grey600_24dp.pngbin0 -> 493 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.pngbin0 -> 490 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.pngbin0 -> 223 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.pngbin0 -> 857 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.pngbin0 -> 662 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.pngbin0 -> 397 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_edit_grey600_24dp.pngbin0 -> 639 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_edit_white_24dp.pngbin0 -> 632 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.pngbin0 -> 254 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.pngbin0 -> 1115 bytes
-rw-r--r--app/src/main/res/layout-xlarge/dashboard.xml (renamed from app/src/main/res/layout-xlarge/client_dashboard.xml)0
-rw-r--r--app/src/main/res/layout-xlarge/eip_service_fragment.xml35
-rw-r--r--app/src/main/res/layout-xlarge/provider_list_fragment.xml16
-rw-r--r--app/src/main/res/layout-xlarge/session_dialog.xml (renamed from app/src/main/res/layout-xlarge/log_in_dialog.xml)0
-rw-r--r--app/src/main/res/layout/about.xml11
-rw-r--r--app/src/main/res/layout/configuration_wizard_activity.xml7
-rw-r--r--app/src/main/res/layout/dashboard.xml (renamed from app/src/main/res/layout/client_dashboard.xml)1
-rw-r--r--app/src/main/res/layout/eip_service_fragment.xml40
-rw-r--r--app/src/main/res/layout/provider_list_fragment.xml15
-rw-r--r--app/src/main/res/layout/provider_list_item.xml8
-rw-r--r--app/src/main/res/layout/session_dialog.xml (renamed from app/src/main/res/layout/log_in_dialog.xml)3
-rw-r--r--app/src/main/res/menu/logmenu.xml10
-rw-r--r--app/src/main/res/values-v21/refs.xml13
-rw-r--r--app/src/main/res/values-v21/styles.xml15
-rw-r--r--app/src/main/res/values/colours.xml13
-rw-r--r--app/src/main/res/values/refs.xml15
-rw-r--r--app/src/main/res/values/strings.xml2
-rw-r--r--app/src/main/res/values/styles.xml6
-rw-r--r--app/src/main/res/values/untranslatable.xml700
-rw-r--r--app/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java275
-rw-r--r--app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java449
-rw-r--r--app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java117
-rw-r--r--app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java186
-rw-r--r--app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java37
96 files changed, 3463 insertions, 3214 deletions
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java
index 1af17fe6..94cb67a3 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java
@@ -15,11 +15,11 @@ import se.leap.bitmaskclient.Dashboard;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.test.ConnectionManager;
-public class testDashboard extends ActivityInstrumentationTestCase2<Dashboard> {
+public class testDashboardIntegration extends ActivityInstrumentationTestCase2<Dashboard> {
private Solo solo;
- public testDashboard() {
+ public testDashboardIntegration() {
super(Dashboard.class);
}
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java
new file mode 100644
index 00000000..4e1819d0
--- /dev/null
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java
@@ -0,0 +1,32 @@
+package se.leap.bitmaskclient.test;
+
+import android.content.Context;
+import android.content.Intent;
+import android.test.ActivityUnitTestCase;
+import android.test.ServiceTestCase;
+
+import se.leap.bitmaskclient.Dashboard;
+import se.leap.bitmaskclient.eip.EIP;
+
+public class testEIP extends ServiceTestCase<EIP> {
+
+ private Context context;
+ private Intent intent;
+ private EIP activity;
+
+ public testEIP(Class<EIP> activityClass) {
+ super(activityClass);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
+}
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java
index 2821373a..d7f4bfb3 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java
@@ -33,7 +33,6 @@ public class testLeapSRPSession extends TestCase {
public void testExponential() {
byte[] expected_A;
byte[] a_byte;
- SRPParameters params;
LeapSRPSession client;
/* Test 1: abytes = 4 */
@@ -43,8 +42,7 @@ public class testLeapSRPSession extends TestCase {
salt = "64c3289d04a6ecad",
a = "3565fdc2";
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
byte[] A = client.exponential();
@@ -55,8 +53,7 @@ public class testLeapSRPSession extends TestCase {
expected_A = new BigInteger("11acfacc08178d48f95c0e69adb11f6d144dd0980ee6e44b391347592e3bd5e9cb841d243b3d9ac2adb25b367a2558e8829b22dcef96c0934378412383ccf95141c3cb5f17ada20f53a0225f56a07f2b0c0469ed6bbad3646f7b71bdd4bedf5cc6fac244b26d3195d8f55877ff94a925b0c0c8f7273eca733c0355b38360442e", 16).toByteArray();
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
A = client.exponential();
@@ -73,8 +70,7 @@ public class testLeapSRPSession extends TestCase {
salt = "64c3289d04a6ecad",
a = "8c911355";
byte[] a_byte = new BigInteger(a, 16).toByteArray();
- SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- LeapSRPSession client = new LeapSRPSession(username, password, params, a_byte);
+ LeapSRPSession client = new LeapSRPSession(username, password, a_byte);
byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
assertTrue(Arrays.equals(x, expected_x));
@@ -93,8 +89,7 @@ public class testLeapSRPSession extends TestCase {
a = "38d5b211";
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
A = client.exponential();
@@ -110,8 +105,7 @@ public class testLeapSRPSession extends TestCase {
a = "36ee80ec";
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
A = client.exponential();
@@ -321,8 +315,7 @@ public class testLeapSRPSession extends TestCase {
salt = "64c3289d04a6ecad",
a = "8c911355";
byte[] a_byte = new BigInteger(a, 16).toByteArray();
- SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- LeapSRPSession client = new LeapSRPSession(username, password, params, a_byte);
+ LeapSRPSession client = new LeapSRPSession(username, password, a_byte);
byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
assertTrue(Arrays.equals(x, expected_x));
@@ -345,8 +338,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("517278a03a0320a52dcb391caf5264d76149d7d9b71ed2b65536233344c550cf", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
A = client.exponential();
@@ -365,8 +357,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("3bfb91c7d04b6da6381fe3d2648d992cdc6bc67b8ee16d1cfa733f786d492261", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray());
A = client.exponential();
@@ -390,8 +381,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("8f4552b1021a4de621d8f50f0921c4d20651e702d9d71276f8f6c15b838de018", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -418,8 +408,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("04cf3ab3b75dbc4b116ca2fec949bf3deca1e360e016d7ab2b8a49904c534a27", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -448,8 +437,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("082cf49ad5a34cc5ca571e3d063aec4bd96e7b96a6d951295180631650a84587", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -479,8 +467,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("5cc3d7f0077e978c83acdef14a725af01488c1728f0cf32cd7013d24faf5d901", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -510,8 +497,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("d78da7e0a23c9b87a2f09cdee05c510c105b4a8d471b47402c38f4cdfa49fe6d", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -541,8 +527,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("a382025452bad8a6ccd0f703253fda90e7ea7bd0c2d466a389455080a4bd015d", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -572,8 +557,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("9e99f9adfbfaa7add3626ed6e6aea94c9fa60dab6b8d56ad0cc950548f577d32", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -603,8 +587,7 @@ public class testLeapSRPSession extends TestCase {
expected_M2 = trim(new BigInteger("ffccafa0febc1771a428082b30b7ce409856de4581c7d7d986f5b80015aba0d3", 16).toByteArray());
a_byte = new BigInteger(a, 16).toByteArray();
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256");
- client = new LeapSRPSession(username, password, params, a_byte);
+ client = new LeapSRPSession(username, password, a_byte);
x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray()));
assertTrue(Arrays.equals(x, expected_x));
@@ -626,8 +609,7 @@ public class testLeapSRPSession extends TestCase {
String password = "holahola2";
byte[] salt = new BigInteger("67e8348d1500d26c", 16).toByteArray();
- SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), salt, "SHA-256");
- LeapSRPSession client = new LeapSRPSession(username, password, params);
+ LeapSRPSession client = new LeapSRPSession(username, password);
String expected_v = "12bea84e588ffa2f8fc5ae47cb5e751a8f2d9e8125268ad9ab483eff83f98cb08484350eb478bee582b8b72363ff8e7b12e9f332e86f7a0bd77689927c609d275471c6ad2cff8b1e7bbfc3664169c3b7bccb0b974154c1f1656b64274568015ca1b849c9d9890ae4437ed686341b432340809b81c30727ed2aadea8bdec6d101";
diff --git a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java
index 78fcda56..ac2e00b8 100644
--- a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java
+++ b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,48 +16,30 @@
*/
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Display;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View.MeasureSpec;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Iterator;
+import android.app.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.widget.*;
+
+import com.pedrogomez.renderers.*;
+
+import java.net.*;
+import java.util.*;
+
+import butterknife.*;
+import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
+import javax.inject.Inject;
+
import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface;
import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface;
import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import se.leap.bitmaskclient.FragmentManagerEnhanced;
-
-import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.eip.Constants;
/**
* Activity that builds and shows the list of known available providers.
@@ -68,12 +50,17 @@ import se.leap.bitmaskclient.R;
*
*/
public class ConfigurationWizard extends Activity
-implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
+implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
+
+ @InjectView(R.id.progressbar_configuration_wizard) ProgressBar mProgressBar;
+ @InjectView(R.id.progressbar_description) TextView progressbar_description;
- private ProgressBar mProgressBar;
- private TextView progressbar_description;
- private ProviderListFragment provider_list_fragment;
+ @InjectView(R.id.provider_list) ListView provider_list_view;
+ @Inject ProviderListAdapter adapter;
+
+ private ProviderManager provider_manager;
private Intent mConfigState = new Intent();
+ private Provider selected_provider;
final public static String TAG = ConfigurationWizard.class.getSimpleName();
final public static String TYPE_OF_CERTIFICATE = "type_of_certificate";
@@ -82,7 +69,9 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
final protected static String PROVIDER_SET = "PROVIDER SET";
final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
- final protected static String ASSETS_URL_FOLDER = "urls";
+
+ final private static String PROGRESSBAR_TEXT = TAG + "PROGRESSBAR_TEXT";
+ final private static String PROGRESSBAR_NUMBER = TAG + "PROGRESSBAR_NUMBER";
public ProviderAPIResultReceiver providerAPI_result_receiver;
private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update;
@@ -90,67 +79,94 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
private static SharedPreferences preferences;
FragmentManagerEnhanced fragment_manager;
private static boolean setting_up_provider = false;
+ private String progressbar_text = "";
+ private String provider_name = "";
+ private int progress = -1;
+
+ private void initProviderList() {
+ List<Renderer<Provider>> prototypes = new ArrayList<Renderer<Provider>>();
+ prototypes.add(new ProviderRenderer(this));
+ ProviderRendererBuilder providerRendererBuilder = new ProviderRendererBuilder(prototypes);
+ adapter = new ProviderListAdapter(getLayoutInflater(), providerRendererBuilder, provider_manager);
+ provider_list_view.setAdapter(adapter);
+ }
@Override
+ protected void onSaveInstanceState(@NotNull Bundle outState) {
+ if(mProgressBar != null)
+ outState.putInt(PROGRESSBAR_NUMBER, mProgressBar.getProgress());
+ if(progressbar_description != null)
+ outState.putString(PROGRESSBAR_TEXT, progressbar_description.getText().toString());
+ if(selected_provider != null)
+ outState.putParcelable(Provider.KEY, selected_provider);
+ outState.putParcelable(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
- fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
+ preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
+ fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
+ provider_manager = ProviderManager.getInstance(getAssets(), getExternalFilesDir(null));
- setUpInitialUI();
+ setUpInitialUI();
- loadPreseededProviders();
+ setUpProviderAPIResultReceiver();
- setUpProviderAPIResultReceiver();
-
- // Only create our fragments if we're not restoring a saved instance
- if ( savedInstanceState == null ){
- // TODO Some welcome screen?
- // We will need better flow control when we have more Fragments (e.g. user auth)
- setUpProviderList();
+ setUpProviderList();
+
+ if(savedInstanceState != null) {
+ restoreState(savedInstanceState);
}
+ }
+
+ private void restoreState(Bundle savedInstanceState) {
+ progressbar_text = savedInstanceState.getString(PROGRESSBAR_TEXT, "");
+ provider_name = savedInstanceState.getString(Provider.NAME, "");
+ selected_provider = savedInstanceState.getParcelable(Provider.KEY);
+ progress = savedInstanceState.getInt(PROGRESSBAR_NUMBER, -1);
+ providerAPI_result_receiver = savedInstanceState.getParcelable(ProviderAPI.RECEIVER_KEY);
+ providerAPI_result_receiver.setReceiver(this);
+ }
- // TODO: If exposing deep links into your app, handle intents here.
+ @Override
+ protected void onPostResume() {
+ super.onPostResume();
+ if(!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) {
+ progressbar_description.setText(progressbar_text);
+ //onItemSelectedUi(getProvider(provider_name));
+ mProgressBar.setProgress(progress);
+
+ progressbar_text = "";
+ provider_name = "";
+ progress = -1;
+ }
}
private void setUpInitialUI() {
- setContentView(R.layout.configuration_wizard_activity);
+ setContentView(R.layout.configuration_wizard_activity);
+ ButterKnife.inject(this);
- hideProgressBar();
+ hideProgressBar();
}
private void hideProgressBar() {
- mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard);
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
-
- progressbar_description = (TextView) findViewById(R.id.progressbar_description);
progressbar_description.setVisibility(TextView.INVISIBLE);
}
private void setUpProviderList() {
- provider_list_fragment = ProviderListFragment.newInstance();
-
- Bundle arguments = new Bundle();
- int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1);
- if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER)
- arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true);
-
- provider_list_fragment.setArguments(arguments);
-
- putProviderListFragment(provider_list_fragment);
+ initProviderList();
}
- private void putProviderListFragment(ProviderListFragment fragment) {
-
- fragment_manager.replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG);
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if(providerAPI_broadcast_receiver_update != null)
+ unregisterReceiver(providerAPI_broadcast_receiver_update);
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(providerAPI_broadcast_receiver_update);
- }
-
private void setUpProviderAPIResultReceiver() {
providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
providerAPI_result_receiver.setReceiver(this);
@@ -166,7 +182,15 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
if(resultCode == ProviderAPI.PROVIDER_OK) {
mConfigState.setAction(PROVIDER_SET);
- if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){
+ try {
+ String provider_json_string = preferences.getString(Provider.KEY, "");
+ if(!provider_json_string.isEmpty())
+ selected_provider.define(new JSONObject(provider_json_string));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){
mConfigState.putExtra(SERVICES_RETRIEVED, true);
downloadAnonCert();
@@ -175,26 +199,26 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
hideProgressBar();
setResult(RESULT_OK);
-
+
showProviderDetails();
}
} else if(resultCode == ProviderAPI.PROVIDER_NOK) {
hideProgressBar();
- preferences.edit().remove(Provider.KEY).commit();
+ preferences.edit().remove(Provider.KEY).apply();
setting_up_provider = false;
setResult(RESULT_CANCELED, mConfigState);
String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
- showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
+ showDownloadFailedDialog(reason_to_fail);
}
else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
mProgressBar.incrementProgressBy(1);
hideProgressBar();
-
- setResult(RESULT_OK);
-
+
showProviderDetails();
+
+ setResult(RESULT_OK);
} else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
hideProgressBar();
@@ -204,32 +228,36 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
// I need this for CW to wait for the About activity to end before going back to Dashboard.
}
}
+
+ @OnItemClick(R.id.provider_list)
+ void onItemSelected(int position) {
+ //TODO Code 2 pane view
+ selected_provider = adapter.getItem(position);
+ onItemSelectedLogic(selected_provider);
+ onItemSelectedUi(selected_provider);
+ }
- /**
- * Callback method from {@link ProviderListFragment.Callbacks}
- * indicating that the item with the given ID was selected.
- */
- @Override
- public void onItemSelected(String id) {
- //TODO Code 2 pane view
- ProviderItem selected_provider = getProvider(id);
- int provider_index = getProviderIndex(id);
-
- startProgressBar(provider_index+1);
- provider_list_fragment.hideAllBut(provider_index);
-
- boolean danger_on = true;
- if(preferences.contains(ProviderItem.DANGER_ON))
- danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false);
- setUpProvider(selected_provider.providerMainUrl(), danger_on);
+ private void onItemSelectedLogic(Provider selected_provider) {
+ boolean danger_on = true;
+ if(preferences.contains(ProviderItem.DANGER_ON))
+ danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false);
+ setUpProvider(selected_provider.mainUrl(), danger_on);
}
+
+ private void onItemSelectedUi(Provider provider) {
+ startProgressBar();
+ adapter.hideAllBut(adapter.indexOf(provider));
+ }
+
+
@Override
public void onBackPressed() {
if(setting_up_provider) {
- stopSettingUpProvider();
+ stopSettingUpProvider();
} else {
- usualBackButton();
+ askDashboardToQuitApp();
+ super.onBackPressed();
}
}
@@ -238,74 +266,35 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
mProgressBar.setVisibility(ProgressBar.GONE);
mProgressBar.setProgress(0);
progressbar_description.setVisibility(TextView.GONE);
- preferences.edit().remove(Provider.KEY).commit();
- setting_up_provider = false;
- showAllProviders();
+
+ cancelSettingUpProvider();
}
-
- private void usualBackButton() {
- try {
- boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false;
- boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false;
- if(!is_provider_set_up || !is_provider_set_up_truly) {
- askDashboardToQuitApp();
- } else {
- setResult(RESULT_OK);
- }
- } catch (JSONException e) {
- askDashboardToQuitApp();
- super.onBackPressed();
- e.printStackTrace();
- }
- super.onBackPressed();
+
+ public void cancelSettingUpProvider() {
+ showAllProviders();
+ setting_up_provider = false;
+ preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
}
+
private void askDashboardToQuitApp() {
Intent ask_quit = new Intent();
ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT);
setResult(RESULT_CANCELED, ask_quit);
}
- private ProviderItem getProvider(String name) {
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(name)) {
- return provider;
- }
- }
- return null;
- }
-
- private void startProgressBar() {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- progressbar_description.setVisibility(TextView.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- }
-
- private void startProgressBar(int list_item_index) {
- startProgressBar();
- int measured_height = listItemHeight(list_item_index);
- mProgressBar.setTranslationY(measured_height);
- progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
- }
+ private void startProgressBar() {
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ progressbar_description.setVisibility(TextView.VISIBLE);
+ mProgressBar.setProgress(0);
+ mProgressBar.setMax(3);
- private int getProviderIndex(String id) {
- int index = 0;
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(id)) {
- break;
- } else index++;
- }
- return index;
+ int measured_height = listItemHeight();
+ mProgressBar.setTranslationY(measured_height);
+ progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
}
- private int listItemHeight(int list_item_index) {
- ListView provider_list_view = (ListView)findViewById(android.R.id.list);
- ListAdapter provider_list_adapter = provider_list_view.getAdapter();
- View listItem = provider_list_adapter.getView(0, null, provider_list_view);
+ private int listItemHeight() {
+ View listItem = adapter.getView(0, null, provider_list_view);
listItem.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
@@ -315,93 +304,13 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
int screenWidth = display.getWidth(); // deprecated
int listViewWidth = screenWidth - 10 - 10;
- int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth,
- MeasureSpec.AT_MOST);
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth,
+ View.MeasureSpec.AT_MOST);
listItem.measure(widthSpec, 0);
return listItem.getMeasuredHeight();
}
- /**
- * Loads providers data from url files contained in the assets folder
- * @return true if the files were correctly read
- */
- private boolean loadPreseededProviders() {
- boolean loaded_preseeded_providers = true;
- try {
- //TODO Put that folder in a better place (also inside the "for")
- String[] urls_filepaths = getAssets().list(ASSETS_URL_FOLDER);
- for(String url_filepath : urls_filepaths) {
- addNewProviderToList(url_filepath);
- }
- } catch (IOException e) {
- loaded_preseeded_providers = false;
- }
-
- return loaded_preseeded_providers;
- }
-
- private void addNewProviderToList(String url_filepath) {
- String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath);
- if(getId(provider_main_url).isEmpty()) {
- String provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString();
- ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url));
- }
- }
-
- private String extractProviderMainUrlFromAssetsFile(String filepath) {
- String provider_main_url = "";
- try {
- InputStream input_stream_file_contents = getAssets().open(filepath);
- byte[] urls_file_bytes = new byte[input_stream_file_contents.available()];
- input_stream_file_contents.read(urls_file_bytes);
- String urls_file_content = new String(urls_file_bytes);
- JSONObject file_contents = new JSONObject(urls_file_content);
- provider_main_url = file_contents.getString(Provider.MAIN_URL);
- } catch (JSONException e) {
- } catch (IOException e) {
- }
- return provider_main_url;
- }
-
- private String getId(String provider_main_url) {
- try {
- URL provider_url = new URL(provider_main_url);
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- URL aux_provider_url = new URL(provider.providerMainUrl());
- if(isSameURL(provider_url, aux_provider_url)) {
- return provider.name();
- }
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- return "";
- }
-
- /**
- * Checks, whether 2 urls are pointing to the same location.
- *
- * @param url a url
- * @param baseUrl an other url, that should be compared.
- * @return true, if the urls point to the same host and port and use the
- * same protocol, false otherwise.
- */
- private boolean isSameURL(final URL url, final URL baseUrl) {
- if (!url.getProtocol().equals(baseUrl.getProtocol())) {
- return false;
- }
- if (!url.getHost().equals(baseUrl.getHost())) {
- return false;
- }
- if (url.getPort() != baseUrl.getPort()) {
- return false;
- }
- return true;
- }
-
/**
* Asks ProviderAPI to download an anonymous (anon) VPN certificate.
*/
@@ -424,8 +333,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
*/
public void addAndSelectNewProvider() {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG);
- DialogFragment newFragment = NewProviderDialog.newInstance();
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
+ new NewProviderDialog().show(fragment_transaction, NewProviderDialog.TAG);
}
/**
@@ -434,7 +342,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
public void addAndSelectNewProvider(String main_url, boolean danger_on) {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG);
- DialogFragment newFragment = NewProviderDialog.newInstance();
+ DialogFragment newFragment = new NewProviderDialog();
Bundle data = new Bundle();
data.putString(Provider.MAIN_URL, main_url);
data.putBoolean(ProviderItem.DANGER_ON, danger_on);
@@ -446,16 +354,15 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
* Once selected a provider, this fragment offers the user to log in,
* use it anonymously (if possible)
* or cancel his/her election pressing the back button.
- * @param view
- * @param reason_to_fail
+ * @param reason_to_fail
*/
- public void showDownloadFailedDialog(View view, String reason_to_fail) {
+ public void showDownloadFailedDialog(String reason_to_fail) {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG);
DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail);
newFragment.show(fragment_transaction, DownloadFailedDialog.TAG);
}
-
+
/**
* Once selected a provider, this fragment offers the user to log in,
* use it anonymously (if possible)
@@ -470,33 +377,33 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
}
- public void showAndSelectProvider(String provider_main_url, boolean danger_on) {
- if(getId(provider_main_url).isEmpty())
- showProvider(provider_main_url, danger_on);
- autoSelectProvider(provider_main_url, danger_on);
- }
-
- private void showProvider(final String provider_main_url, final boolean danger_on) {
- String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
- ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url);
- provider_list_fragment.addItem(added_provider);
- }
-
- private void autoSelectProvider(String provider_main_url, boolean danger_on) {
- preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).commit();
- onItemSelected(getId(provider_main_url));
- }
+ public void showAndSelectProvider(String provider_main_url, boolean danger_on) {
+ try {
+ selected_provider = new Provider(new URL((provider_main_url)));
+ adapter.add(selected_provider);
+ adapter.saveProviders();
+ autoSelectProvider(selected_provider, danger_on);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void autoSelectProvider(Provider provider, boolean danger_on) {
+ preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).apply();
+ selected_provider = provider;
+ onItemSelectedLogic(selected_provider);
+ onItemSelectedUi(selected_provider);
+ }
/**
* Asks ProviderAPI to download a new provider.json file
- * @param provider_name
- * @param provider_main_url
+n * @param provider_main_url
* @param danger_on tells if HTTPS client should bypass certificate errors
*/
- public void setUpProvider(String provider_main_url, boolean danger_on) {
+ public void setUpProvider(URL provider_main_url, boolean danger_on) {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider_main_url);
+ parameters.putString(Provider.MAIN_URL, provider_main_url.toString());
parameters.putBoolean(ProviderItem.DANGER_ON, danger_on);
provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
@@ -541,23 +448,14 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
public void showAllProviders() {
- provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null)
- provider_list_fragment.unhideAll();
- }
-
- public void cancelSettingUpProvider() {
- provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null && preferences.contains(ProviderItem.DANGER_ON)) {
- provider_list_fragment.removeLastItem();
- }
- preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
+ adapter.showAllProviders();
}
@Override
public void login() {
Intent ask_login = new Intent();
- ask_login.putExtra(LogInDialog.TAG, LogInDialog.TAG);
+ ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG);
+ ask_login.putExtra(Provider.KEY, selected_provider);
setResult(RESULT_OK, ask_login);
setting_up_provider = false;
finish();
@@ -565,7 +463,9 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
@Override
public void use_anonymously() {
- setResult(RESULT_OK);
+ Intent pass_provider = new Intent();
+ pass_provider.putExtra(Provider.KEY, selected_provider);
+ setResult(RESULT_OK, pass_provider);
setting_up_provider = false;
finish();
}
diff --git a/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java b/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java
index cf09c64b..8fe1c3eb 100644
--- a/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java
+++ b/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java
@@ -16,14 +16,14 @@
*/
package se.leap.bitmaskclient;
+import butterknife.ButterKnife;
+import butterknife.InjectView;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import se.leap.bitmaskclient.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
-import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -40,20 +40,17 @@ import android.widget.Toast;
public class NewProviderDialog extends DialogFragment {
final public static String TAG = "newProviderDialog";
-
+
+ @InjectView(R.id.new_provider_url)
+ EditText url_input_field;
+ @InjectView(R.id.danger_checkbox)
+ CheckBox danger_checkbox;
+
public interface NewProviderDialogInterface {
public void showAndSelectProvider(String url_provider, boolean danger_on);
}
NewProviderDialogInterface interface_with_ConfigurationWizard;
-
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance() {
- NewProviderDialog dialog_fragment = new NewProviderDialog();
- return dialog_fragment;
- }
@Override
public void onAttach(Activity activity) {
@@ -70,36 +67,19 @@ public class NewProviderDialog extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
- View new_provider_dialog_view = inflater.inflate(R.layout.new_provider_dialog, null);
- final EditText url_input_field = (EditText)new_provider_dialog_view.findViewById(R.id.new_provider_url);
- if(getArguments() != null && getArguments().containsKey(Provider.MAIN_URL)) {
- url_input_field.setText(getArguments().getString(Provider.MAIN_URL));
- }
- final CheckBox danger_checkbox = (CheckBox)new_provider_dialog_view.findViewById(R.id.danger_checkbox);
- if(getArguments() != null && getArguments().containsKey(ProviderItem.DANGER_ON)) {
- danger_checkbox.setActivated(getArguments().getBoolean(ProviderItem.DANGER_ON));
- }
+ View view = inflater.inflate(R.layout.new_provider_dialog, null);
+ ButterKnife.inject(this, view);
+ Bundle arguments = getArguments();
+ if(arguments != null) {
+ url_input_field.setText(arguments.getString(Provider.MAIN_URL, ""));
+ danger_checkbox.setActivated(arguments.getBoolean(ProviderItem.DANGER_ON, false));
+ }
- builder.setView(new_provider_dialog_view)
+ builder.setView(view)
.setMessage(R.string.introduce_new_provider)
.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- String entered_url = url_input_field.getText().toString().trim();
- if(!entered_url.startsWith("https://")) {
- if (entered_url.startsWith("http://")){
- entered_url = entered_url.substring("http://".length());
- }
- entered_url = "https://".concat(entered_url);
- }
- boolean danger_on = danger_checkbox.isChecked();
- if(validURL(entered_url)) {
- interface_with_ConfigurationWizard.showAndSelectProvider(entered_url, danger_on);
- Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();
- } else {
- url_input_field.setText("");
- danger_checkbox.setChecked(false);
- Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();;
- }
+ saveProvider();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@@ -111,6 +91,25 @@ public class NewProviderDialog extends DialogFragment {
return builder.create();
}
+ private void saveProvider() {
+ String entered_url = url_input_field.getText().toString().trim();
+ if(!entered_url.startsWith("https://")) {
+ if (entered_url.startsWith("http://")){
+ entered_url = entered_url.substring("http://".length());
+ }
+ entered_url = "https://".concat(entered_url);
+ }
+ boolean danger_on = danger_checkbox.isChecked();
+ if(validURL(entered_url)) {
+ interface_with_ConfigurationWizard.showAndSelectProvider(entered_url, danger_on);
+ Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();
+ } else {
+ url_input_field.setText("");
+ danger_checkbox.setChecked(false);
+ Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();;
+ }
+ }
+
/**
* Checks if the entered url is valid or not.
* @param entered_url
diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
index 52645631..886d70a0 100644
--- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -17,60 +17,22 @@
package se.leap.bitmaskclient;
import android.app.IntentService;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.util.Base64;
-import android.util.Log;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
+import android.content.*;
+import android.os.*;
+import android.util.*;
+import java.io.*;
import java.math.BigInteger;
-import java.net.ConnectException;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.CookiePolicy;
-import java.net.MalformedURLException;
-import java.net.SocketTimeoutException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
import java.security.interfaces.RSAPrivateKey;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.NoSuchElementException;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
+import java.util.*;
+import javax.net.ssl.*;
import org.apache.http.client.ClientProtocolException;
-import org.json.JSONException;
-import org.json.JSONObject;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import se.leap.bitmaskclient.R;
+import org.json.*;
+import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
+import se.leap.bitmaskclient.eip.*;
/**
* Implements HTTP api methods used to manage communications with the provider server.
@@ -84,6 +46,7 @@ import se.leap.bitmaskclient.R;
public class ProviderAPI extends IntentService {
final public static String
+ TAG = ProviderAPI.class.getSimpleName(),
SET_UP_PROVIDER = "setUpProvider",
DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
SRP_REGISTER = "srpRegister",
@@ -96,23 +59,22 @@ public class ProviderAPI extends IntentService {
ERRORS = "errors",
UPDATE_PROGRESSBAR = "update_progressbar",
CURRENT_PROGRESS = "current_progress",
- TAG = ProviderAPI.class.getSimpleName();
+ DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE"
;
final public static int
- CUSTOM_PROVIDER_ADDED = 0,
- SRP_AUTHENTICATION_SUCCESSFUL = 3,
- SRP_AUTHENTICATION_FAILED = 4,
- SRP_REGISTRATION_SUCCESSFUL = 5,
- SRP_REGISTRATION_FAILED = 6,
- LOGOUT_SUCCESSFUL = 7,
+ SUCCESSFUL_LOGIN = 3,
+ FAILED_LOGIN = 4,
+ SUCCESSFUL_SIGNUP = 5,
+ FAILED_SIGNUP = 6,
+ SUCCESSFUL_LOGOUT = 7,
LOGOUT_FAILED = 8,
CORRECTLY_DOWNLOADED_CERTIFICATE = 9,
INCORRECTLY_DOWNLOADED_CERTIFICATE = 10,
PROVIDER_OK = 11,
PROVIDER_NOK = 12,
- CORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 13,
- INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14
+ CORRECTLY_DOWNLOADED_EIP_SERVICE = 13,
+ INCORRECTLY_DOWNLOADED_EIP_SERVICE= 14
;
private static boolean
@@ -123,12 +85,12 @@ public class ProviderAPI extends IntentService {
private static String last_provider_main_url;
private static boolean last_danger_on = false;
- private static boolean setting_up_provider = true;
+ private static boolean go_ahead = true;
private static SharedPreferences preferences;
private static String provider_api_url;
public static void stop() {
- setting_up_provider = false;
+ go_ahead = false;
}
public ProviderAPI() {
@@ -165,15 +127,15 @@ public class ProviderAPI extends IntentService {
try {
JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "no provider"));
provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION);
+ go_ahead = true;
} catch (JSONException e) {
+ go_ahead = false;
}
}
-
- setting_up_provider = true;
if(action.equalsIgnoreCase(SET_UP_PROVIDER)) {
Bundle result = setUpProvider(parameters);
- if(setting_up_provider) {
+ if(go_ahead) {
if(result.getBoolean(RESULT_KEY)) {
receiver.send(PROVIDER_OK, result);
} else {
@@ -183,20 +145,20 @@ public class ProviderAPI extends IntentService {
} else if (action.equalsIgnoreCase(SRP_REGISTER)) {
Bundle session_id_bundle = tryToRegister(parameters);
if(session_id_bundle.getBoolean(RESULT_KEY)) {
- receiver.send(SRP_REGISTRATION_SUCCESSFUL, session_id_bundle);
+ receiver.send(SUCCESSFUL_SIGNUP, session_id_bundle);
} else {
- receiver.send(SRP_REGISTRATION_FAILED, session_id_bundle);
+ receiver.send(FAILED_SIGNUP, session_id_bundle);
}
} else if (action.equalsIgnoreCase(SRP_AUTH)) {
Bundle session_id_bundle = tryToAuthenticate(parameters);
if(session_id_bundle.getBoolean(RESULT_KEY)) {
- receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle);
+ receiver.send(SUCCESSFUL_LOGIN, session_id_bundle);
} else {
- receiver.send(SRP_AUTHENTICATION_FAILED, session_id_bundle);
+ receiver.send(FAILED_LOGIN, session_id_bundle);
}
} else if (action.equalsIgnoreCase(LOG_OUT)) {
if(logOut()) {
- receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY);
+ receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY);
} else {
receiver.send(LOGOUT_FAILED, Bundle.EMPTY);
}
@@ -206,15 +168,22 @@ public class ProviderAPI extends IntentService {
} else {
receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
}
- }
+ } else if(action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) {
+ Bundle result = getAndSetEipServiceJson();
+ if(result.getBoolean(RESULT_KEY)) {
+ receiver.send(CORRECTLY_DOWNLOADED_EIP_SERVICE, result);
+ } else {
+ receiver.send(INCORRECTLY_DOWNLOADED_EIP_SERVICE, result);
+ }
+ }
}
private Bundle tryToRegister(Bundle task) {
Bundle session_id_bundle = new Bundle();
int progress = 0;
- String username = (String) task.get(SessionDialogInterface.USERNAME);
- String password = (String) task.get(SessionDialogInterface.PASSWORD);
+ String username = (String) task.get(SessionDialog.USERNAME);
+ String password = (String) task.get(SessionDialog.PASSWORD);
if(validUserLoginData(username, password)) {
session_id_bundle = register(username, password);
@@ -222,12 +191,12 @@ public class ProviderAPI extends IntentService {
} else {
if(!wellFormedPassword(password)) {
session_id_bundle.putBoolean(RESULT_KEY, false);
- session_id_bundle.putString(SessionDialogInterface.USERNAME, username);
- session_id_bundle.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true);
+ session_id_bundle.putString(SessionDialog.USERNAME, username);
+ session_id_bundle.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true);
}
if(username.isEmpty()) {
session_id_bundle.putBoolean(RESULT_KEY, false);
- session_id_bundle.putBoolean(SessionDialogInterface.USERNAME_MISSING, true);
+ session_id_bundle.putBoolean(SessionDialog.USERNAME_MISSING, true);
}
}
@@ -246,8 +215,8 @@ public class ProviderAPI extends IntentService {
if(api_result.has(ERRORS))
result = authFailedNotification(api_result, username);
else {
- result.putString(SessionDialogInterface.USERNAME, username);
- result.putString(SessionDialogInterface.PASSWORD, password);
+ result.putString(SessionDialog.USERNAME, username);
+ result.putString(SessionDialog.PASSWORD, password);
result.putBoolean(RESULT_KEY, true);
}
@@ -263,20 +232,20 @@ public class ProviderAPI extends IntentService {
Bundle result = new Bundle();
int progress = 0;
- String username = (String) task.get(SessionDialogInterface.USERNAME);
- String password = (String) task.get(SessionDialogInterface.PASSWORD);
+ String username = (String) task.get(SessionDialog.USERNAME);
+ String password = (String) task.get(SessionDialog.PASSWORD);
if(validUserLoginData(username, password)) {
result = authenticate(username, password);
broadcast_progress(progress++);
} else {
if(!wellFormedPassword(password)) {
result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialogInterface.USERNAME, username);
- result.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true);
+ result.putString(SessionDialog.USERNAME, username);
+ result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true);
}
if(username.isEmpty()) {
result.putBoolean(RESULT_KEY, false);
- result.putBoolean(SessionDialogInterface.USERNAME_MISSING, true);
+ result.putBoolean(SessionDialog.USERNAME_MISSING, true);
}
}
@@ -306,7 +275,7 @@ public class ProviderAPI extends IntentService {
}
} else {
result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialogInterface.USERNAME, username);
+ result.putString(SessionDialog.USERNAME, username);
result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message));
}
} catch (JSONException e) {
@@ -337,7 +306,7 @@ public class ProviderAPI extends IntentService {
} catch(JSONException e) {}
if(!username.isEmpty())
- user_notification_bundle.putString(SessionDialogInterface.USERNAME, username);
+ user_notification_bundle.putString(SessionDialog.USERNAME, username);
user_notification_bundle.putBoolean(RESULT_KEY, false);
return user_notification_bundle;
@@ -407,7 +376,7 @@ public class ProviderAPI extends IntentService {
* Sends an HTTP POST request to the api server to register a new user.
* @param server_url
* @param username
- * @param salted_password
+ * @param salt
* @param password_verifier
* @return response from authentication server
*/
@@ -528,6 +497,7 @@ public class ProviderAPI extends IntentService {
last_danger_on = task.getBoolean(ProviderItem.DANGER_ON);
last_provider_main_url = task.getString(Provider.MAIN_URL);
CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false;
+ go_ahead = true;
}
if(!PROVIDER_JSON_DOWNLOADED)
@@ -558,7 +528,7 @@ public class ProviderAPI extends IntentService {
String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI);
String cert_string = downloadWithCommercialCA(ca_cert_url, danger_on);
- if(validCertificate(cert_string) && setting_up_provider) {
+ if(validCertificate(cert_string) && go_ahead) {
preferences.edit().putString(Provider.CA_CERT, cert_string).commit();
result.putBoolean(RESULT_KEY, true);
} else {
@@ -619,7 +589,7 @@ public class ProviderAPI extends IntentService {
private Bundle getAndSetProviderJson(String provider_main_url, boolean danger_on) {
Bundle result = new Bundle();
- if(setting_up_provider) {
+ if(go_ahead) {
String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json", danger_on);
try {
@@ -629,8 +599,8 @@ public class ProviderAPI extends IntentService {
//TODO setProviderName(name);
preferences.edit().putString(Provider.KEY, provider_json.toString()).commit();
- preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit();
- preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit();
+ preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit();
+ preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit();
result.putBoolean(RESULT_KEY, true);
} catch (JSONException e) {
@@ -646,7 +616,7 @@ public class ProviderAPI extends IntentService {
private Bundle getAndSetEipServiceJson() {
Bundle result = new Bundle();
String eip_service_json_string = "";
- if(setting_up_provider) {
+ if(go_ahead) {
try {
JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
@@ -654,7 +624,7 @@ public class ProviderAPI extends IntentService {
JSONObject eip_service_json = new JSONObject(eip_service_json_string);
eip_service_json.getInt(Provider.API_RETURN_SERIAL);
- preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit();
+ preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit();
result.putBoolean(RESULT_KEY, true);
} catch (JSONException e) {
@@ -731,7 +701,7 @@ public class ProviderAPI extends IntentService {
/**
* Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider.
- * @param url as a string
+ * @param url_string as a string
* @param danger_on true to download CA certificate in case it has not been downloaded.
* @return an empty string if it fails, the url content if not.
*/
@@ -855,7 +825,6 @@ public class ProviderAPI extends IntentService {
/**
* Logs out from the api url retrieved from the task.
- * @param task containing api url from which the user will log out
* @return true if there were no exceptions
*/
private boolean logOut() {
@@ -898,28 +867,18 @@ public class ProviderAPI extends IntentService {
}
return true;
}
-
- private boolean updateVpnCertificate() {
- getNewCert();
-
- Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
- updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
- startService(updateEIP);
-
- return true;
- }
/**
* Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
*
* @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
*/
- private boolean getNewCert() {
+ private boolean updateVpnCertificate() {
try {
JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
String provider_main_url = provider_json.getString(Provider.API_URL);
- URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE);
+ URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE);
boolean danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false);
@@ -956,12 +915,13 @@ public class ProviderAPI extends IntentService {
}
RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString);
keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT );
- preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit();
+ preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit();
X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString);
certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT);
- preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
- preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit();
+
+ preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
+
return true;
} catch (CertificateException e) {
// TODO Auto-generated catch block
diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java
index 3ca003a0..d6f482ca 100644
--- a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java
+++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java
@@ -1,22 +1,17 @@
-package se.leap.bitmaskclient;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
+package se.leap.bitmaskclient;
+
+import org.json.*;
+
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
+
+import android.app.*;
+import android.content.*;
+import android.os.Bundle;
+import android.view.*;
+import android.widget.TextView;
+
public class ProviderDetailFragment extends DialogFragment {
final public static String TAG = "providerDetailFragment";
@@ -66,7 +61,7 @@ public class ProviderDetailFragment extends DialogFragment {
private boolean anon_allowed(JSONObject provider_json) {
try {
JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(EIP.ALLOWED_ANON) && service_description.getBoolean(EIP.ALLOWED_ANON);
+ return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON);
} catch (JSONException e) {
return false;
}
@@ -85,7 +80,7 @@ public class ProviderDetailFragment extends DialogFragment {
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
- editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
+ editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
interface_with_configuration_wizard.showAllProviders();
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d5081b8d..5f61cd78 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.leap.bitmaskclient"
- android:versionCode="102"
- android:versionName="0.8.0" >
+ android:versionCode="106"
+ android:versionName="0.8.1" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -27,16 +27,17 @@
<uses-sdk
android:minSdkVersion="14"
- android:targetSdkVersion="18" />
+ android:targetSdkVersion="21"/>
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:logo="@drawable/icon"
- android:label="@string/app" >
+ android:label="@string/app"
+ android:theme="@style/appstyle">
<service
- android:name="se.leap.bitmaskclient.VoidVpnService"
+ android:name="se.leap.bitmaskclient.eip.VoidVpnService"
android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService" />
@@ -62,9 +63,10 @@
</receiver>
<activity
- android:name="se.leap.bitmaskclient.VoidVpnLauncher" />
+ android:name="se.leap.bitmaskclient.eip.VoidVpnLauncher"
+ android:theme="@android:style/Theme.NoDisplay" />
+
<activity
- android:theme="@android:style/Theme.DeviceDefault.Light.Dialog"
android:name="de.blinkt.openvpn.activities.DisconnectVPN" />
<activity
@@ -99,11 +101,11 @@
android:label="@string/title_about_activity" >
</activity>
- <service android:name="se.leap.bitmaskclient.EIP" android:exported="false">
+ <service android:name="se.leap.bitmaskclient.eip.EIP" android:exported="false">
<intent-filter>
- <action android:name="se.leap.bitmaskclient.UPDATE_EIP_SERVICE"/>
- <action android:name="se.leap.bitmaskclient.START_EIP"/>
- <action android:name="se.leap.bitmaskclient.STOP_EIP"/>
+ <action android:name="se.leap.bitmaskclient.eip.UPDATE_EIP_SERVICE"/>
+ <action android:name="se.leap.bitmaskclient.eip.START_EIP"/>
+ <action android:name="se.leap.bitmaskclient.eip.STOP_EIP"/>
</intent-filter>
</service>
</application>
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 65214c4f..fb2ba90d 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -45,7 +45,6 @@ import java.util.Collection;
import java.util.Locale;
import java.util.UUID;
import java.util.Vector;
-import java.util.concurrent.Future;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@@ -54,6 +53,7 @@ import javax.crypto.NoSuchPaddingException;
import de.blinkt.openvpn.core.NativeUtils;
import de.blinkt.openvpn.core.OpenVPNService;
+import de.blinkt.openvpn.core.VPNLaunchHelper;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.X509Utils;
@@ -68,11 +68,8 @@ public class VpnProfile implements Serializable {
public static final String EXTRA_PROFILEUUID = "de.blinkt.openvpn.profileUUID";
public static final String INLINE_TAG = "[[INLINE]]";
public static final String DISPLAYNAME_TAG = "[[NAME]]";
- private static final String MININONPIEVPN = "nopievpn";
- private static final String MINIPIEVPN = "pievpn";
private static final long serialVersionUID = 7085688938959334563L;
- private static final String OVPNCONFIGFILE = "android.conf";
public static final int MAXLOGLEVEL = 4;
public static final int CURRENT_PROFILE_VERSION = 2;
public static final int DEFAULT_MSSFIX_SIZE = 1450;
@@ -164,20 +161,6 @@ public class VpnProfile implements Serializable {
mProfileVersion = CURRENT_PROFILE_VERSION;
}
- public static String getMiniVPNExecutableName()
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
- return VpnProfile.MINIPIEVPN;
- else
- return VpnProfile.MININONPIEVPN;
- }
-
- public static String[] replacePieWithNoPie(String[] mArgv)
- {
- mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN);
- return mArgv;
- }
-
public static String openVpnEscape(String unescaped) {
if (unescaped == null)
return null;
@@ -576,19 +559,6 @@ public class VpnProfile implements Serializable {
return parts[0] + " " + netmask;
}
- private String[] buildOpenvpnArgv(File cacheDir) {
- Vector<String> args = new Vector<String>();
-
- // Add fixed paramenters
- //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
- args.add(cacheDir.getAbsolutePath() + "/" + getMiniVPNExecutableName());
-
- args.add("--config");
- args.add(cacheDir.getAbsolutePath() + "/" + OVPNCONFIGFILE);
-
-
- return args.toArray(new String[args.size()]);
- }
@@ -603,7 +573,7 @@ public class VpnProfile implements Serializable {
try {
- FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
+ FileWriter cfg = new FileWriter(VPNLaunchHelper.getConfigFilePath(context));
cfg.write(getConfigFile(context, false));
cfg.flush();
cfg.close();
@@ -618,7 +588,7 @@ public class VpnProfile implements Serializable {
String prefix = context.getPackageName();
Intent intent = new Intent(context, OpenVPNService.class);
- intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir()));
+ intent.putExtra(prefix + ".ARGV", VPNLaunchHelper.buildOpenvpnArgv(context));
intent.putExtra(prefix + ".profileUUID", mUuid.toString());
ApplicationInfo info = context.getApplicationInfo();
@@ -648,7 +618,7 @@ public class VpnProfile implements Serializable {
public static boolean isEmbedded(String data) {
if (data==null)
return false;
- if(data.startsWith(INLINE_TAG) || data.startsWith(DISPLAYNAME_TAG))
+ if (data.startsWith(INLINE_TAG) || data.startsWith(DISPLAYNAME_TAG))
return true;
else
return false;
diff --git a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java
index e6b73a48..4940d5d6 100644
--- a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java
+++ b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java
@@ -17,7 +17,7 @@ import de.blinkt.openvpn.core.ProfileManager;
/**
* Created by arne on 13.10.13.
*/
-public class DisconnectVPN extends Activity implements DialogInterface.OnClickListener{
+public class DisconnectVPN extends Activity implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
protected OpenVPNService mService;
private ServiceConnection mConnection = new ServiceConnection() {
@@ -71,6 +71,7 @@ public class DisconnectVPN extends Activity implements DialogInterface.OnClickLi
builder.setMessage(R.string.cancel_connection_query);
builder.setNegativeButton(android.R.string.no, this);
builder.setPositiveButton(android.R.string.yes,this);
+ builder.setOnCancelListener(this);
builder.show();
}
@@ -84,4 +85,9 @@ public class DisconnectVPN extends Activity implements DialogInterface.OnClickLi
}
finish();
}
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java
new file mode 100644
index 00000000..5b1dda58
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java
@@ -0,0 +1,47 @@
+package de.blinkt.openvpn.core;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.RestrictionEntry;
+import android.os.Build;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+
+import se.leap.bitmaskclient.R;
+
+/**
+ * Created by arne on 25.07.13.
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+public class GetRestrictionReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ final PendingResult result = goAsync();
+
+ new Thread() {
+ @Override
+ public void run() {
+ final Bundle extras = new Bundle();
+
+ ArrayList<RestrictionEntry> restrictionEntries = initRestrictions(context);
+
+ extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, restrictionEntries);
+ result.setResult(Activity.RESULT_OK,null,extras);
+ result.finish();
+ }
+ }.run();
+ }
+
+ private ArrayList<RestrictionEntry> initRestrictions(Context context) {
+ ArrayList<RestrictionEntry> restrictions = new ArrayList<RestrictionEntry>();
+ RestrictionEntry allowChanges = new RestrictionEntry("allow_changes",false);
+ allowChanges.setTitle(context.getString(R.string.allow_vpn_changes));
+ restrictions.add(allowChanges);
+
+ return restrictions;
+ }
+}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index ada065ba..d9830955 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -719,6 +719,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
public void updateState(String state, String logmessage, int resid, ConnectionStatus level) {
// If the process is not running, ignore any state,
// Notification should be invisible in this state
+
doSendBroadcast(state, level);
if (mProcessThread == null && !mNotificationAlwaysVisible)
return;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
index e3c60854..e36a5b8a 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
@@ -5,6 +5,7 @@
package de.blinkt.openvpn.core;
+import android.annotation.SuppressLint;
import android.util.Log;
import java.io.BufferedReader;
@@ -30,6 +31,7 @@ import de.blinkt.openvpn.core.VpnStatus.LogItem;
public class OpenVPNThread implements Runnable {
private static final String DUMP_PATH_STRING = "Dump path: ";
+ @SuppressLint("SdCardPath")
private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:";
private static final String TAG = "OpenVPN";
public static final int M_FATAL = (1 << 4);
@@ -78,7 +80,8 @@ public class OpenVPNThread implements Runnable {
if( exitvalue != 0) {
VpnStatus.logError("Process exited with exit value " + exitvalue);
if (mBrokenPie) {
- String[] noPieArgv = VpnProfile.replacePieWithNoPie(mArgv);
+ /* This will probably fail since the NoPIE binary is probably not written */
+ String[] noPieArgv = VPNLaunchHelper.replacePieWithNoPie(mArgv);
// We are already noPIE, nothing to gain
if (!noPieArgv.equals(mArgv)) {
@@ -190,7 +193,7 @@ public class OpenVPNThread implements Runnable {
private String genLibraryPath(String[] argv, ProcessBuilder pb) {
// Hack until I find a good way to get the real library path
- String applibpath = argv[0].replace("/cache/" + VpnProfile.getMiniVPNExecutableName() , "/lib");
+ String applibpath = argv[0].replaceFirst("/cache/.*$" , "/lib");
String lbpath = pb.environment().get("LD_LIBRARY_PATH");
if(lbpath==null)
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index 40f9742b..208aa359 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -5,70 +5,122 @@
package de.blinkt.openvpn.core;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.os.Build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Vector;
import se.leap.bitmaskclient.R;
import de.blinkt.openvpn.VpnProfile;
public class VPNLaunchHelper {
- static private boolean writeMiniVPN(Context context) {
- File mvpnout = new File(context.getCacheDir(),VpnProfile.getMiniVPNExecutableName());
- if (mvpnout.exists() && mvpnout.canExecute())
- return true;
-
- IOException e2 = null;
-
- try {
- InputStream mvpn;
-
- try {
- mvpn = context.getAssets().open(VpnProfile.getMiniVPNExecutableName() + "." + Build.CPU_ABI);
- }
- catch (IOException errabi) {
- VpnStatus.logInfo("Failed getting assets for archicture " + Build.CPU_ABI);
- e2=errabi;
- mvpn = context.getAssets().open(VpnProfile.getMiniVPNExecutableName() + "." + Build.CPU_ABI2);
-
- }
-
-
- FileOutputStream fout = new FileOutputStream(mvpnout);
-
- byte buf[]= new byte[4096];
-
- int lenread = mvpn.read(buf);
- while(lenread> 0) {
- fout.write(buf, 0, lenread);
- lenread = mvpn.read(buf);
- }
- fout.close();
-
- if(!mvpnout.setExecutable(true)) {
- VpnStatus.logError("Failed to make OpenVPN executable");
- return false;
- }
-
-
- return true;
- } catch (IOException e) {
- if(e2!=null)
- VpnStatus.logException(e2);
- VpnStatus.logException(e);
-
- return false;
- }
+ private static final String MININONPIEVPN = "nopievpn";
+ private static final String MINIPIEVPN = "pievpn";
+ private static final String OVPNCONFIGFILE = "android.conf";
+
+
+
+ static private String writeMiniVPN(Context context) {
+ String[] abis;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ abis = getSupportedAbisLollipop();
+ else
+ abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};
+
+ for (String abi: abis) {
+
+ File mvpnout = new File(context.getCacheDir(), getMiniVPNExecutableName() + "." + abi);
+ if ((mvpnout.exists() && mvpnout.canExecute()) || writeMiniVPNBinary(context, abi, mvpnout)) {
+ return mvpnout.getPath();
+ }
+ }
+
+ return null;
}
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static String[] getSupportedAbisLollipop() {
+ return Build.SUPPORTED_ABIS;
+ }
+
+ private static String getMiniVPNExecutableName()
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
+ return MINIPIEVPN;
+ else
+ return MININONPIEVPN;
+ }
+
+
+ public static String[] replacePieWithNoPie(String[] mArgv)
+ {
+ mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN);
+ return mArgv;
+ }
+
+
+ public static String[] buildOpenvpnArgv(Context c) {
+ Vector<String> args = new Vector<String>();
+
+ // Add fixed paramenters
+ //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
+ args.add(writeMiniVPN(c));
+
+ args.add("--config");
+ args.add(c.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
+
+
+ return args.toArray(new String[args.size()]);
+ }
+
+ private static boolean writeMiniVPNBinary(Context context, String abi, File mvpnout) {
+ try {
+ InputStream mvpn;
+
+ try {
+ mvpn = context.getAssets().open(getMiniVPNExecutableName() + "." + abi);
+ }
+ catch (IOException errabi) {
+ VpnStatus.logInfo("Failed getting assets for archicture " + abi);
+ return false;
+ }
+
+
+ FileOutputStream fout = new FileOutputStream(mvpnout);
+
+ byte buf[]= new byte[4096];
+
+ int lenread = mvpn.read(buf);
+ while(lenread> 0) {
+ fout.write(buf, 0, lenread);
+ lenread = mvpn.read(buf);
+ }
+ fout.close();
+
+ if(!mvpnout.setExecutable(true)) {
+ VpnStatus.logError("Failed to make OpenVPN executable");
+ return false;
+ }
+
+
+ return true;
+ } catch (IOException e) {
+ VpnStatus.logException(e);
+ return false;
+ }
+
+ }
public static void startOpenVpn(VpnProfile startprofile, Context context) {
- if(!writeMiniVPN(context)) {
+ if(writeMiniVPN(context)==null) {
VpnStatus.logError("Error writing minivpn binary");
return;
}
@@ -80,4 +132,9 @@ public class VPNLaunchHelper {
context.startService(startVPN);
}
+
+ public static String getConfigFilePath(Context context) {
+ return context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE;
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
index 6d025422..6c4e517b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
@@ -1,15 +1,10 @@
package se.leap.bitmaskclient;
import android.app.Activity;
-import android.app.Fragment;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
import android.widget.TextView;
-import se.leap.bitmaskclient.R;
public class AboutActivity extends Activity {
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index c95d0c8b..c0f0b0c3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -16,11 +16,15 @@
*/
package se.leap.bitmaskclient;
+import android.util.Base64;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
-import java.lang.IllegalArgumentException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -33,13 +37,6 @@ import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Base64;
-
/**
* Stores constants, and implements auxiliary methods used across all LEAP Android classes.
*
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 364a79af..e32dbdee 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -14,18 +14,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
-import se.leap.bitmaskclient.FragmentManagerEnhanced;
-import se.leap.bitmaskclient.SignUpDialog;
-
-import de.blinkt.openvpn.activities.LogWindow;
+package se.leap.bitmaskclient;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DialogFragment;
@@ -41,24 +32,36 @@ import android.os.ResultReceiver;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
+
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import de.blinkt.openvpn.activities.LogWindow;
+import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.eip.EIP;
+import se.leap.bitmaskclient.eip.EipStatus;
/**
- * The main user facing Activity of LEAP Android, consisting of status, controls,
+ * The main user facing Activity of Bitmask Android, consisting of status, controls,
* and access to preferences.
*
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author parmegv
*/
-public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, Receiver {
+public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver {
protected static final int CONFIGURE_LEAP = 0;
protected static final int SWITCH_PROVIDER = 1;
+ final public static String TAG = Dashboard.class.getSimpleName();
final public static String SHARED_PREFERENCES = "LEAPPreferences";
final public static String ACTION_QUIT = "quit";
public static final String REQUEST_CODE = "request_code";
@@ -66,98 +69,119 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
public static final String START_ON_BOOT = "dashboard start on boot";
final public static String ON_BOOT = "dashboard on boot";
public static final String APP_VERSION = "bitmask version";
- final public static String TAG = Dashboard.class.getSimpleName();
-
- private EipServiceFragment eipFragment;
- private ProgressBar mProgressBar;
- private TextView eipStatus;
- private static Context app;
- protected static SharedPreferences preferences;
- private static Provider provider;
+ private static Context app;
+ protected static SharedPreferences preferences;
+ private FragmentManagerEnhanced fragment_manager;
- private boolean authed_eip = false;
+ @InjectView(R.id.providerName)
+ TextView provider_name;
+ EipFragment eip_fragment;
+ private Provider provider;
+ private static boolean authed_eip;
public ProviderAPIResultReceiver providerAPI_result_receiver;
- private FragmentManagerEnhanced fragment_manager;
- @Override
+ @Override
+ protected void onSaveInstanceState(@NotNull Bundle outState) {
+ if(provider != null)
+ outState.putParcelable(Provider.KEY, provider);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = this;
PRNGFixes.apply();
-
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
handleVersion();
-
- authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false);
- if (preferences.getString(Provider.KEY, "").isEmpty())
- startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
- else
- buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
+
+ provider = getSavedProvider(savedInstanceState);
+ if (provider == null || provider.getName().isEmpty())
+ startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
+ else
+ buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
}
+ private Provider getSavedProvider(Bundle savedInstanceState) {
+ Provider provider = null;
+ if(savedInstanceState != null)
+ provider = savedInstanceState.getParcelable(Provider.KEY);
+ else if(preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false))
+ provider = getSavedProviderFromSharedPreferences();
+
+ return provider;
+ }
+
+ private Provider getSavedProviderFromSharedPreferences() {
+ Provider provider = null;
+ try {
+ provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, "")));
+ provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
+ } catch (MalformedURLException | JSONException e) {
+ e.printStackTrace();
+ }
+
+ return provider;
+ }
+
+
private void handleVersion() {
try {
int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
int lastDetectedVersion = preferences.getInt(APP_VERSION, 0);
- preferences.edit().putInt(APP_VERSION, versionCode);
+ preferences.edit().putInt(APP_VERSION, versionCode).apply();
Log.d("Dashboard", "detected version code: " + versionCode);
Log.d("Dashboard", "last detected version code: " + lastDetectedVersion);
switch(versionCode) {
case 91: // 0.6.0 without Bug #5999
case 101: // 0.8.0
- if(!preferences.getString(EIP.KEY, "").isEmpty()) {
+ if(!preferences.getString(Constants.KEY, "").isEmpty()) {
Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class);
- rebuildVpnProfiles.setAction(EIP.ACTION_REBUILD_PROFILES);
+ rebuildVpnProfiles.setAction(Constants.ACTION_UPDATE_EIP_SERVICE);
startService(rebuildVpnProfiles);
}
break;
}
} catch (NameNotFoundException e) {
+ Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package");
}
}
-
- @Override
- protected void onDestroy() {
-
- super.onDestroy();
- }
-
- protected void onPause() {
- super.onPause();
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, final Intent data){
- if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) {
- // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) {
- if ( resultCode == RESULT_OK ){
- preferences.edit().putInt(EIP.PARSED_SERIAL, 0).commit();
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
-
- Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
- updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
- startService(updateEIP);
-
- buildDashboard(false);
- invalidateOptionsMenu();
- if(data != null && data.hasExtra(LogInDialog.TAG)) {
- View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(Bundle.EMPTY);
- }
- } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) {
- finish();
- } else
- configErrorDialog();
- }
+ @SuppressLint("CommitPrefEdits")
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ Log.d(TAG, "onActivityResult: requestCode = " + requestCode);
+ if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) {
+ if ( resultCode == RESULT_OK ) {
+ preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
+ updateEipService();
+
+ if (data.hasExtra(Provider.KEY)) {
+ provider = data.getParcelableExtra(Provider.KEY);
+ preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit();
+ preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply();
+ preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply();
+ }
+ buildDashboard(false);
+ invalidateOptionsMenu();
+ if (data.hasExtra(SessionDialog.TAG)) {
+ logInDialog(Bundle.EMPTY);
+ }
+ } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) {
+ finish();
+ } else
+ configErrorDialog();
+ } else if(requestCode == EIP.DISCONNECT) {
+ EipStatus.getInstance().setConnectedOrDisconnected();
}
+ }
/**
* Dialog shown when encountering a configuration error. Such errors require
@@ -178,7 +202,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
.setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- preferences.edit().remove(Provider.KEY).commit();
+ preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply();
finish();
}
})
@@ -190,30 +214,27 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
* service dependent UI elements to include.
*/
private void buildDashboard(boolean hide_and_turn_on_eip) {
- provider = Provider.getInstance();
- provider.init( this );
-
- setContentView(R.layout.client_dashboard);
-
- TextView providerNameTV = (TextView) findViewById(R.id.providerName);
- providerNameTV.setText(provider.getDomain());
- providerNameTV.setTextSize(28);
-
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ setContentView(R.layout.dashboard);
+ ButterKnife.inject(this);
+ provider_name.setText(provider.getDomain());
if ( provider.hasEIP()){
- eipFragment = new EipServiceFragment();
- if (hide_and_turn_on_eip) {
- preferences.edit().remove(Dashboard.START_ON_BOOT).commit();
- Bundle arguments = new Bundle();
- arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true);
- eipFragment.setArguments(arguments);
- }
- fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG);
- if (hide_and_turn_on_eip) {
- onBackPressed();
- }
+ fragment_manager.removePreviousFragment(EipFragment.TAG);
+ eip_fragment = new EipFragment();
+
+ if (hide_and_turn_on_eip) {
+ preferences.edit().remove(Dashboard.START_ON_BOOT).apply();
+ Bundle arguments = new Bundle();
+ arguments.putBoolean(EipFragment.START_ON_BOOT, true);
+ if(eip_fragment != null) eip_fragment.setArguments(arguments);
+ }
+
+ fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
+
+ if (hide_and_turn_on_eip) {
+ onBackPressed();
+ }
}
}
@@ -222,12 +243,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
JSONObject provider_json;
try {
String provider_json_string = preferences.getString(Provider.KEY, "");
- if(provider_json_string.isEmpty() == false) {
+ if(!provider_json_string.isEmpty()) {
provider_json = new JSONObject(provider_json_string);
JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
boolean authed_eip = !LeapSRPSession.getToken().isEmpty();
boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION);
- preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip);
+ preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip).apply();
if(allow_registered_eip) {
if(authed_eip) {
@@ -267,13 +288,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
startActivity(startLW);
return true;
case R.id.switch_provider:
- if (Provider.getInstance().hasEIP()){
- if (preferences.getBoolean(EIP.AUTHED_EIP, false)){
- logOut();
- }
- eipStop();
+ if (provider.hasEIP()){
+ if (preferences.getBoolean(Constants.AUTHED_EIP, false)) {
+ logOut();
+ }
+ eip_fragment.askToStopEIP();
}
- preferences.edit().clear().commit();
+ preferences.edit().clear().apply();
startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER);
return true;
case R.id.login_button:
@@ -291,10 +312,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
- private Intent prepareProviderAPICommand() {
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- eipStatus = (TextView) findViewById(R.id.eipStatus);
-
+ protected Intent prepareProviderAPICommand() {
providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
providerAPI_result_receiver.setReceiver(this);
@@ -308,12 +326,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
* Shows the log in dialog.
*/
public void logInDialog(Bundle resultData) {
- FragmentTransaction transaction = fragment_manager.removePreviousFragment(LogInDialog.TAG);
+ FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
- DialogFragment newFragment = LogInDialog.newInstance();
+ DialogFragment newFragment = SessionDialog.newInstance();
if(resultData != null && !resultData.isEmpty())
newFragment.setArguments(resultData);
- newFragment.show(transaction, LogInDialog.TAG);
+ newFragment.show(transaction, SessionDialog.TAG);
}
@Override
@@ -323,24 +341,20 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
if(parameters == null)
parameters = new Bundle();
- parameters.putString(SessionDialogInterface.USERNAME, username);
- parameters.putString(SessionDialogInterface.PASSWORD, password);
-
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- eipStatus.setText(R.string.authenticating_message);
+ parameters.putString(SessionDialog.USERNAME, username);
+ parameters.putString(SessionDialog.PASSWORD, password);
+ if(eip_fragment != null) {
+ eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE);
+ eip_fragment.status_message.setText(R.string.authenticating_message);
+ }
provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
provider_API_command.setAction(ProviderAPI.SRP_AUTH);
startService(provider_API_command);
}
- public void cancelAuthedEipOn() {
- EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
- eipFragment.checkEipSwitch(false);
- }
-
public void cancelLoginOrSignup() {
- hideProgressBar();
+ EipStatus.getInstance().setConnectedOrDisconnected();
}
/**
@@ -348,12 +362,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
*/
public void logOut() {
Intent provider_API_command = prepareProviderAPICommand();
-
- if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
- eipStatus.setText(R.string.logout_message);
-
+ if(eip_fragment != null) {
+
+ eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE);
+ eip_fragment.status_message.setText(R.string.logout_message);
+ }
provider_API_command.setAction(ProviderAPI.LOG_OUT);
startService(provider_API_command);
}
@@ -362,13 +375,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
* Shows the sign up dialog.
*/
public void signUpDialog(Bundle resultData) {
- FragmentTransaction transaction = fragment_manager.removePreviousFragment(SignUpDialog.TAG);
+ FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
- DialogFragment newFragment = SignUpDialog.newInstance();
+ DialogFragment newFragment = SessionDialog.newInstance();
if(resultData != null && !resultData.isEmpty()) {
newFragment.setArguments(resultData);
}
- newFragment.show(transaction, SignUpDialog.TAG);
+ newFragment.show(transaction, SessionDialog.TAG);
}
@Override
@@ -378,12 +391,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
if(parameters == null)
parameters = new Bundle();
- parameters.putString(SessionDialogInterface.USERNAME, username);
- parameters.putString(SessionDialogInterface.PASSWORD, password);
-
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- eipStatus.setText(R.string.signingup_message);
-
+ parameters.putString(SessionDialog.USERNAME, username);
+ parameters.putString(SessionDialog.PASSWORD, password);
+ if(eip_fragment != null) {
+ eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE);
+ eip_fragment.status_message.setText(R.string.signingup_message);
+ }
provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
provider_API_command.setAction(ProviderAPI.SRP_REGISTER);
startService(provider_API_command);
@@ -410,38 +423,39 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL) {
- String username = resultData.getString(SessionDialogInterface.USERNAME);
- String password = resultData.getString(SessionDialogInterface.PASSWORD);
+ Log.d(TAG, "onReceiveResult");
+ if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) {
+ String username = resultData.getString(SessionDialog.USERNAME);
+ String password = resultData.getString(SessionDialog.PASSWORD);
logIn(username, password);
- } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED) {
+ } else if(resultCode == ProviderAPI.FAILED_SIGNUP) {
changeStatusMessage(resultCode);
hideProgressBar();
signUpDialog(resultData);
- } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL) {
+ } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) {
changeStatusMessage(resultCode);
hideProgressBar();
invalidateOptionsMenu();
authed_eip = true;
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
+ preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
downloadAuthedUserCertificate();
- } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) {
+ } else if(resultCode == ProviderAPI.FAILED_LOGIN) {
changeStatusMessage(resultCode);
hideProgressBar();
logInDialog(resultData);
- } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) {
+ } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) {
changeStatusMessage(resultCode);
hideProgressBar();
invalidateOptionsMenu();
authed_eip = false;
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
+ preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
} else if(resultCode == ProviderAPI.LOGOUT_FAILED) {
changeStatusMessage(resultCode);
@@ -453,46 +467,55 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
hideProgressBar();
setResult(RESULT_OK);
- Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
- ResultReceiver eip_receiver = new ResultReceiver(new Handler()){
- protected void onReceiveResult(int resultCode, Bundle resultData){
- super.onReceiveResult(resultCode, resultData);
- String request = resultData.getString(EIP.REQUEST_TAG);
- if (resultCode == Activity.RESULT_OK){
- if(authed_eip)
- eipStart();
- else
- eipStatus.setText("Certificate updated");
- }
- }
- };
- updateEIP.putExtra(EIP.RECEIVER_TAG, eip_receiver);
- updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
- startService(updateEIP);
+
+ updateEipService();
} else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
changeStatusMessage(resultCode);
hideProgressBar();
setResult(RESULT_CANCELED);
}
+ else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) {
+ setResult(RESULT_OK);
+
+ updateEipService();
+ } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) {
+ setResult(RESULT_CANCELED);
+ }
}
+ private void updateEipService() {
+ Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
+ updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE);
+ ResultReceiver receiver = new ResultReceiver(new Handler()) {
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ String request = resultData.getString(Constants.REQUEST_TAG);
+ if(request.equalsIgnoreCase(Constants.ACTION_UPDATE_EIP_SERVICE)) {
+ if(resultCode == Activity.RESULT_OK) {
+ if(authed_eip && eip_fragment != null) eip_fragment.startEipFromScratch();
+ }
+ }
+ }
+ };
+ //updateEIP.putExtra(Constants.RECEIVER_TAG, receiver);
+ startService(updateEIP);
+ }
+
private void changeStatusMessage(final int previous_result_code) {
// TODO Auto-generated method stub
ResultReceiver eip_status_receiver = new ResultReceiver(new Handler()){
protected void onReceiveResult(int resultCode, Bundle resultData){
super.onReceiveResult(resultCode, resultData);
- String request = resultData.getString(EIP.REQUEST_TAG);
- if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
- if (request.equalsIgnoreCase(EIP.ACTION_IS_EIP_RUNNING)){
+ String request = resultData.getString(Constants.REQUEST_TAG);
+ if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){
if (resultCode == Activity.RESULT_OK){
switch(previous_result_code){
- case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break;
- case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break;
- case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.authed_secured_status); break;
- case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break;
- case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break;
- case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break;
+ case ProviderAPI.SUCCESSFUL_LOGIN: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break;
+ case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break;
+ case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.authed_secured_status); break;
+ case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break;
+ case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break;
+ case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break;
}
}
@@ -500,13 +523,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
switch(previous_result_code){
- case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break;
- case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break;
- case ProviderAPI.SRP_REGISTRATION_FAILED: eipStatus.setText(R.string.registration_failed_message); break;
+ case ProviderAPI.SUCCESSFUL_LOGIN: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break;
+ case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break;
+ case ProviderAPI.FAILED_SIGNUP: eip_fragment.status_message.setText(R.string.registration_failed_message); break;
case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break;
- case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break;
- case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break;
- case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break;
+ case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break;
+ case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break;
+ case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break;
}
}
}
@@ -517,11 +540,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
private void hideProgressBar() {
- if(mProgressBar == null)
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
-
- mProgressBar.setProgress(0);
- mProgressBar.setVisibility(ProgressBar.GONE);
+ if(eip_fragment != null) {
+ eip_fragment.progress_bar.setProgress(0);
+ eip_fragment.progress_bar.setVisibility(ProgressBar.GONE);
+ }
}
/**
@@ -544,24 +566,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
private void eipIsRunning(ResultReceiver eip_receiver){
// TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
Intent eip_intent = new Intent(this, EIP.class);
- eip_intent.setAction(EIP.ACTION_IS_EIP_RUNNING);
- eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver);
+ eip_intent.setAction(Constants.ACTION_IS_EIP_RUNNING);
+ eip_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver);
startService(eip_intent);
}
-
- private void eipStop(){
- EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
- eipFragment.stopEIP();
- }
-
- private void eipStart() {
- EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
- eipFragment.startEipFromScratch();
- }
-
- protected void showProgressBar() {
- if(mProgressBar == null)
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
index f78002b0..a44253c6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
@@ -16,9 +16,6 @@
*/
package se.leap.bitmaskclient;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java
deleted file mode 100644
index 2f06def3..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/EIP.java
+++ /dev/null
@@ -1,524 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package se.leap.bitmaskclient;
-
-import android.app.Activity;
-import android.app.IntentService;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.util.Log;
-import de.blinkt.openvpn.LaunchVPN;
-import de.blinkt.openvpn.VpnProfile;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.core.ConfigParser;
-import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
-import de.blinkt.openvpn.core.ProfileManager;
-import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
-import java.io.IOException;
-import java.io.StringReader;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.Vector;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import se.leap.bitmaskclient.Dashboard;
-import se.leap.bitmaskclient.Provider;
-import se.leap.bitmaskclient.R;
-
-/**
- * EIP is the abstract base class for interacting with and managing the Encrypted
- * Internet Proxy connection. Connections are started, stopped, and queried through
- * this IntentService.
- * Contains logic for parsing eip-service.json from the provider, configuring and selecting
- * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections.
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- * @author Parménides GV <parmegv@sdf.org>
- */
-public final class EIP extends IntentService {
-
- public final static String AUTHED_EIP = "authed eip";
- public final static String ACTION_CHECK_CERT_VALIDITY = "se.leap.bitmaskclient.CHECK_CERT_VALIDITY";
- public final static String ACTION_START_EIP = "se.leap.bitmaskclient.START_EIP";
- public final static String ACTION_STOP_EIP = "se.leap.bitmaskclient.STOP_EIP";
- public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.bitmaskclient.UPDATE_EIP_SERVICE";
- public final static String ACTION_IS_EIP_RUNNING = "se.leap.bitmaskclient.IS_RUNNING";
- public final static String ACTION_REBUILD_PROFILES = "se.leap.bitmaskclient.REBUILD_PROFILES";
- public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION";
- public final static String STATUS = "eip status";
- public final static String DATE_FROM_CERTIFICATE = "date from certificate";
- public final static String ALLOWED_ANON = "allow_anonymous";
- public final static String ALLOWED_REGISTERED = "allow_registration";
- public final static String CERTIFICATE = "cert";
- public final static String PRIVATE_KEY = "private_key";
- public final static String KEY = "eip";
- public final static String PARSED_SERIAL = "eip_parsed_serial";
- public final static String SERVICE_API_PATH = "config/eip-service.json";
- public final static String RECEIVER_TAG = "receiverTag";
- public final static String REQUEST_TAG = "requestTag";
- public final static String TAG = EIP.class.getSimpleName();
- private static SharedPreferences preferences;
-
- private static Context context;
- private static ResultReceiver mReceiver;
- private static boolean mBound = false;
-
- private static JSONObject eipDefinition = null;
-
- private static OVPNGateway activeGateway = null;
-
- protected static ConnectionStatus lastConnectionStatusLevel;
- protected static boolean mIsDisconnecting = false;
- protected static boolean mIsStarting = false;
-
- public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
- public EIP(){
- super("LEAPEIP");
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- context = getApplicationContext();
-
- preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
- }
-
- @Override
- public void onDestroy() {
-
- mBound = false;
-
- super.onDestroy();
- }
-
-
- @Override
- protected void onHandleIntent(Intent intent) {
- String action = intent.getAction();
- mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
-
- if ( action == ACTION_START_EIP )
- startEIP();
- else if ( action == ACTION_STOP_EIP )
- stopEIP();
- else if ( action == ACTION_IS_EIP_RUNNING )
- isRunning();
- else if ( action == ACTION_UPDATE_EIP_SERVICE )
- updateEIPService();
- else if ( action == ACTION_CHECK_CERT_VALIDITY )
- checkCertValidity();
- else if ( action == ACTION_REBUILD_PROFILES )
- updateGateways();
- }
-
- /**
- * Initiates an EIP connection by selecting a gateway and preparing and sending an
- * Intent to {@link se.leap.openvpn.LaunchVPN}.
- * It also sets up early routes.
- */
- private void startEIP() {
- earlyRoutes();
- activeGateway = selectGateway();
-
- if(activeGateway != null && activeGateway.mVpnProfile != null) {
- mReceiver = EipServiceFragment.getReceiver();
- launchActiveGateway();
- }
- }
-
- /**
- * Early routes are routes that block traffic until a new
- * VpnService is started properly.
- */
- private void earlyRoutes() {
- Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class);
- void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(void_vpn_launcher);
- }
-
- /**
- * Choose a gateway to connect to based on timezone from system locale data
- *
- * @return The gateway to connect to
- */
- private OVPNGateway selectGateway() {
- String closest_location = closestGateway();
- String chosen_host = chooseHost(closest_location);
-
- return new OVPNGateway(chosen_host);
- }
-
- private String closestGateway() {
- TreeMap<Integer, Set<String>> offsets = calculateOffsets();
- return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
- }
-
- private TreeMap<Integer, Set<String>> calculateOffsets() {
- TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
-
- int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
-
- JSONObject locations = availableLocations();
- Iterator<String> locations_names = locations.keys();
- while(locations_names.hasNext()) {
- try {
- String location_name = locations_names.next();
- JSONObject location = locations.getJSONObject(location_name);
-
- int dist = timezoneDistance(localOffset, location.optInt("timezone"));
-
- Set<String> set = (offsets.get(dist) != null) ?
- offsets.get(dist) : new HashSet<String>();
-
- set.add(location_name);
- offsets.put(dist, set);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- return offsets;
- }
-
- private JSONObject availableLocations() {
- JSONObject locations = null;
- try {
- if(eipDefinition == null) updateEIPService();
- locations = eipDefinition.getJSONObject("locations");
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- return locations;
- }
-
- private int timezoneDistance(int local_timezone, int remote_timezone) {
- // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
- int dist = Math.abs(local_timezone - remote_timezone);
-
- // Farther than 12 timezones and it's shorter around the "back"
- if (dist > 12)
- dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things.
-
- return dist;
- }
-
- private String chooseHost(String location) {
- String chosen_host = "";
- try {
- JSONArray gateways = eipDefinition.getJSONArray("gateways");
- for (int i = 0; i < gateways.length(); i++) {
- JSONObject gw = gateways.getJSONObject(i);
- if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){
- chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name");
- break;
- }
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return chosen_host;
- }
-
- private void launchActiveGateway() {
- Intent intent = new Intent(this,LaunchVPN.class);
- intent.setAction(Intent.ACTION_MAIN);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() );
- intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
- intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
- intent.putExtra(RECEIVER_TAG, mReceiver);
- startActivity(intent);
- }
-
- /**
- * Disconnects the EIP connection gracefully through the bound service or forcefully
- * if there is no bound service. Sends a message to the requesting ResultReceiver.
- */
- private void stopEIP() {
- if(isConnected()) {
- Intent disconnect_vpn = new Intent(this, DisconnectVPN.class);
- disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(disconnect_vpn);
- mIsDisconnecting = true;
- lastConnectionStatusLevel = ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user
- Log.d(TAG, "mIsDisconnecting = true");
- }
-
- tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK);
- }
-
- private void tellToReceiver(String action, int resultCode) {
- if (mReceiver != null){
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, action);
- mReceiver.send(resultCode, resultData);
- }
- }
-
- /**
- * Checks the last stored status notified by ics-openvpn
- * Sends <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
- * request if it's not connected, <code>Activity.RESULT_OK</code> otherwise.
- */
-
- private void isRunning() {
- int resultCode = Activity.RESULT_CANCELED;
- boolean is_connected = isConnected();
-
- resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
-
- tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode);
- }
-
- protected static boolean isConnected() {
- return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting;
- }
-
- /**
- * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()}
- * to parse gateway definitions.
- * TODO Implement API call to refresh eip-service.json from the provider
- */
- private void updateEIPService() {
- try {
- String eip_definition_string = preferences.getString(KEY, "");
- if(eip_definition_string.isEmpty() == false) {
- eipDefinition = new JSONObject(eip_definition_string);
- }
- deleteAllVpnProfiles();
- updateGateways();
- if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- private void deleteAllVpnProfiles() {
- ProfileManager vpl = ProfileManager.getInstance(context);
- Collection<VpnProfile> profiles = vpl.getProfiles();
- profiles.removeAll(profiles);
- }
-
- /**
- * Walk the list of gateways defined in eip-service.json and parse them into
- * OVPNGateway objects.
- * TODO Store the OVPNGateways (as Serializable) in SharedPreferences
- */
- private void updateGateways(){
- JSONArray gatewaysDefined = null;
- try {
- if(eipDefinition == null) updateEIPService();
- gatewaysDefined = eipDefinition.getJSONArray("gateways");
- for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
- JSONObject gw = null;
- gw = gatewaysDefined.getJSONObject(i);
-
- if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") )
- new OVPNGateway(gw);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit();
- }
-
- private void checkCertValidity() {
- String certificate = preferences.getString(CERTIFICATE, "");
- checkCertValidity(certificate);
- }
-
- private void checkCertValidity(String certificate_string) {
- if(!certificate_string.isEmpty()) {
- X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string);
-
- Calendar offset_date = calculateOffsetCertificateValidity(certificate);
- Bundle result = new Bundle();
- result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY);
- try {
- Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
- certificate.checkValidity(offset_date.getTime());
- mReceiver.send(Activity.RESULT_OK, result);
- Log.d(TAG, "Valid certificate");
- } catch(CertificateExpiredException e) {
- mReceiver.send(Activity.RESULT_CANCELED, result);
- Log.d(TAG, "Updating certificate");
- } catch(CertificateNotYetValidException e) {
- mReceiver.send(Activity.RESULT_CANCELED, result);
- }
- }
- }
-
- private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) {
- String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString();
-
- String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date);
-
- Calendar offset_date = Calendar.getInstance();
- try {
- Date date = certificate_date_format.parse(date_string);
- long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2;
- long current_date_millis = offset_date.getTimeInMillis();
- offset_date.setTimeInMillis(current_date_millis + difference);
- Log.d(TAG, "certificate not after = " + certificate.getNotAfter());
- } catch(ParseException e) {
- e.printStackTrace();
- }
-
- return offset_date;
- }
-
- /**
- * OVPNGateway provides objects defining gateways and their options and metadata.
- * Each instance contains a VpnProfile for OpenVPN specific data and member
- * variables describing capabilities and location
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
- private class OVPNGateway {
-
- private String TAG = "OVPNGateway";
-
- private String mName;
- private VpnProfile mVpnProfile;
- private JSONObject mGateway;
- private HashMap<String,Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
-
-
- /**
- * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it.
- * FIXME This needs to become a findGatewayByName() method
- *
- * @param name The hostname of the gateway to inflate
- */
- private OVPNGateway(String name){
- mName = name;
-
- this.loadVpnProfile();
- }
-
- private void loadVpnProfile() {
- ProfileManager vpl = ProfileManager.getInstance(context);
- try {
- if ( mName == null )
- mVpnProfile = vpl.getProfiles().iterator().next();
- else
- mVpnProfile = vpl.getProfileByName(mName);
- } catch (NoSuchElementException e) {
- updateEIPService();
- this.loadVpnProfile(); // FIXME catch infinite loops
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json
- * and create a VpnProfile belonging to it.
- *
- * @param gateway The JSON OpenVPN gateway definition to parse
- */
- protected OVPNGateway(JSONObject gateway){
-
- mGateway = gateway;
-
- // Currently deletes VpnProfile for host, if there already is one, and builds new
- ProfileManager vpl = ProfileManager.getInstance(context);
- Collection<VpnProfile> profiles = vpl.getProfiles();
- for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){
- VpnProfile p = it.next();
-
- if ( p.mName.equalsIgnoreCase( mName ) ) {
- it.remove();
- vpl.removeProfile(context, p);
- }
- }
-
- this.createVPNProfile();
-
- vpl.addProfile(mVpnProfile);
- vpl.saveProfile(context, mVpnProfile);
- vpl.saveProfileList(context);
- }
-
- /**
- * Create and attach the VpnProfile to our gateway object
- */
- protected void createVPNProfile(){
- try {
- ConfigParser cp = new ConfigParser();
-
- JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration");
- VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway);
- String configuration = vpn_configuration_generator.generate();
-
- cp.parseConfig(new StringReader(configuration));
- mVpnProfile = cp.convertProfile();
- mVpnProfile.mName = mName = locationAsName();
- Log.v(TAG,"Created VPNProfile");
-
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ConfigParseError e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- } catch (IOException e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- }
- }
-
-
- public String locationAsName() {
- try {
- return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name");
- } catch (JSONException e) {
- Log.v(TAG,"Couldn't read gateway name for profile creation! Returning original name = " + mName);
- e.printStackTrace();
- return (mName != null) ? mName : "";
- }
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
new file mode 100644
index 00000000..420da7a1
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -0,0 +1,362 @@
+package se.leap.bitmaskclient;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnCheckedChanged;
+import de.blinkt.openvpn.activities.DisconnectVPN;
+import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.eip.EIP;
+import se.leap.bitmaskclient.eip.EipStatus;
+import se.leap.bitmaskclient.eip.VoidVpnService;
+
+public class EipFragment extends Fragment implements Observer {
+
+ public static String TAG = EipFragment.class.getSimpleName();
+
+ protected static final String IS_PENDING = TAG + ".is_pending";
+ protected static final String IS_CONNECTED = TAG + ".is_connected";
+ protected static final String STATUS_MESSAGE = TAG + ".status_message";
+ public static final String START_ON_BOOT = "start on boot";
+
+ private View view;
+ @InjectView(R.id.eipSwitch)
+ Switch eip_switch;
+ @InjectView(R.id.status_message)
+ TextView status_message;
+ @InjectView(R.id.eipProgress)
+ ProgressBar progress_bar;
+
+ private static Activity parent_activity;
+ private static EIPReceiver mEIPReceiver;
+ private static EipStatus eip_status;
+ private boolean is_starting_to_connect;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ parent_activity = activity;
+
+ Dashboard dashboard = (Dashboard) parent_activity;
+ Intent provider_API_command = dashboard.prepareProviderAPICommand();
+ provider_API_command.setAction(ProviderAPI.DOWNLOAD_EIP_SERVICE);
+ parent_activity.startService(provider_API_command);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ eip_status = EipStatus.getInstance();
+ eip_status.addObserver(this);
+ mEIPReceiver = new EIPReceiver(new Handler());
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ view = inflater.inflate(R.layout.eip_service_fragment, container, false);
+ ButterKnife.inject(this, view);
+
+ if (eip_status.isConnecting())
+ eip_switch.setVisibility(View.VISIBLE);
+
+ Log.d(TAG, "onCreateView, eip_switch is checked? " + eip_switch.isChecked());
+
+ Bundle arguments = getArguments();
+ if(arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT))
+ startEipFromScratch();
+
+ if (savedInstanceState != null) {
+ status_message.setText(savedInstanceState.getString(STATUS_MESSAGE));
+ if(savedInstanceState.getBoolean(IS_PENDING))
+ eip_status.setConnecting();
+ else if(savedInstanceState.getBoolean(IS_CONNECTED)) {
+ eip_status.setConnectedOrDisconnected();
+ }
+ }
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY);
+ handleNewState(eip_status);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putBoolean(IS_PENDING, eip_status.isConnecting());
+ outState.putBoolean(IS_CONNECTED, eip_status.isConnected());
+ Log.d(TAG, "status message onSaveInstanceState = " + status_message.getText().toString());
+ outState.putString(STATUS_MESSAGE, status_message.getText().toString());
+ super.onSaveInstanceState(outState);
+ }
+
+ protected void saveEipStatus() {
+ boolean eip_is_on = false;
+ Log.d(TAG, "saveEipStatus");
+ if(eip_switch.isChecked()) {
+ eip_is_on = true;
+ }
+
+ if(parent_activity != null)
+ Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit();
+ }
+
+ @OnCheckedChanged(R.id.eipSwitch)
+ void handleSwitch(boolean isChecked) {
+ if(isChecked)
+ handleSwitchOn();
+ else
+ handleSwitchOff();
+
+ saveEipStatus();
+ }
+
+ private void handleSwitchOn() {
+ if(canStartEIP())
+ startEipFromScratch();
+ else if(canLogInToStartEIP()) {
+ Log.d(TAG, "Can Log In to start EIP");
+ Dashboard dashboard = (Dashboard) parent_activity;
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(IS_PENDING, true);
+ dashboard.logInDialog(bundle);
+ }
+ }
+
+ private boolean canStartEIP() {
+ boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty();
+ boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false);
+ return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting();
+ }
+
+ private boolean canLogInToStartEIP() {
+ boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false);
+ boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
+ Log.d(TAG, "Allow registered? " + isAllowedRegistered);
+ Log.d(TAG, "Is logged in? " + isLoggedIn);
+ return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected();
+ }
+
+ private void handleSwitchOff() {
+ if(eip_status.isConnecting()) {
+ askPendingStartCancellation();
+ } else if(eip_status.isConnected()) {
+ askToStopEIP();
+ }
+ }
+
+ private void askPendingStartCancellation() {
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(parent_activity);
+ alertBuilder.setTitle(parent_activity.getString(R.string.eip_cancel_connect_title))
+ .setMessage(parent_activity.getString(R.string.eip_cancel_connect_text))
+ .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ askToStopEIP();
+ }
+ })
+ .setNegativeButton(parent_activity.getString(R.string.no), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ eip_switch.setChecked(true);
+ }
+ })
+ .show();
+ }
+
+ public void startEipFromScratch() {
+ is_starting_to_connect = true;
+ progress_bar.setVisibility(View.VISIBLE);
+ eip_switch.setVisibility(View.VISIBLE);
+ String status = parent_activity.getString(R.string.eip_status_start_pending);
+ status_message.setText(status);
+
+ if(!eip_switch.isChecked()) {
+ eip_switch.setChecked(true);
+ saveEipStatus();
+ }
+ eipCommand(Constants.ACTION_START_EIP);
+ }
+
+ private void stopEIP() {
+ if(eip_status.isConnecting())
+ VoidVpnService.stop();
+ Intent disconnect_vpn = new Intent(parent_activity, DisconnectVPN.class);
+ parent_activity.startActivityForResult(disconnect_vpn, EIP.DISCONNECT);
+ eip_status.setDisconnecting();
+ }
+
+ protected void askToStopEIP() {
+ hideProgressBar();
+
+ String status = parent_activity.getString(R.string.eip_state_not_connected);
+ status_message.setText(status);
+ eipCommand(Constants.ACTION_STOP_EIP);
+ }
+
+ /**
+ * Send a command to EIP
+ *
+ * @param action A valid String constant from EIP class representing an Intent
+ * filter for the EIP class
+ */
+ private void eipCommand(String action){
+ // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
+ Intent vpn_intent = new Intent(parent_activity.getApplicationContext(), EIP.class);
+ vpn_intent.setAction(action);
+ vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver);
+ parent_activity.startService(vpn_intent);
+ }
+
+ @Override
+ public void update (Observable observable, Object data) {
+ if(observable instanceof EipStatus) {
+ eip_status = (EipStatus) observable;
+ final EipStatus eip_status = (EipStatus) observable;
+ parent_activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ handleNewState(eip_status);
+ }
+ });
+ }
+ }
+
+ private void handleNewState(EipStatus eip_status) {
+ Log.d(TAG, "handleNewState: " + eip_status.toString());
+ if(eip_status.wantsToDisconnect())
+ setDisconnectedUI();
+ else if(eip_status.isConnecting() || is_starting_to_connect)
+ setInProgressUI(eip_status);
+ else if (eip_status.isConnected())
+ setConnectedUI();
+ else if (eip_status.isDisconnected() && !eip_status.isConnecting())
+ setDisconnectedUI();
+ }
+
+ private void setConnectedUI() {
+ hideProgressBar();
+ Log.d(TAG, "setConnectedUi? " + eip_status.isConnected());
+ adjustSwitch();
+ is_starting_to_connect = false;
+ status_message.setText(parent_activity.getString(R.string.eip_state_connected));
+ }
+
+ private void setDisconnectedUI(){
+ hideProgressBar();
+ adjustSwitch();
+ status_message.setText(parent_activity.getString(R.string.eip_state_not_connected));
+ }
+
+ private void adjustSwitch() {
+ if(eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) {
+ Log.d(TAG, "adjustSwitch, isConnected || isConnecting, is checked");
+ if(!eip_switch.isChecked()) {
+ eip_switch.setChecked(true);
+ }
+ } else {
+ Log.d(TAG, "adjustSwitch, !isConnected && !isConnecting? " + eip_status.toString());
+
+ if(eip_switch.isChecked()) {
+ eip_switch.setChecked(false);
+ }
+ }
+ }
+
+ private void setInProgressUI(EipStatus eip_status) {
+ int localizedResId = eip_status.getLocalizedResId();
+ String logmessage = eip_status.getLogMessage();
+ String prefix = parent_activity.getString(localizedResId);
+
+ status_message.setText(prefix + " " + logmessage);
+ is_starting_to_connect = false;
+ adjustSwitch();
+ }
+
+ private void hideProgressBar() {
+ if(progress_bar != null)
+ progress_bar.setVisibility(View.GONE);
+ }
+
+ protected class EIPReceiver extends ResultReceiver {
+
+ protected EIPReceiver(Handler handler){
+ super(handler);
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ super.onReceiveResult(resultCode, resultData);
+
+ String request = resultData.getString(Constants.REQUEST_TAG);
+
+ if (request.equals(Constants.ACTION_START_EIP)) {
+ switch (resultCode){
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+
+ break;
+ }
+ } else if (request.equals(Constants.ACTION_STOP_EIP)) {
+ switch (resultCode){
+ case Activity.RESULT_OK:
+ stopEIP();
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ } else if (request.equals(Constants.EIP_NOTIFICATION)) {
+ switch (resultCode){
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ Dashboard dashboard = (Dashboard) parent_activity;
+
+ progress_bar.setVisibility(View.VISIBLE);
+ status_message.setText(getString(R.string.updating_certificate_message));
+ if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) {
+ dashboard.logInDialog(Bundle.EMPTY);
+ } else {
+ Intent provider_API_command = dashboard.prepareProviderAPICommand();
+ provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
+ parent_activity.startService(provider_API_command);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+
+ public static EIPReceiver getReceiver() {
+ return mEIPReceiver;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
deleted file mode 100644
index 6d223dd6..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
+++ /dev/null
@@ -1,424 +0,0 @@
-package se.leap.bitmaskclient;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.ProviderAPIResultReceiver;
-import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
-import se.leap.bitmaskclient.Dashboard;
-
-import de.blinkt.openvpn.activities.LogWindow;
-import de.blinkt.openvpn.core.VpnStatus;
-import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus.StateListener;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.CompoundButton;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.Switch;
-import android.widget.TextView;
-
-public class EipServiceFragment extends Fragment implements StateListener, OnCheckedChangeListener {
-
- protected static final String IS_EIP_PENDING = "is_eip_pending";
- public static final String START_ON_BOOT = "start on boot";
-
- private View eipFragment;
- private static Switch eipSwitch;
- private View eipDetail;
- private TextView eipStatus;
-
- private static EIPReceiver mEIPReceiver;
-
-
- public static String TAG = "se.leap.bitmask.EipServiceFragment";
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
- eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false);
- eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail));
- eipDetail.setVisibility(View.VISIBLE);
-
- View eipSettings = eipFragment.findViewById(R.id.eipSettings);
- eipSettings.setVisibility(View.GONE); // FIXME too!
-
- if (EIP.mIsStarting)
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
-
- eipStatus = (TextView) eipFragment.findViewById(R.id.eipStatus);
-
- eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch);
- eipSwitch.setOnCheckedChangeListener(this);
-
- if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT))
- startEipFromScratch();
-
- return eipFragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mEIPReceiver = new EIPReceiver(new Handler());
-
- if (savedInstanceState != null)
- EIP.mIsStarting = savedInstanceState.getBoolean(IS_EIP_PENDING);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- VpnStatus.addStateListener(this);
-
- eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY);
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- VpnStatus.removeStateListener(this);
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(IS_EIP_PENDING, EIP.mIsStarting);
- }
-
- protected void saveEipStatus() {
- boolean eip_is_on = false;
- Log.d("bitmask", "saveEipStatus");
- if(eipSwitch.isChecked()) {
- eip_is_on = true;
- }
-
- if(getActivity() != null)
- Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit();
- }
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (buttonView.equals(eipSwitch)){
- handleSwitch(isChecked);
- }
- }
-
- private void handleSwitch(boolean isChecked) {
- if(isChecked)
- handleSwitchOn();
- else
- handleSwitchOff();
-
- saveEipStatus();
- }
-
- private void handleSwitchOn() {
- if(canStartEIP())
- startEipFromScratch();
- else if(canLogInToStartEIP()) {
- Log.d(TAG, "Can Log In to start EIP");
- Dashboard dashboard = (Dashboard) getActivity();
- dashboard.logInDialog(Bundle.EMPTY);
- }
- }
-
- private boolean canStartEIP() {
- boolean certificateExists = !Dashboard.preferences.getString(EIP.CERTIFICATE, "").isEmpty();
- boolean isAllowedAnon = Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false);
- return (isAllowedAnon || certificateExists) && !EIP.mIsStarting && !EIP.isConnected();
- }
-
- private boolean canLogInToStartEIP() {
- boolean isAllowedRegistered = Dashboard.preferences.getBoolean(EIP.ALLOWED_REGISTERED, false);
- boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
- Log.d(TAG, "Allow registered? " + isAllowedRegistered);
- Log.d(TAG, "Is logged in? " + isLoggedIn);
- return isAllowedRegistered && !isLoggedIn && !EIP.mIsStarting && !EIP.isConnected();
- }
-
- private void handleSwitchOff() {
- if(EIP.mIsStarting) {
- askPendingStartCancellation();
- } else if(EIP.isConnected()) {
- Log.d(TAG, "Stopping EIP");
- stopEIP();
- }
- }
-
- private void askPendingStartCancellation() {
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
- alertBuilder.setTitle(getResources().getString(R.string.eip_cancel_connect_title))
- .setMessage(getResources().getString(R.string.eip_cancel_connect_text))
- .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- stopEIP();
- }
- })
- .setNegativeButton(getResources().getString(R.string.no), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Log.d(TAG, "askPendingStartCancellation checks the switch to true");
- eipSwitch.setChecked(true);
- }
- })
- .show();
- }
-
- public void startEipFromScratch() {
- EIP.mIsStarting = true;
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
- String status = getResources().getString(R.string.eip_status_start_pending);
- setEipStatus(status);
-
- if(!eipSwitch.isChecked()) {
- Log.d(TAG, "startEipFromScratch checks the switch to true");
- eipSwitch.setChecked(true);
- saveEipStatus();
- }
- eipCommand(EIP.ACTION_START_EIP);
- }
-
- protected void stopEIP() {
- EIP.mIsStarting = false;
- View eipProgressBar = getActivity().findViewById(R.id.eipProgress);
- if(eipProgressBar != null)
- eipProgressBar.setVisibility(View.GONE);
-
- String status = getResources().getString(R.string.eip_state_not_connected);
- setEipStatus(status);
- eipCommand(EIP.ACTION_STOP_EIP);
- }
-
- /**
- * Send a command to EIP
- *
- * @param action A valid String constant from EIP class representing an Intent
- * filter for the EIP class
- */
- private void eipCommand(String action){
- // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent vpn_intent = new Intent(getActivity().getApplicationContext(), EIP.class);
- vpn_intent.setAction(action);
- vpn_intent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver);
- getActivity().startService(vpn_intent);
- }
-
- @Override
- public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- boolean isNewLevel = EIP.lastConnectionStatusLevel != level;
- boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == ConnectionStatus.UNKNOWN_LEVEL;
- Log.d(TAG, "update state with level " + level);
- if(!justDecidedOnDisconnect && (isNewLevel || level == ConnectionStatus.LEVEL_CONNECTED)) {
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- EIP.lastConnectionStatusLevel = level;
- handleNewState(state, logmessage, localizedResId, level);
- }
- });
- } else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) {
- EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
- updateState(state, logmessage, localizedResId, level);
- } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED)
- // handleNewState(state, logmessage, localizedResId, level);
- }
-
- private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- if (level == ConnectionStatus.LEVEL_CONNECTED)
- setConnectedUI();
- else if (isDisconnectedLevel(level) && !EIP.mIsStarting)
- setDisconnectedUI();
- else if (level == ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET)
- setNoServerReplyUI(localizedResId, logmessage);
- else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED)
- setServerReplyUI(state, localizedResId, logmessage);
- // else if (level == ConnectionStatus.LEVEL_AUTH_FAILED)
- // handleSwitchOn();
- }
-
- private boolean isDisconnectedLevel(final ConnectionStatus level) {
- return level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED;
- }
-
- private void setConnectedUI() {
- hideProgressBar();
- Log.d(TAG, "mIsDisconnecting = false in setConnectedUI");
- EIP.mIsStarting = false; //TODO This should be done in the onReceiveResult from START_EIP command, but right now LaunchVPN isn't notifying anybody the resultcode of the request so we need to listen the states with this listener.
- EIP.mIsDisconnecting = false; //TODO See comment above
- String status = getString(R.string.eip_state_connected);
- setEipStatus(status);
- adjustSwitch();
- }
-
- private void setDisconnectedUI(){
- hideProgressBar();
- EIP.mIsStarting = false; //TODO See comment in setConnectedUI()
- Log.d(TAG, "mIsDisconnecting = false in setDisconnectedUI");
- EIP.mIsDisconnecting = false; //TODO See comment in setConnectedUI()
-
- String status = getString(R.string.eip_state_not_connected);
- setEipStatus(status);
- adjustSwitch();
- }
-
- private void adjustSwitch() {
- if(EIP.isConnected()) {
- if(!eipSwitch.isChecked()) {
- eipSwitch.setChecked(true);
- }
- } else {
- if(eipSwitch.isChecked()) {
- eipSwitch.setChecked(false);
- }
- }
- }
-
- private void setNoServerReplyUI(int localizedResId, String logmessage) {
- if(eipStatus != null) {
- String prefix = getString(localizedResId);
- setEipStatus(prefix + " " + logmessage);
- }
- }
-
- private void setServerReplyUI(String state, int localizedResId, String logmessage) {
- if(eipStatus != null)
- if(state.equals("AUTH") || state.equals("GET_CONFIG")) {
- String prefix = getString(localizedResId);
- setEipStatus(prefix + " " + logmessage);
- }
- }
-
- protected void setEipStatus(String status) {
- if(eipStatus == null)
- eipStatus = (TextView) getActivity().findViewById(R.id.eipStatus);
- eipStatus.setText(status);
- }
-
- private void hideProgressBar() {
- if(getActivity() != null && getActivity().findViewById(R.id.eipProgress) != null)
- getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
- }
-
- /**
- * Inner class for handling messages related to EIP status and control requests
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
- protected class EIPReceiver extends ResultReceiver {
-
- protected EIPReceiver(Handler handler){
- super(handler);
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- super.onReceiveResult(resultCode, resultData);
-
- String request = resultData.getString(EIP.REQUEST_TAG);
- boolean checked = false;
-
- if (request == EIP.ACTION_IS_EIP_RUNNING) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = true;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- break;
- }
- } else if (request == EIP.ACTION_START_EIP) {
- switch (resultCode){
- case Activity.RESULT_OK:
- Log.d(TAG, "Action start eip = Result OK");
- checked = true;
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
- EIP.mIsStarting = false;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE);
- break;
- }
- } else if (request == EIP.ACTION_STOP_EIP) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = false;
- break;
- case Activity.RESULT_CANCELED:
- checked = true;
- break;
- }
- } else if (request == EIP.EIP_NOTIFICATION) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = true;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- break;
- }
- } else if (request == EIP.ACTION_CHECK_CERT_VALIDITY) {
- checked = eipSwitch.isChecked();
-
- switch (resultCode) {
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- Dashboard dashboard = (Dashboard) getActivity();
-
- dashboard.showProgressBar();
- String status = getResources().getString(R.string.updating_certificate_message);
- setEipStatus(status);
-
- if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false)) {
- dashboard.logInDialog(Bundle.EMPTY);
- } else {
-
- Intent provider_API_command = new Intent(getActivity(), ProviderAPI.class);
- if (dashboard.providerAPI_result_receiver == null) {
- dashboard.providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- dashboard.providerAPI_result_receiver.setReceiver(dashboard);
- }
-
- provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, dashboard.providerAPI_result_receiver);
- getActivity().startService(provider_API_command);
- }
- break;
- }
- }
- }
- }
-
-
- public static EIPReceiver getReceiver() {
- return mEIPReceiver;
- }
-
- public static boolean isEipSwitchChecked() {
- return eipSwitch.isChecked();
- }
-
- public void checkEipSwitch(boolean checked) {
- eipSwitch.setChecked(checked);
- // Log.d(TAG, "checkEipSwitch");
- // onCheckedChanged(eipSwitch, checked);
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
index c4844be9..49af9274 100644
--- a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
+++ b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
@@ -45,6 +45,10 @@ public class FragmentManagerEnhanced {
transaction.replace(containerViewId, fragment, tag).commit();
}
+ public FragmentTransaction beginTransaction() {
+ return generic_fragment_manager.beginTransaction();
+ }
+
public Fragment findFragmentByTag(String tag) {
return generic_fragment_manager.findFragmentByTag(tag);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
index a953a710..989dc395 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
@@ -17,13 +17,14 @@
package se.leap.bitmaskclient;
+import org.jboss.security.srp.SRPParameters;
+
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
-import org.jboss.security.srp.SRPParameters;
/**
* Implements all SRP algorithm logic.
diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
index eb196d46..07ed6c8f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
@@ -3,8 +3,8 @@ package se.leap.bitmaskclient;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.util.Log;
+import se.leap.bitmaskclient.eip.Constants;
public class OnBootReceiver extends BroadcastReceiver {
@@ -14,7 +14,7 @@ public class OnBootReceiver extends BroadcastReceiver {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
if (!context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getString(Provider.KEY, "").isEmpty() && context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getBoolean(Dashboard.START_ON_BOOT, false)) {
Intent dashboard_intent = new Intent(context, Dashboard.class);
- dashboard_intent.setAction(EIP.ACTION_START_EIP);
+ dashboard_intent.setAction(Constants.ACTION_START_EIP);
dashboard_intent.putExtra(Dashboard.ON_BOOT, true);
dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(dashboard_intent);
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 8d6385e0..d7ff6633 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -16,32 +16,32 @@
*/
package se.leap.bitmaskclient;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Locale;
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Parcel;
+import android.os.Parcelable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import android.content.Context;
-import android.app.Activity;
-import android.content.SharedPreferences;
+import java.io.File;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Locale;
/**
* @author Sean Leonard <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
*
*/
-public final class Provider implements Serializable {
+public final class Provider implements Parcelable {
- private static final long serialVersionUID = 6003835972151761353L;
-
- private static Provider instance = null;
-
- // We'll access our preferences here
- private static SharedPreferences preferences = null;
- // Represents our Provider's provider.json
- private static JSONObject definition = null;
+ private JSONObject definition; // Represents our Provider's provider.json
+ private URL main_url;
final public static String
API_URL = "api_uri",
@@ -69,71 +69,64 @@ public final class Provider implements Serializable {
private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
protected static final String[] API_EIP_TYPES = {"openvpn"};
- private static final String PREFS_EIP_NAME = null;
+ public Provider(URL main_url) {
+ this.main_url = main_url;
+ }
+ public Provider(File provider_file) {
-
- // What, no individual fields?! We're going to gamble on org.json.JSONObject and JSONArray
- // Supporting multiple API versions will probably break this paradigm,
- // Forcing me to write a real constructor and rewrite getters/setters
- // Also will refactor if i'm instantiating the same local variables all the time
-
- /**
- *
- */
- private Provider() {}
-
- protected static Provider getInstance(){
- if(instance==null){
- instance = new Provider();
- }
- return instance;
- }
+ }
+ public static final Parcelable.Creator<Provider> CREATOR
+ = new Parcelable.Creator<Provider>() {
+ public Provider createFromParcel(Parcel in) {
+ return new Provider(in);
+ }
- protected void init(Activity activity) {
-
- // Load our preferences from SharedPreferences
- // If there's nothing there, we will end up returning a rather empty object
- // to whoever called getInstance() and they can run the First Run Wizard
- //preferences = context.getgetPreferences(0); // 0 == MODE_PRIVATE, but we don't extend Android's classes...
-
- // Load SharedPreferences
- preferences = activity.getSharedPreferences(Dashboard.SHARED_PREFERENCES,Context.MODE_PRIVATE);
- // Inflate our provider.json data
- try {
- definition = new JSONObject( preferences.getString(Provider.KEY, "") );
- } catch (JSONException e) {
- // TODO: handle exception
-
- // FIXME!! We want "real" data!!
- }
- }
+ public Provider[] newArray(int size) {
+ return new Provider[size];
+ }
+ };
+
+ private Provider(Parcel in) {
+ try {
+ main_url = new URL(in.readString());
+ String definition_string = in.readString();
+ if(definition_string != null)
+ definition = new JSONObject((definition_string));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void define(JSONObject provider_json) {
+ definition = provider_json;
+ }
+
+ protected JSONObject definition() { return definition; }
protected String getDomain(){
- String domain = "Null";
- try {
- domain = definition.getString(API_TERM_DOMAIN);
- } catch (JSONException e) {
- domain = "Null";
- e.printStackTrace();
- }
- return domain;
+ return main_url.getHost();
}
+
+ protected URL mainUrl() {
+ return main_url;
+ }
protected String getName(){
// Should we pass the locale in, or query the system here?
String lang = Locale.getDefault().getLanguage();
- String name = "Null"; // Should it actually /be/ null, for error conditions?
+ String name = "";
try {
- name = definition.getJSONObject(API_TERM_NAME).getString(lang);
+ if(definition != null)
+ name = definition.getJSONObject(API_TERM_NAME).getString(lang);
+ else throw new JSONException("Provider not defined");
} catch (JSONException e) {
- // TODO: Nesting try/catch blocks? Crazy
- // Maybe you should actually handle exception?
- try {
- name = definition.getJSONObject(API_TERM_NAME).getString( definition.getString(API_TERM_DEFAULT_LANGUAGE) );
- } catch (JSONException e2) {
- // TODO: Will you handle the exception already?
- }
+ if(main_url != null) {
+ String host = main_url.getHost();
+ name = host.substring(0, host.indexOf("."));
+ }
}
return name;
@@ -157,58 +150,60 @@ public final class Provider implements Serializable {
}
protected boolean hasEIP() {
- JSONArray services = null;
try {
- services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"]
+ JSONArray services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"]
+ for (int i=0;i<API_EIP_TYPES.length+1;i++){
+ try {
+ // Walk the EIP types array looking for matches in provider's service definitions
+ if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) )
+ return true;
+ } catch (NullPointerException e){
+ e.printStackTrace();
+ return false;
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return false;
+ }
+ }
} catch (Exception e) {
// TODO: handle exception
}
- for (int i=0;i<API_EIP_TYPES.length+1;i++){
- try {
- // Walk the EIP types array looking for matches in provider's service definitions
- if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) )
- return true;
- } catch (NullPointerException e){
- e.printStackTrace();
- return false;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- }
return false;
}
-
- protected String getEIPType() {
- // FIXME!!!!! We won't always be providing /only/ OpenVPN, will we?
- // This will have to hook into some saved choice of EIP transport
- if ( instance.hasEIP() )
- return "OpenVPN";
- else
- return null;
- }
-
- protected JSONObject getEIP() {
- // FIXME!!!!! We won't always be providing /only/ OpenVPN, will we?
- // This will have to hook into some saved choice of EIP transport, cluster, gateway
- // with possible "choose at random" preference
- if ( instance.hasEIP() ){
- // TODO Might need an EIP class, but we've only got OpenVPN type right now,
- // and only one gateway for our only provider...
- // TODO We'll try to load from preferences, have to call ProviderAPI if we've got nothin...
- JSONObject eipObject = null;
- try {
- eipObject = new JSONObject( preferences.getString(PREFS_EIP_NAME, "") );
- } catch (JSONException e) {
- // TODO ConfigHelper.rescueJSON()
- // Still nothing?
- // TODO ProviderAPI.getEIP()
- e.printStackTrace();
- }
-
- return eipObject;
- } else
- return null;
- }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(main_url.toString());
+ if(definition != null)
+ parcel.writeString(definition.toString());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if(o instanceof Provider) {
+ Provider p = (Provider) o;
+ return p.mainUrl().getHost().equals(mainUrl().getHost());
+ } else return false;
+ }
+
+ public JSONObject toJson() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put(Provider.MAIN_URL, main_url);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ @Override
+ public int hashCode() {
+ return mainUrl().getHost().hashCode();
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
index 43bba085..c63e2edb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
@@ -1,7 +1,5 @@
package se.leap.bitmaskclient;
-import java.util.List;
-
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@@ -9,7 +7,15 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TwoLineListItem;
-public class ProviderListAdapter<T> extends ArrayAdapter<T> {
+import com.pedrogomez.renderers.AdapteeCollection;
+import com.pedrogomez.renderers.RendererAdapter;
+import com.pedrogomez.renderers.RendererBuilder;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public class ProviderListAdapter extends RendererAdapter<Provider> {
private static boolean[] hidden = null;
public void hide(int position) {
@@ -23,10 +29,23 @@ public class ProviderListAdapter<T> extends ArrayAdapter<T> {
notifyDataSetChanged();
notifyDataSetInvalidated();
}
+
+ public void showAllProviders() {
+ for(int i = 0; i < hidden.length; i++)
+ hidden[i] = false;
+ notifyDataSetChanged();
+ notifyDataSetInvalidated();
+ }
- public void unHideAll() {
- for (int provider_index = 0; provider_index < hidden.length; provider_index++)
- hidden[provider_index] = false;
+ public void hideAllBut(int position) {
+ for (int i = 0; i < hidden.length; i++) {
+ if (i != position)
+ hidden[i] = true;
+ else
+ hidden[i] = false;
+ }
+ notifyDataSetChanged();
+ notifyDataSetInvalidated();
}
private int getRealPosition(int position) {
@@ -60,55 +79,52 @@ public class ProviderListAdapter<T> extends ArrayAdapter<T> {
return (hidden.length - getHiddenCount());
}
- public ProviderListAdapter(Context mContext, int layout, List<T> objects) {
- super(mContext, layout, objects);
- if(hidden == null) {
- hidden = new boolean[objects.size()];
- for (int i = 0; i < objects.size(); i++)
- hidden[i] = false;
- }
- }
-
- public ProviderListAdapter(Context mContext, int layout, List<T> objects, boolean show_all_providers) {
- super(mContext, layout, objects);
- if(show_all_providers) {
- hidden = new boolean[objects.size()];
- for (int i = 0; i < objects.size(); i++)
- hidden[i] = false;
- }
- }
+ public ProviderListAdapter(LayoutInflater layoutInflater, RendererBuilder rendererBuilder,
+ AdapteeCollection<Provider> collection) {
+ super(layoutInflater, rendererBuilder, collection);
+ hidden = new boolean[collection.size()];
+ for (int i = 0; i < collection.size(); i++)
+ hidden[i] = false;
+ }
@Override
- public void add(T item) {
+ public void add(Provider item) {
super.add(item);
- boolean[] new_hidden = new boolean[hidden.length+1];
- System.arraycopy(hidden, 0, new_hidden, 0, hidden.length);
- new_hidden[hidden.length] = false;
- hidden = new_hidden;
+ if(getCollection().size() > hidden.length) {
+ boolean[] new_hidden = new boolean[hidden.length + 1];
+ System.arraycopy(hidden, 0, new_hidden, 0, hidden.length);
+ new_hidden[hidden.length] = false;
+ hidden = new_hidden;
+ }
}
@Override
- public void remove(T item) {
+ public void remove(Provider item) {
super.remove(item);
boolean[] new_hidden = new boolean[hidden.length-1];
System.arraycopy(hidden, 0, new_hidden, 0, hidden.length-1);
hidden = new_hidden;
}
- @Override
- public View getView(int index, View convertView, ViewGroup parent) {
- TwoLineListItem row;
- int position = getRealPosition(index);
- if (convertView == null) {
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- row = (TwoLineListItem)inflater.inflate(R.layout.provider_list_item, null);
- } else {
- row = (TwoLineListItem)convertView;
- }
- ProviderListContent.ProviderItem data = ProviderListContent.ITEMS.get(position);
- row.getText1().setText(data.domain());
- row.getText2().setText(data.name());
+ protected int indexOf(Provider item) {
+ int index = 0;
+ ProviderManager provider_manager = (ProviderManager) getCollection();
+ Set<Provider> providers = provider_manager.providers();
+ for (Provider provider : providers) {
+ if (provider.equals(item)) {
+ break;
+ } else index++;
+ }
+ return index;
+ }
- return row;
- }
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ return super.getView(getRealPosition(position), convertView, parent);
+ }
+
+ public void saveProviders() {
+ ProviderManager provider_manager = (ProviderManager) getCollection();
+ provider_manager.saveCustomProvidersToFile();
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java
deleted file mode 100644
index db414d87..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.bitmaskclient;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import android.app.Activity;
-import android.app.ListFragment;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-
-/**
- * A list fragment representing a list of Providers. This fragment
- * also supports tablet devices by allowing list items to be given an
- * 'activated' state upon selection. This helps indicate which item is
- * currently being viewed in a {@link DashboardFragment}.
- * <p>
- * Activities containing this fragment MUST implement the {@link Callbacks}
- * interface.
- */
-public class ProviderListFragment extends ListFragment {
-
- public static String TAG = "provider_list_fragment";
- public static String SHOW_ALL_PROVIDERS = "show_all_providers";
- public static String TOP_PADDING = "top padding from providerlistfragment";
- private ProviderListAdapter<ProviderItem> content_adapter;
-
- /**
- * The serialization (saved instance state) Bundle key representing the
- * activated item position. Only used on tablets.
- */
- private static final String STATE_ACTIVATED_POSITION = "activated_position";
-
- /**
- * The fragment's current callback object, which is notified of list item
- * clicks.
- */
- private Callbacks mCallbacks = sDummyCallbacks;
-
- /**
- * The current activated item position. Only used on tablets.
- */
- private int mActivatedPosition = ListView.INVALID_POSITION;
-
- /**
- * A callback interface that all activities containing this fragment must
- * implement. This mechanism allows activities to be notified of item
- * selections.
- */
- public interface Callbacks {
- /**
- * Callback for when an item has been selected.
- */
- public void onItemSelected(String id);
- }
-
- /**
- * A dummy implementation of the {@link Callbacks} interface that does
- * nothing. Used only when this fragment is not attached to an activity.
- */
- private static Callbacks sDummyCallbacks = new Callbacks() {
- @Override
- public void onItemSelected(String id) {
- }
- };
-
- /**
- * Mandatory empty constructor for the fragment manager to instantiate the
- * fragment (e.g. upon screen orientation changes).
- */
- public ProviderListFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if(getArguments().containsKey(SHOW_ALL_PROVIDERS))
- content_adapter = new ProviderListAdapter<ProviderListContent.ProviderItem>(
- getActivity(),
- R.layout.provider_list_item,
- ProviderListContent.ITEMS, getArguments().getBoolean(SHOW_ALL_PROVIDERS));
- else
- content_adapter = new ProviderListAdapter<ProviderListContent.ProviderItem>(
- getActivity(),
- R.layout.provider_list_item,
- ProviderListContent.ITEMS);
-
-
- setListAdapter(content_adapter);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- return inflater.inflate(R.layout.provider_list_fragment, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // Restore the previously serialized activated item position.
- if (savedInstanceState != null
- && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
- setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
- }
- if(getArguments() != null && getArguments().containsKey(TOP_PADDING)) {
- int topPadding = getArguments().getInt(TOP_PADDING);
- View current_view = getView();
- getView().setPadding(current_view.getPaddingLeft(), topPadding, current_view.getPaddingRight(), current_view.getPaddingBottom());
- }
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
-
- // Activities containing this fragment must implement its callbacks.
- if (!(activity instanceof Callbacks)) {
- throw new IllegalStateException("Activity must implement fragment's callbacks.");
- }
-
- mCallbacks = (Callbacks) activity;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
-
- // Reset the active callbacks interface to the dummy implementation.
- mCallbacks = sDummyCallbacks;
- }
-
- @Override
- public void onListItemClick(ListView listView, View view, int position, long id) {
- super.onListItemClick(listView, view, position, id);
-
- // Notify the active callbacks interface (the activity, if the
- // fragment is attached to one) that an item has been selected.
- mCallbacks.onItemSelected(ProviderListContent.ITEMS.get(position).name());
-
- for(int item_position = 0; item_position < listView.getCount(); item_position++) {
- if(item_position != position)
- content_adapter.hide(item_position);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mActivatedPosition != ListView.INVALID_POSITION) {
- // Serialize and persist the activated item position.
- outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
- }
- }
-
- public void notifyAdapter() {
- content_adapter.notifyDataSetChanged();
- }
- /**
- * Turns on activate-on-click mode. When this mode is on, list items will be
- * given the 'activated' state when touched.
- */
- public void setActivateOnItemClick(boolean activateOnItemClick) {
- // When setting CHOICE_MODE_SINGLE, ListView will automatically
- // give items the 'activated' state when touched.
- getListView().setChoiceMode(activateOnItemClick
- ? ListView.CHOICE_MODE_SINGLE
- : ListView.CHOICE_MODE_NONE);
- }
-
- private void setActivatedPosition(int position) {
- if (position == ListView.INVALID_POSITION) {
- getListView().setItemChecked(mActivatedPosition, false);
- } else {
- getListView().setItemChecked(position, true);
- }
-
- mActivatedPosition = position;
- }
-
- public void removeLastItem() {
- unhideAll();
- content_adapter.remove(content_adapter.getItem(content_adapter.getCount()-1));
- content_adapter.notifyDataSetChanged();
- }
-
- public void addItem(ProviderItem provider) {
- content_adapter.add(provider);
- content_adapter.notifyDataSetChanged();
- }
-
- public void hideAllBut(int position) {
- int real_count = content_adapter.getCount();
- for(int i = 0; i < real_count;)
- if(i != position) {
- content_adapter.hide(i);
- position--;
- real_count--;
- } else {
- i++;
- }
- }
-
- public void unhideAll() {
- if(content_adapter != null) {
- content_adapter.unHideAll();
- content_adapter.notifyDataSetChanged();
- }
- }
-
- /**
- * @return a new instance of this ListFragment.
- */
- public static ProviderListFragment newInstance() {
- return new ProviderListFragment();
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
new file mode 100644
index 00000000..69bd7c1e
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
@@ -0,0 +1,179 @@
+package se.leap.bitmaskclient;
+
+import android.content.res.AssetManager;
+
+import com.pedrogomez.renderers.AdapteeCollection;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Created by parmegv on 4/12/14.
+ */
+public class ProviderManager implements AdapteeCollection<Provider> {
+
+ private AssetManager assets_manager;
+ private File external_files_dir;
+ private Set<Provider> default_providers;
+ private Set<Provider> custom_providers;
+
+ private static ProviderManager instance;
+
+ final protected static String URLS = "urls";
+
+ public static ProviderManager getInstance(AssetManager assets_manager, File external_files_dir) {
+ if(instance == null)
+ instance = new ProviderManager(assets_manager);
+
+ instance.addCustomProviders(external_files_dir);
+ return instance;
+ }
+
+ public ProviderManager(AssetManager assets_manager) {
+ this.assets_manager = assets_manager;
+ addDefaultProviders(assets_manager);
+ }
+
+ private void addDefaultProviders(AssetManager assets_manager) {
+ try {
+ default_providers = providersFromAssets(URLS, assets_manager.list(URLS));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Set<Provider> providersFromAssets(String directory, String[] relative_file_paths) {
+ Set<Provider> providers = new HashSet<Provider>();
+ try {
+ for(String file : relative_file_paths) {
+ String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file));
+ providers.add(new Provider(new URL(main_url)));
+ }
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return providers;
+ }
+
+
+ private void addCustomProviders(File external_files_dir) {
+ this.external_files_dir = external_files_dir;
+ custom_providers = external_files_dir.isDirectory() ?
+ providersFromFiles(external_files_dir.list()) :
+ new HashSet<Provider>();
+ }
+
+ private Set<Provider> providersFromFiles(String[] files) {
+ Set<Provider> providers = new HashSet<Provider>();
+ try {
+ for(String file : files) {
+ String main_url = extractMainUrlFromInputStream(new FileInputStream(external_files_dir.getAbsolutePath() + "/" + file));
+ providers.add(new Provider(new URL(main_url)));
+ }
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ return providers;
+ }
+
+ private String extractMainUrlFromInputStream(InputStream input_stream_file_contents) {
+ String main_url = "";
+ byte[] bytes = new byte[0];
+ try {
+ bytes = new byte[input_stream_file_contents.available()];
+ if(input_stream_file_contents.read(bytes) > 0) {
+ JSONObject file_contents = new JSONObject(new String(bytes));
+ main_url = file_contents.getString(Provider.MAIN_URL);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return main_url;
+ }
+
+ public Set<Provider> providers() {
+ Set<Provider> all_providers = new HashSet<Provider>();
+ all_providers.addAll(default_providers);
+ all_providers.addAll(custom_providers);
+ return all_providers;
+ }
+
+ @Override
+ public int size() {
+ return providers().size();
+ }
+
+ @Override
+ public Provider get(int index) {
+ Iterator<Provider> iterator = providers().iterator();
+ while(iterator.hasNext() && index > 0) {
+ iterator.next();
+ index--;
+ }
+ return iterator.next();
+ }
+
+ @Override
+ public void add(Provider element) {
+ if(!default_providers.contains(element))
+ custom_providers.add(element);
+ }
+
+ @Override
+ public void remove(Provider element) {
+ custom_providers.remove(element);
+ }
+
+ @Override
+ public void addAll(Collection<Provider> elements) {
+ custom_providers.addAll(elements);
+ }
+
+ @Override
+ public void removeAll(Collection<Provider> elements) {
+ custom_providers.removeAll(elements);
+ default_providers.removeAll(elements);
+ }
+
+ @Override
+ public void clear() {
+ default_providers.clear();
+ custom_providers.clear();
+ }
+
+ protected void saveCustomProvidersToFile() {
+ try {
+ for (Provider provider : custom_providers) {
+ File provider_file = new File(external_files_dir, provider.getName() + ".json");
+ if(!provider_file.exists()) {
+ FileWriter writer = new FileWriter(provider_file);
+ writer.write(provider.toJson().toString());
+ writer.close();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
new file mode 100644
index 00000000..6e194e84
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
@@ -0,0 +1,57 @@
+package se.leap.bitmaskclient;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.pedrogomez.renderers.Renderer;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnItemClick;
+import butterknife.OnItemSelected;
+
+/**
+ * Created by parmegv on 4/12/14.
+ */
+public class ProviderRenderer extends Renderer<Provider> {
+ private final Context context;
+
+ @InjectView(R.id.provider_name)
+ TextView name;
+ @InjectView(R.id.provider_domain)
+ TextView domain;
+
+ public ProviderRenderer(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ protected View inflate(LayoutInflater inflater, ViewGroup parent) {
+ View view = inflater.inflate(R.layout.provider_list_item, parent, false);
+ ButterKnife.inject(this, view);
+ return view;
+ }
+
+ @Override
+ protected void setUpView(View rootView) {
+ /*
+ * Empty implementation substituted with the usage of ButterKnife library by Jake Wharton.
+ */
+ }
+
+ @Override
+ protected void hookListeners(View rootView) {
+ //Empty
+ }
+
+ @Override
+ public void render() {
+ Provider provider = getContent();
+ name.setText(provider.getName());
+ domain.setText(provider.getDomain());
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java
new file mode 100644
index 00000000..7366e68e
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java
@@ -0,0 +1,25 @@
+package se.leap.bitmaskclient;
+
+import android.content.Context;
+
+import com.pedrogomez.renderers.Renderer;
+import com.pedrogomez.renderers.RendererBuilder;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+/**
+ * Created by parmegv on 4/12/14.
+ */
+ public class ProviderRendererBuilder extends RendererBuilder<Provider> {
+ public ProviderRendererBuilder(Collection<Renderer<Provider>> prototypes) {
+ super(prototypes);
+ }
+ @Override
+ protected Class getPrototypeClass(Provider content) {
+ return ProviderRenderer.class;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
index 5a0c9a6d..22e0f128 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
@@ -16,22 +16,19 @@
*/
package se.leap.bitmaskclient;
-import se.leap.bitmaskclient.R;
-import android.R.color;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
-import android.content.res.ColorStateList;
import android.os.Bundle;
-import android.provider.CalendarContract.Colors;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.BounceInterpolator;
import android.widget.EditText;
import android.widget.TextView;
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+
/**
* Implements the log in dialog, currently without progress dialog.
*
@@ -42,47 +39,56 @@ import android.widget.TextView;
* @author parmegv
*
*/
-public class LogInDialog extends SessionDialogInterface {
+public class SessionDialog extends DialogFragment{
- final public static String TAG = LogInDialog.class.getSimpleName();
+ final public static String TAG = SessionDialog.class.getSimpleName();
+
+ final public static String USERNAME = "username";
+ final public static String PASSWORD = "password";
+ final public static String USERNAME_MISSING = "username missing";
+ final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length";
+
+ @InjectView(R.id.user_message)
+ TextView user_message;
+ @InjectView(R.id.username_entered)
+ EditText username_field;
+ @InjectView(R.id.password_entered)
+ EditText password_field;
+
+ private static SessionDialog dialog;
private static boolean is_eip_pending = false;
public AlertDialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
- View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null);
+ View view = inflater.inflate(R.layout.session_dialog, null);
+ ButterKnife.inject(this, view);
- final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message);
- if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) {
- user_message.setText(getArguments().getString(getResources().getString(R.string.user_message)));
- } else {
- user_message.setVisibility(View.GONE);
- }
-
- final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered);
- if(getArguments() != null && getArguments().containsKey(USERNAME)) {
- String username = getArguments().getString(USERNAME);
- username_field.setText(username);
- }
- if (getArguments() != null && getArguments().containsKey(USERNAME_MISSING)) {
- username_field.setError(getResources().getString(R.string.username_ask));
- }
-
- final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered);
if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) {
password_field.requestFocus();
}
- if (getArguments() != null && getArguments().containsKey(PASSWORD_INVALID_LENGTH)) {
- password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message));
- }
- if(getArguments() != null && getArguments().getBoolean(EipServiceFragment.IS_EIP_PENDING, false)) {
- is_eip_pending = true;
+
+ Bundle arguments = getArguments();
+ if (arguments != null) {
+ is_eip_pending = arguments.getBoolean(EipFragment.IS_PENDING, false);
+ if (arguments.containsKey(PASSWORD_INVALID_LENGTH))
+ password_field.setError(getString(R.string.error_not_valid_password_user_message));
+ if (arguments.containsKey(USERNAME)) {
+ String username = arguments.getString(USERNAME);
+ username_field.setText(username);
}
-
+ if (arguments.containsKey(USERNAME_MISSING)) {
+ username_field.setError(getString(R.string.username_ask));
+ }
+ if(arguments.containsKey(getString(R.string.user_message)))
+ user_message.setText(arguments.getString(getString(R.string.user_message)));
+ else
+ user_message.setVisibility(View.GONE);
+ }
- builder.setView(log_in_dialog_view)
+ builder.setView(view)
.setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String username = username_field.getText().toString();
@@ -107,35 +113,37 @@ public class LogInDialog extends SessionDialogInterface {
return builder.create();
}
+
/**
- * Interface used to communicate LogInDialog with Dashboard.
+ * Interface used to communicate SessionDialog with Dashboard.
*
* @author parmegv
*
*/
- public interface LogInDialogInterface {
+ public interface SessionDialogInterface {
public void logIn(String username, String password);
- public void cancelAuthedEipOn();
public void signUp(String username, String password);
public void cancelLoginOrSignup();
}
- LogInDialogInterface interface_with_Dashboard;
+ SessionDialogInterface interface_with_Dashboard;
/**
* @return a new instance of this DialogFragment.
*/
public static DialogFragment newInstance() {
- LogInDialog dialog_fragment = new LogInDialog();
- return dialog_fragment;
+ if(dialog == null)
+ dialog = new SessionDialog();
+
+ return dialog;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- interface_with_Dashboard = (LogInDialogInterface) activity;
+ interface_with_Dashboard = (SessionDialogInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement LogInDialogListener");
@@ -146,6 +154,6 @@ public class LogInDialog extends SessionDialogInterface {
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
if(is_eip_pending)
- interface_with_Dashboard.cancelAuthedEipOn();
+ interface_with_Dashboard.cancelLoginOrSignup();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java
deleted file mode 100644
index 7b08a4d1..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package se.leap.bitmaskclient;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-
-/**
- * @author parmegv
- */
-public abstract class SessionDialogInterface extends DialogFragment {
- final public static String USERNAME = "username";
- final public static String PASSWORD = "password";
- final public static String USERNAME_MISSING = "username missing";
- final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length";
-
- @Override
- public void onAttach(Activity activity) { super.onAttach(activity); }
-
- @Override
- public void onCancel(DialogInterface dialog) { super.onCancel(dialog); }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
deleted file mode 100644
index 3cb41f4f..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.bitmaskclient;
-
-import se.leap.bitmaskclient.R;
-import android.R.color;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.content.res.ColorStateList;
-import android.os.Bundle;
-import android.provider.CalendarContract.Colors;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.BounceInterpolator;
-import android.widget.EditText;
-import android.widget.TextView;
-
-/**
- * Implements the sign up dialog, currently without progress dialog.
- *
- * It returns to the previous fragment when finished, and sends username and password to the registration method.
- *
- * It also notifies the user if the password is not valid.
- *
- * @author parmegv
- *
- */
-public class SignUpDialog extends SessionDialogInterface {
-
- final public static String TAG = SignUpDialog.class.getSimpleName();
-
- private static boolean is_eip_pending = false;
-
- public AlertDialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null);
-
- final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message);
- if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) {
- user_message.setText(getArguments().getString(getResources().getString(R.string.user_message)));
- } else {
- user_message.setVisibility(View.GONE);
- }
-
- final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered);
- if(getArguments() != null && getArguments().containsKey(USERNAME)) {
- String username = getArguments().getString(USERNAME);
- username_field.setText(username);
- }
- if (getArguments() != null && getArguments().containsKey(USERNAME_MISSING)) {
- username_field.setError(getResources().getString(R.string.username_ask));
- }
-
- final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered);
- if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) {
- password_field.requestFocus();
- }
- if (getArguments() != null && getArguments().containsKey(PASSWORD_INVALID_LENGTH)) {
- password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message));
- }
- if(getArguments() != null && getArguments().getBoolean(EipServiceFragment.IS_EIP_PENDING, false)) {
- is_eip_pending = true;
- }
-
-
- builder.setView(log_in_dialog_view)
- .setPositiveButton(R.string.signup_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = username_field.getText().toString();
- String password = password_field.getText().toString();
- dialog.dismiss();
- interface_with_Dashboard.signUp(username, password);
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- interface_with_Dashboard.cancelLoginOrSignup();
- }
- });
-
- return builder.create();
- }
-
- /**
- * Interface used to communicate SignUpDialog with Dashboard.
- *
- * @author parmegv
- *
- */
- public interface SignUpDialogInterface {
- public void signUp(String username, String password);
- public void cancelAuthedEipOn();
- public void cancelLoginOrSignup();
- }
-
- SignUpDialogInterface interface_with_Dashboard;
-
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance() {
- SignUpDialog dialog_fragment = new SignUpDialog();
- return dialog_fragment;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- interface_with_Dashboard = (SignUpDialogInterface) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement SignUpDialogListener");
- }
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- if(is_eip_pending)
- interface_with_Dashboard.cancelAuthedEipOn();
- super.onCancel(dialog);
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
new file mode 100644
index 00000000..12c2e015
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.eip;
+
+/**
+ *
+ * Constants for intent passing, shared preferences
+ *
+ * @author Parménides GV <parmegv@sdf.org>
+ *
+ */
+public interface Constants {
+
+ public final static String TAG = Constants.class.getSimpleName();
+
+ public final static String AUTHED_EIP = TAG + ".AUTHED_EIP";
+ public final static String ACTION_CHECK_CERT_VALIDITY = TAG + ".CHECK_CERT_VALIDITY";
+ public final static String ACTION_START_EIP = TAG + ".START_EIP";
+ public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP";
+ public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE";
+ public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING";
+ public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION";
+ public final static String ALLOWED_ANON = "allow_anonymous";
+ public final static String ALLOWED_REGISTERED = "allow_registration";
+ public final static String CERTIFICATE = "cert";
+ public final static String PRIVATE_KEY = TAG + ".PRIVATE_KEY";
+ public final static String KEY = TAG + ".KEY";
+ public final static String RECEIVER_TAG = TAG + ".RECEIVER_TAG";
+ public final static String REQUEST_TAG = TAG + ".REQUEST_TAG";
+ public final static String START_BLOCKING_VPN_PROFILE = TAG + ".START_BLOCKING_VPN_PROFILE";
+ public final static String PROVIDER_CONFIGURED = TAG + ".PROVIDER_CONFIGURED";
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
new file mode 100644
index 00000000..3d3070c8
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -0,0 +1,251 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.eip;
+
+import android.app.Activity;
+import android.app.IntentService;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import de.blinkt.openvpn.LaunchVPN;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ProfileManager;
+import se.leap.bitmaskclient.Dashboard;
+import se.leap.bitmaskclient.EipFragment;
+
+import static se.leap.bitmaskclient.eip.Constants.ACTION_CHECK_CERT_VALIDITY;
+import static se.leap.bitmaskclient.eip.Constants.ACTION_IS_EIP_RUNNING;
+import static se.leap.bitmaskclient.eip.Constants.ACTION_START_EIP;
+import static se.leap.bitmaskclient.eip.Constants.ACTION_STOP_EIP;
+import static se.leap.bitmaskclient.eip.Constants.ACTION_UPDATE_EIP_SERVICE;
+import static se.leap.bitmaskclient.eip.Constants.CERTIFICATE;
+import static se.leap.bitmaskclient.eip.Constants.KEY;
+import static se.leap.bitmaskclient.eip.Constants.RECEIVER_TAG;
+import static se.leap.bitmaskclient.eip.Constants.REQUEST_TAG;
+
+/**
+ * EIP is the abstract base class for interacting with and managing the Encrypted
+ * Internet Proxy connection. Connections are started, stopped, and queried through
+ * this IntentService.
+ * Contains logic for parsing eip-service.json from the provider, configuring and selecting
+ * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections.
+ *
+ * @author Sean Leonard <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
+ */
+public final class EIP extends IntentService {
+
+ public final static String TAG = EIP.class.getSimpleName();
+ public final static String SERVICE_API_PATH = "config/eip-service.json";
+
+ public static final int DISCONNECT = 15;
+
+ private static Context context;
+ private static ResultReceiver mReceiver;
+ private static SharedPreferences preferences;
+
+ private static JSONObject eip_definition;
+ private static List<Gateway> gateways = new ArrayList<Gateway>();
+ private static ProfileManager profile_manager;
+ private static Gateway gateway;
+
+ public EIP(){
+ super(TAG);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ context = getApplicationContext();
+ profile_manager = ProfileManager.getInstance(context);
+
+ preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
+ refreshEipDefinition();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ String action = intent.getAction();
+ mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
+
+ if ( action.equals(ACTION_START_EIP))
+ startEIP();
+ else if (action.equals(ACTION_STOP_EIP))
+ stopEIP();
+ else if (action.equals(ACTION_IS_EIP_RUNNING))
+ isRunning();
+ else if (action.equals(ACTION_UPDATE_EIP_SERVICE))
+ updateEIPService();
+ else if (action.equals(ACTION_CHECK_CERT_VALIDITY))
+ checkCertValidity();
+ }
+
+ /**
+ * Initiates an EIP connection by selecting a gateway and preparing and sending an
+ * Intent to {@link de.blinkt.openvpn.LaunchVPN}.
+ * It also sets up early routes.
+ */
+ private void startEIP() {
+ if(gateways.isEmpty())
+ updateEIPService();
+ earlyRoutes();
+
+ GatewaySelector gateway_selector = new GatewaySelector(gateways);
+ gateway = gateway_selector.select();
+ if(gateway != null && gateway.getProfile() != null) {
+ mReceiver = EipFragment.getReceiver();
+ launchActiveGateway();
+ }
+ tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK);
+ }
+
+ /**
+ * Early routes are routes that block traffic until a new
+ * VpnService is started properly.
+ */
+ private void earlyRoutes() {
+ Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class);
+ void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(void_vpn_launcher);
+ }
+
+ private void launchActiveGateway() {
+ Intent intent = new Intent(this,LaunchVPN.class);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName());
+ intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
+ startActivity(intent);
+ }
+
+ private void stopEIP() {
+ EipStatus eip_status = EipStatus.getInstance();
+ Log.d(TAG, "stopEip(): eip is connected? " + eip_status.isConnected());
+ int result_code = Activity.RESULT_CANCELED;
+ if(eip_status.isConnected() || eip_status.isConnecting())
+ result_code = Activity.RESULT_OK;
+
+ tellToReceiver(ACTION_STOP_EIP, result_code);
+ }
+
+ /**
+ * Checks the last stored status notified by ics-openvpn
+ * Sends <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
+ * request if it's not connected, <code>Activity.RESULT_OK</code> otherwise.
+ */
+ private void isRunning() {
+ EipStatus eip_status = EipStatus.getInstance();
+ int resultCode = (eip_status.isConnected()) ?
+ Activity.RESULT_OK :
+ Activity.RESULT_CANCELED;
+ tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode);
+ }
+
+ /**
+ * Loads eip-service.json from SharedPreferences, delete previous vpn profiles and add new gateways.
+ * TODO Implement API call to refresh eip-service.json from the provider
+ */
+ private void updateEIPService() {
+ refreshEipDefinition();
+ deleteAllVpnProfiles();
+ updateGateways();
+ tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK);
+ }
+
+ private void refreshEipDefinition() {
+ try {
+ String eip_definition_string = preferences.getString(KEY, "");
+ if(!eip_definition_string.isEmpty()) {
+ eip_definition = new JSONObject(eip_definition_string);
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void deleteAllVpnProfiles() {
+ Collection<VpnProfile> profiles = profile_manager.getProfiles();
+ profiles.removeAll(profiles);
+ gateways.clear();
+ }
+
+ /**
+ * Walk the list of gateways defined in eip-service.json and parse them into
+ * Gateway objects.
+ * TODO Store the Gateways (as Serializable) in SharedPreferences
+ */
+ private void updateGateways(){
+ try {
+ if(eip_definition != null) {
+ JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways");
+ for (int i = 0; i < gatewaysDefined.length(); i++) {
+ JSONObject gw = gatewaysDefined.getJSONObject(i);
+ if (isOpenVpnGateway(gw)) {
+ addGateway(new Gateway(eip_definition, context, gw));
+ }
+ }
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private boolean isOpenVpnGateway(JSONObject gateway) {
+ try {
+ String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString();
+ return transport.contains("openvpn");
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ private void addGateway(Gateway gateway) {
+ profile_manager.addProfile(gateway.getProfile());
+ gateways.add(gateway);
+ }
+
+ private void checkCertValidity() {
+ VpnCertificateValidator validator = new VpnCertificateValidator();
+ int resultCode = validator.isValid(preferences.getString(CERTIFICATE, "")) ?
+ Activity.RESULT_OK :
+ Activity.RESULT_CANCELED;
+ tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode);
+ }
+
+ private void tellToReceiver(String action, int resultCode) {
+ if (mReceiver != null){
+ Bundle resultData = new Bundle();
+ resultData.putString(REQUEST_TAG, action);
+ mReceiver.send(resultCode, resultData);
+ }
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
new file mode 100644
index 00000000..4ac3bd6a
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.eip;
+
+import android.util.Log;
+
+import java.util.Observable;
+
+import de.blinkt.openvpn.core.VpnStatus;
+
+public class EipStatus extends Observable implements VpnStatus.StateListener {
+ public static String TAG = EipStatus.class.getSimpleName();
+ private static EipStatus current_status;
+
+ private static VpnStatus.ConnectionStatus level = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
+ private static boolean wants_to_disconnect = false;
+
+ private String state, log_message;
+ private int localized_res_id;
+
+ public static EipStatus getInstance() {
+ if(current_status == null) {
+ current_status = new EipStatus();
+ VpnStatus.addStateListener(current_status);
+ }
+ return current_status;
+ }
+
+ private EipStatus() { }
+
+ @Override
+ public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) {
+ current_status = getInstance();
+ current_status.setState(state);
+ current_status.setLogMessage(logmessage);
+ current_status.setLocalizedResId(localizedResId);
+ current_status.setLevel(level);
+ current_status.setChanged();
+ if(isConnected() || isDisconnected())
+ setConnectedOrDisconnected();
+ else if(isConnecting())
+ setConnecting();
+ Log.d(TAG, "update state with level " + level);
+ current_status.notifyObservers();
+ }
+
+ public boolean wantsToDisconnect() {
+ return wants_to_disconnect;
+ }
+
+ public boolean isConnecting() {
+ return
+ !isConnected() &&
+ !isDisconnected() &&
+ !isPaused();
+ }
+
+ public boolean isConnected() {
+ return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
+ }
+
+ public boolean isDisconnected() {
+ return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
+ }
+
+ public boolean isPaused() {
+ return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED;
+ }
+
+ public void setConnecting() {
+ wants_to_disconnect = false;
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
+
+ public void setConnectedOrDisconnected() {
+ Log.d(TAG, "setConnectedOrDisconnected()");
+ wants_to_disconnect = false;
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
+
+ public void setDisconnecting() {
+ wants_to_disconnect = false;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public String getLogMessage() {
+ return log_message;
+ }
+
+ public int getLocalizedResId() {
+ return localized_res_id;
+ }
+
+ public VpnStatus.ConnectionStatus getLevel() {
+ return level;
+ }
+
+ private void setState(String state) {
+ this.state = state;
+ }
+
+ private void setLogMessage(String log_message) {
+ this.log_message = log_message;
+ }
+
+ private void setLocalizedResId(int localized_res_id) {
+ this.localized_res_id = localized_res_id;
+ }
+
+ private void setLevel(VpnStatus.ConnectionStatus level) {
+ EipStatus.level = level;
+ }
+
+ @Override
+ public String toString() {
+ return "State: " + state + " Level: " + level.toString();
+ }
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
new file mode 100644
index 00000000..3ee9443c
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.eip;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.Iterator;
+
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ConfigParser;
+import de.blinkt.openvpn.core.ProfileManager;
+import se.leap.bitmaskclient.Dashboard;
+
+/**
+ * Gateway provides objects defining gateways and their metadata.
+ * Each instance contains a VpnProfile for OpenVPN specific data and member
+ * variables describing capabilities and location (name)
+ *
+ * @author Sean Leonard <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
+ */
+public class Gateway {
+
+ private String TAG = Gateway.class.getSimpleName();
+
+ private String mName;
+ private int timezone;
+ private JSONObject general_configuration;
+ private Context context;
+ private VpnProfile mVpnProfile;
+ private JSONObject mGateway;
+
+ /**
+ * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json
+ * and create a VpnProfile belonging to it.
+ *
+ * @param gateway The JSON OpenVPN gateway definition to parse
+ */
+ protected Gateway(JSONObject eip_definition, Context context, JSONObject gateway){
+
+ mGateway = gateway;
+
+ this.context = context;
+ general_configuration = getGeneralConfiguration(eip_definition);
+ timezone = getTimezone(eip_definition);
+ mName = locationAsName(eip_definition);
+
+ // Currently deletes VpnProfile for host, if there already is one, and builds new
+ ProfileManager vpl = ProfileManager.getInstance(context);
+ Collection<VpnProfile> profiles = vpl.getProfiles();
+ for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){
+ VpnProfile p = it.next();
+
+ if ( p.mName.equalsIgnoreCase( mName ) ) {
+ it.remove();
+ vpl.removeProfile(context, p);
+ }
+ }
+
+ mVpnProfile = createVPNProfile();
+ mVpnProfile.mName = mName;
+
+ vpl.addProfile(mVpnProfile);
+ vpl.saveProfile(context, mVpnProfile);
+ vpl.saveProfileList(context);
+ }
+
+ private JSONObject getGeneralConfiguration(JSONObject eip_definition) {
+ try {
+ return eip_definition.getJSONObject("openvpn_configuration");
+ } catch (JSONException e) {
+ return new JSONObject();
+ }
+ }
+
+ private int getTimezone(JSONObject eip_definition) {
+ JSONObject location = getLocationInfo(eip_definition);
+ return location.optInt("timezone");
+ }
+
+ private String locationAsName(JSONObject eip_definition) {
+ JSONObject location = getLocationInfo(eip_definition);
+ return location.optString("name");
+ }
+
+ private JSONObject getLocationInfo(JSONObject eip_definition) {
+ try {
+ JSONObject locations = eip_definition.getJSONObject("locations");
+
+ return locations.getJSONObject(mGateway.getString("location"));
+ } catch (JSONException e) {
+ return new JSONObject();
+ }
+ }
+
+ /**
+ * Create and attach the VpnProfile to our gateway object
+ */
+ private VpnProfile createVPNProfile(){
+ try {
+ ConfigParser cp = new ConfigParser();
+
+ SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE);
+ VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, general_configuration, mGateway);
+ String configuration = vpn_configuration_generator.generate();
+
+ cp.parseConfig(new StringReader(configuration));
+ return cp.convertProfile();
+ } catch (ConfigParser.ConfigParseError e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ Log.v(TAG,"Error creating VPNProfile");
+ e.printStackTrace();
+ return null;
+ } catch (IOException e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ Log.v(TAG,"Error creating VPNProfile");
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public VpnProfile getProfile() {
+ return mVpnProfile;
+ }
+
+ public int getTimezone() {
+ return timezone;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
new file mode 100644
index 00000000..39ae7ca6
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
@@ -0,0 +1,46 @@
+package se.leap.bitmaskclient.eip;
+
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeMap;
+
+public class GatewaySelector {
+ List<Gateway> gateways;
+
+ public GatewaySelector(List<Gateway> gateways) {
+ this.gateways = gateways;
+ }
+
+ public Gateway select() {
+ return closestGateway();
+ }
+
+ private Gateway closestGateway() {
+ TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets();
+ return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next();
+ }
+
+ private TreeMap<Integer, Set<Gateway>> calculateOffsets() {
+ TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>();
+ int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
+ for(Gateway gateway : gateways) {
+ int dist = timezoneDistance(localOffset, gateway.getTimezone());
+ Set<Gateway> set = (offsets.get(dist) != null) ?
+ offsets.get(dist) : new HashSet<Gateway>();
+ set.add(gateway);
+ offsets.put(dist, set);
+ }
+ return offsets;
+ }
+
+ private int timezoneDistance(int local_timezone, int remote_timezone) {
+ // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
+ int dist = Math.abs(local_timezone - remote_timezone);
+ // Farther than 12 timezones and it's shorter around the "back"
+ if (dist > 12)
+ dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things.
+ return dist;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java
index 3b286fbf..d79d8003 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java
@@ -1,4 +1,4 @@
-package se.leap.bitmaskclient;
+package se.leap.bitmaskclient.eip;
import android.app.Activity;
import android.content.Intent;
@@ -8,7 +8,7 @@ import android.os.Bundle;
public class VoidVpnLauncher extends Activity {
private static final int VPN_USER_PERMISSION = 71;
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -28,7 +28,7 @@ public class VoidVpnLauncher extends Activity {
if(requestCode == VPN_USER_PERMISSION) {
if(resultCode == RESULT_OK) {
Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class);
- void_vpn_service.setAction(VoidVpnService.START_BLOCKING_VPN_PROFILE);
+ void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE);
startService(void_vpn_service);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
index 7b597554..0c773208 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -1,19 +1,20 @@
-package se.leap.bitmaskclient;
+package se.leap.bitmaskclient.eip;
import android.content.Intent;
-import android.os.Process;
import android.net.VpnService;
-import android.util.Log;
+import android.os.ParcelFileDescriptor;
+
+import java.io.IOException;
public class VoidVpnService extends VpnService {
- static final String START_BLOCKING_VPN_PROFILE = "se.leap.bitmaskclient.START_BLOCKING_VPN_PROFILE";
static final String TAG = VoidVpnService.class.getSimpleName();
+ static ParcelFileDescriptor fd;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- String action = intent.getAction();
- if (action == START_BLOCKING_VPN_PROFILE) {
+ String action = intent != null ? intent.getAction() : "";
+ if (action == Constants.START_BLOCKING_VPN_PROFILE) {
new Thread(new Runnable() {
public void run() {
Builder builder = new Builder();
@@ -23,7 +24,7 @@ public class VoidVpnService extends VpnService {
builder.addRoute("192.168.1.0", 24);
builder.addDnsServer("10.42.0.1");
try {
- builder.establish();
+ fd = builder.establish();
} catch (Exception e) {
e.printStackTrace();
}
@@ -33,4 +34,20 @@ public class VoidVpnService extends VpnService {
}
return 0;
}
+
+ @Override
+ public void onRevoke() {
+ super.onRevoke();
+ }
+
+ public static boolean stop() {
+ try {
+ fd.close();
+ return true;
+ } catch (IOException | NullPointerException e) {
+ android.util.Log.d(TAG, "VoidVpnService didn't stop");
+ e.printStackTrace();
+ return false;
+ }
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java
new file mode 100644
index 00000000..6487f6c1
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.eip;
+
+import android.util.Log;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+
+import se.leap.bitmaskclient.ConfigHelper;
+
+public class VpnCertificateValidator {
+ public final static String TAG = VpnCertificateValidator.class.getSimpleName();
+
+ public boolean isValid(String certificate) {
+ if(!certificate.isEmpty()) {
+ X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate);
+ return isValid(certificate_x509);
+ } else return true;
+ }
+
+ private boolean isValid(X509Certificate certificate) {
+ Calendar offset_date = calculateOffsetCertificateValidity(certificate);
+ try {
+ Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
+ certificate.checkValidity(offset_date.getTime());
+ return true;
+ } catch(CertificateExpiredException e) {
+ return false;
+ } catch(CertificateNotYetValidException e) {
+ return false;
+ }
+ }
+
+ private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) {
+ Log.d(TAG, "certificate not after = " + certificate.getNotAfter());
+ long preventive_time = Math.abs(certificate.getNotBefore().getTime() - certificate.getNotAfter().getTime())/2;
+ long current_date_millis = Calendar.getInstance().getTimeInMillis();
+
+ Calendar limit_date = Calendar.getInstance();
+ limit_date.setTimeInMillis(current_date_millis + preventive_time);
+ return limit_date;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
index ef049a3c..0c8e9a04 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -14,18 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package se.leap.bitmaskclient;
+package se.leap.bitmaskclient.eip;
import android.content.SharedPreferences;
import android.util.Log;
-import java.util.Iterator;
-import java.util.Vector;
+
import org.json.JSONArray;
-import org.json.JSONObject;
import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Iterator;
import se.leap.bitmaskclient.Provider;
-import se.leap.bitmaskclient.EIP;
public class VpnConfigGenerator {
@@ -39,7 +39,7 @@ public class VpnConfigGenerator {
public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) {
this.general_configuration = general_configuration;
this.gateway = gateway;
- this.preferences = preferences;
+ VpnConfigGenerator.preferences = preferences;
}
public String generate() {
@@ -57,7 +57,6 @@ public class VpnConfigGenerator {
String common_options = "";
try {
Iterator keys = general_configuration.keys();
- Vector<Vector<String>> value = new Vector<Vector<String>>();
while ( keys.hasNext() ){
String key = keys.next().toString();
@@ -121,14 +120,14 @@ public class VpnConfigGenerator {
String key =
"<key>"
+ new_line
- + preferences.getString(EIP.PRIVATE_KEY, "")
+ + preferences.getString(Constants.PRIVATE_KEY, "")
+ new_line
+ "</key>";
String openvpn_cert =
"<cert>"
+ new_line
- + preferences.getString(EIP.CERTIFICATE, "")
+ + preferences.getString(Constants.CERTIFICATE, "")
+ new_line
+ "</cert>";
diff --git a/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png
new file mode 100644
index 00000000..0fd15563
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png
new file mode 100644
index 00000000..a9eac0ca
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_edit_grey600_24dp.png b/app/src/main/res/drawable-hdpi/ic_edit_grey600_24dp.png
new file mode 100644
index 00000000..b5f88c80
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_edit_grey600_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_edit_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_edit_white_24dp.png
new file mode 100644
index 00000000..730416c9
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_edit_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 00000000..30122adf
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png
new file mode 100644
index 00000000..93b3c219
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png
new file mode 100644
index 00000000..e80681ae
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png
new file mode 100644
index 00000000..e4ea52ef
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_edit_grey600_24dp.png b/app/src/main/res/drawable-mdpi/ic_edit_grey600_24dp.png
new file mode 100644
index 00000000..bae3480c
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_edit_grey600_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_edit_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_edit_white_24dp.png
new file mode 100644
index 00000000..85cff0b9
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_edit_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 00000000..49cec669
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png
new file mode 100644
index 00000000..4d019722
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png
new file mode 100644
index 00000000..76e07f09
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png
new file mode 100644
index 00000000..cdb230c2
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_edit_grey600_24dp.png b/app/src/main/res/drawable-xhdpi/ic_edit_grey600_24dp.png
new file mode 100644
index 00000000..4c95bd57
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_edit_grey600_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png
new file mode 100644
index 00000000..7f0ea51b
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 00000000..d4ca77bf
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png
new file mode 100644
index 00000000..dd536bca
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png
new file mode 100644
index 00000000..0eb9d8b0
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png
new file mode 100644
index 00000000..0e95e9b1
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_edit_grey600_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_edit_grey600_24dp.png
new file mode 100644
index 00000000..6ed4351c
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_edit_grey600_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png
new file mode 100644
index 00000000..34ec7092
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 00000000..802b3cd5
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png
new file mode 100644
index 00000000..9963c6a0
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png
new file mode 100644
index 00000000..7b2a480a
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png
new file mode 100644
index 00000000..ccf8c716
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_edit_grey600_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_edit_grey600_24dp.png
new file mode 100644
index 00000000..0c0fd76f
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_edit_grey600_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_edit_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_edit_white_24dp.png
new file mode 100644
index 00000000..9380370f
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_edit_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 00000000..511008ce
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png
new file mode 100644
index 00000000..bb521c14
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/app/src/main/res/layout-xlarge/client_dashboard.xml b/app/src/main/res/layout-xlarge/dashboard.xml
index bd644e1e..bd644e1e 100644
--- a/app/src/main/res/layout-xlarge/client_dashboard.xml
+++ b/app/src/main/res/layout-xlarge/dashboard.xml
diff --git a/app/src/main/res/layout-xlarge/eip_service_fragment.xml b/app/src/main/res/layout-xlarge/eip_service_fragment.xml
index e5c7f23d..38b6aca3 100644
--- a/app/src/main/res/layout-xlarge/eip_service_fragment.xml
+++ b/app/src/main/res/layout-xlarge/eip_service_fragment.xml
@@ -37,39 +37,20 @@
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp" />
- <RelativeLayout
- android:id="@+id/eipDetail"
- android:layout_width="match_parent"
+ <TextView
+ android:id="@+id/status_message"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
android:layout_below="@+id/eipLabel"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
- android:visibility="gone" >
-
- <ImageView
- android:id="@+id/eipSettings"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_margin="10dp"
- android:contentDescription="@string/eip_settings_button_description"
- android:src="@drawable/ic_sysbar_quicksettings" />
-
- <TextView
- android:id="@+id/eipStatus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:clickable="true"
- android:text="@string/status_unknown"
- android:textSize="16sp" />
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:clickable="true"
+ android:text="@string/eip_state_not_connected"
+ android:textSize="16sp" />
- </RelativeLayout>
</RelativeLayout>
diff --git a/app/src/main/res/layout-xlarge/provider_list_fragment.xml b/app/src/main/res/layout-xlarge/provider_list_fragment.xml
deleted file mode 100644
index 59dd37d1..00000000
--- a/app/src/main/res/layout-xlarge/provider_list_fragment.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingLeft="12dp"
- android:paddingRight="12dp"
- android:paddingTop="12dp" >
-
- <ListView
- android:id="@id/android:list"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:drawSelectorOnTop="false" />
-
-</LinearLayout>
diff --git a/app/src/main/res/layout-xlarge/log_in_dialog.xml b/app/src/main/res/layout-xlarge/session_dialog.xml
index 3a9eebb8..3a9eebb8 100644
--- a/app/src/main/res/layout-xlarge/log_in_dialog.xml
+++ b/app/src/main/res/layout-xlarge/session_dialog.xml
diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml
index ccb1ea26..2669caa3 100644
--- a/app/src/main/res/layout/about.xml
+++ b/app/src/main/res/layout/about.xml
@@ -35,6 +35,17 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all"
+ android:text="@string/copyright_blinktgui" />
+
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="10sp" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:autoLink="all"
android:text="@string/repository_url_text" />
<TextView
diff --git a/app/src/main/res/layout/configuration_wizard_activity.xml b/app/src/main/res/layout/configuration_wizard_activity.xml
index f3d0e48b..a5bca1e9 100644
--- a/app/src/main/res/layout/configuration_wizard_activity.xml
+++ b/app/src/main/res/layout/configuration_wizard_activity.xml
@@ -5,6 +5,12 @@
android:layout_height="match_parent"
tools:context=".ConfigurationWizard" >
+ <ListView
+ android:id="@+id/provider_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:drawSelectorOnTop="false" />
+
<ProgressBar
android:id="@+id/progressbar_configuration_wizard"
style="?android:attr/progressBarStyleHorizontal"
@@ -22,5 +28,4 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_centerHorizontal="true"
android:textColor="@android:color/holo_blue_bright" />
-
</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/client_dashboard.xml b/app/src/main/res/layout/dashboard.xml
index f33ac285..67a1122f 100644
--- a/app/src/main/res/layout/client_dashboard.xml
+++ b/app/src/main/res/layout/dashboard.xml
@@ -25,6 +25,7 @@
android:id="@+id/providerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textSize="28sp"
android:layout_marginLeft="10dp"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
diff --git a/app/src/main/res/layout/eip_service_fragment.xml b/app/src/main/res/layout/eip_service_fragment.xml
index 5992a873..64d22147 100644
--- a/app/src/main/res/layout/eip_service_fragment.xml
+++ b/app/src/main/res/layout/eip_service_fragment.xml
@@ -22,8 +22,8 @@
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp" />
-
- <ProgressBar
+
+ <ProgressBar
android:id="@+id/eipProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -34,38 +34,18 @@
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp" />
- <RelativeLayout
- android:id="@+id/eipDetail"
- android:layout_width="match_parent"
+ <TextView
+ android:id="@+id/status_message"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_below="@+id/eipLabel"
+ android:layout_below="@id/eipProgress"
+ android:layout_centerVertical="true"
+ android:paddingTop="5dp"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
- android:paddingTop="10dp"
- android:visibility="gone" >
-
- <ImageView
- android:id="@+id/eipSettings"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_margin="10dp"
- android:contentDescription="@string/eip_settings_button_description"
- android:src="@drawable/ic_sysbar_quicksettings" />
-
- <TextView
- android:id="@+id/eipStatus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:clickable="true"
- android:text="@string/status_unknown" />
-
- </RelativeLayout>
+ android:clickable="true"
+ android:text="@string/eip_state_not_connected" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/provider_list_fragment.xml b/app/src/main/res/layout/provider_list_fragment.xml
deleted file mode 100644
index 70dbae0d..00000000
--- a/app/src/main/res/layout/provider_list_fragment.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingLeft="8dp"
- android:paddingRight="8dp" >
-
- <ListView
- android:id="@id/android:list"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:drawSelectorOnTop="false" />
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/provider_list_item.xml b/app/src/main/res/layout/provider_list_item.xml
index 8746f6f8..68ba7e31 100644
--- a/app/src/main/res/layout/provider_list_item.xml
+++ b/app/src/main/res/layout/provider_list_item.xml
@@ -24,7 +24,7 @@
android:mode="twoLine"
>
- <TextView android:id="@android:id/text1"
+ <TextView android:id="@+id/provider_domain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
@@ -32,11 +32,11 @@
android:textAppearance="?android:attr/textAppearanceListItem"
/>
- <TextView android:id="@android:id/text2"
+ <TextView android:id="@+id/provider_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@android:id/text1"
- android:layout_alignLeft="@android:id/text1"
+ android:layout_below="@id/provider_domain"
+ android:layout_alignLeft="@id/provider_domain"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
diff --git a/app/src/main/res/layout/log_in_dialog.xml b/app/src/main/res/layout/session_dialog.xml
index c8a2f0a8..62215ae8 100644
--- a/app/src/main/res/layout/log_in_dialog.xml
+++ b/app/src/main/res/layout/session_dialog.xml
@@ -4,13 +4,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
- tools:context=".LogInDialog" >
+ tools:context=".SessionDialog" >
<TextView
android:id="@+id/user_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
+ android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
diff --git a/app/src/main/res/menu/logmenu.xml b/app/src/main/res/menu/logmenu.xml
index a1d2a7b5..52ba4b7d 100644
--- a/app/src/main/res/menu/logmenu.xml
+++ b/app/src/main/res/menu/logmenu.xml
@@ -10,33 +10,33 @@
<item
android:id="@+id/toggle_time"
android:alphabeticShortcut="t"
- android:icon="@android:drawable/ic_menu_view"
+ android:icon="@drawable/ic_menu_view"
android:showAsAction="withText|ifRoom"
android:title="@string/logview_options" />
<item
android:id="@+id/clearlog"
- android:icon="@android:drawable/ic_menu_delete"
+ android:icon="@drawable/ic_menu_delete"
android:showAsAction="ifRoom|withText"
android:title="@string/clear_log"
android:titleCondensed="@string/clear"/>
<item
android:id="@+id/send"
- android:icon="@android:drawable/ic_menu_share"
+ android:icon="@drawable/ic_menu_share"
android:showAsAction="ifRoom|withText"
android:title="@string/send_logfile"
android:titleCondensed="@string/send"/>
<item
android:id="@+id/cancel"
- android:icon="@android:drawable/ic_menu_close_clear_cancel"
+ android:icon="@drawable/ic_menu_close_clear_cancel"
android:showAsAction="ifRoom|withText"
android:title="@string/cancel_connection_long"
android:titleCondensed="@string/cancel_connection"/>
<item
android:id="@+id/edit_vpn"
android:alphabeticShortcut="e"
- android:icon="@android:drawable/ic_menu_edit"
+ android:icon="@drawable/ic_menu_edit"
android:showAsAction="withText|ifRoom"
android:title="@string/edit_vpn"
android:visible="false"/>
diff --git a/app/src/main/res/values-v21/refs.xml b/app/src/main/res/values-v21/refs.xml
new file mode 100644
index 00000000..0d5d271a
--- /dev/null
+++ b/app/src/main/res/values-v21/refs.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2014 Arne Schwabe
+ ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+ <drawable name="ic_menu_close_clear_cancel">@drawable/ic_close_white_24dp</drawable>
+ <drawable name="ic_menu_share">@drawable/ic_share_white_24dp </drawable>
+ <drawable name="ic_menu_view">@drawable/ic_filter_list_white_24dp</drawable>
+ <drawable name="ic_menu_delete">@drawable/ic_delete_white_24dp</drawable>
+ <drawable name="ic_menu_edit">@drawable/ic_edit_white_24dp</drawable>
+</resources>
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 00000000..892b6cb0
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2014 Arne Schwabe
+ ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+
+ <!-- http://www.google.de/design/spec/style/color.html#color-color-palette -->
+ <style name="appstyle" parent="android:Theme.Material.Light.DarkActionBar">
+ <item name="android:colorPrimary">@color/primary</item>
+ <item name="android:colorPrimaryDark">@color/primary_dark</item>
+ <item name="android:colorAccent">@color/accent</item>
+ </style>
+</resources>
diff --git a/app/src/main/res/values/colours.xml b/app/src/main/res/values/colours.xml
new file mode 100644
index 00000000..89fb41dd
--- /dev/null
+++ b/app/src/main/res/values/colours.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2014 Arne Schwabe
+ ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+ <!-- Indigo -->
+ <!-- OpenVPN colours #203155, #C66D0D -->
+ <color name="primary">#3F51B5</color>
+ <color name="primary_dark">#303F9F</color>
+ <color name="accent">#FFA726</color>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/refs.xml b/app/src/main/res/values/refs.xml
new file mode 100644
index 00000000..5e7f5e14
--- /dev/null
+++ b/app/src/main/res/values/refs.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2014 Arne Schwabe
+ ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+ <drawable name="ic_menu_close_clear_cancel">@android:drawable/ic_menu_close_clear_cancel</drawable>
+ <drawable name="ic_menu_share">@android:drawable/ic_menu_share </drawable>
+ <drawable name="ic_menu_save">@android:drawable/ic_menu_save</drawable>
+ <drawable name="ic_menu_view">@android:drawable/ic_menu_view</drawable>
+ <drawable name="ic_menu_delete">@android:drawable/ic_menu_delete</drawable>
+ <drawable name="ic_menu_edit">@android:drawable/ic_menu_edit</drawable>
+
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3666b39c..68e71886 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -60,7 +60,7 @@
<string name="signingup_message">Signing up</string>
<string name="logout_message">Logging out from this session.</string>
<string name="logged_out_message">Logged out.</string>
- <string name="log_out_failed_message">Didn\'t logged out.</string>
+ <string name="log_out_failed_message">Didn\'t log out.</string>
<string name="succesful_authentication_message">Authentication succeeded.</string>
<string name="authentication_failed_message">Authentication failed.</string>
<string name="registration_failed_message">Registration failed..</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 7b26a4a7..a60e29b8 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -5,6 +5,10 @@
-->
<resources>
+ <style name="appstyle" parent="android:Theme.DeviceDefault.Light">
+
+ </style>
+
<style name="item">
<item name="android:layout_width">match_parent</item>
@@ -23,7 +27,7 @@
<item name="android:paddingTop">10sp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
- <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
<!-- <item name="android:singleLine">true</item> -->
</style>
diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml
index 619a550f..82147ab5 100644
--- a/app/src/main/res/values/untranslatable.xml
+++ b/app/src/main/res/values/untranslatable.xml
@@ -2470,4 +2470,704 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
</resources> \ No newline at end of file
diff --git a/app/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java b/app/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
deleted file mode 100644
index e595106c..00000000
--- a/app/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
+++ /dev/null
@@ -1,275 +0,0 @@
-package de.blinkt.openvpn.core;
-
-import net.openvpn.ovpn3.ClientAPI_Config;
-import net.openvpn.ovpn3.ClientAPI_EvalConfig;
-import net.openvpn.ovpn3.ClientAPI_Event;
-import net.openvpn.ovpn3.ClientAPI_ExternalPKICertRequest;
-import net.openvpn.ovpn3.ClientAPI_ExternalPKISignRequest;
-import net.openvpn.ovpn3.ClientAPI_LogInfo;
-import net.openvpn.ovpn3.ClientAPI_OpenVPNClient;
-import net.openvpn.ovpn3.ClientAPI_ProvideCreds;
-import net.openvpn.ovpn3.ClientAPI_Status;
-import net.openvpn.ovpn3.ClientAPI_TransportStats;
-
-import java.lang.Override;
-
-import de.blinkt.openvpn.VpnProfile;
-
-import android.content.Context;
-
-public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable, OpenVPNManagement {
-
- static {
- /*System.loadLibrary("crypto");
- System.loadLibrary("ssl");*/
- System.loadLibrary("polarssl-dynamic");
- System.loadLibrary("ovpn3");
- }
-
- private VpnProfile mVp;
- private OpenVPNService mService;
-
- class StatusPoller implements Runnable
- {
- private long mSleeptime;
-
- boolean mStopped=false;
-
- public StatusPoller(long sleeptime) {
- mSleeptime=sleeptime;
- }
-
- public void run() {
- while(!mStopped) {
- try {
- Thread.sleep(mSleeptime);
- } catch (InterruptedException e) {
- }
- ClientAPI_TransportStats t = transport_stats();
- long in = t.getBytesIn();
- long out = t.getBytesOut();
- VpnStatus.updateByteCount(in, out);
- }
- }
-
- public void stop() {
- mStopped=true;
- }
- }
-
- @Override
- public void run() {
- String configstr = mVp.getConfigFile((Context)mService,true);
- if(!setConfig(configstr))
- return;
- setUserPW();
- VpnStatus.logInfo(copyright());
-
- StatusPoller statuspoller = new StatusPoller(5000);
- new Thread(statuspoller,"Status Poller").start();
-
- ClientAPI_Status status = connect();
- if(status.getError()) {
- VpnStatus.logError(String.format("connect() error: %s: %s",status.getStatus(),status.getMessage()));
- } else {
- VpnStatus.logInfo("OpenVPN3 thread finished");
- }
- statuspoller.stop();
- }
-
- @Override
- public boolean tun_builder_set_remote_address(String address, boolean ipv6) {
- mService.setMtu(1500);
- return true;
- }
-
- @Override
- public boolean tun_builder_set_mtu(int mtu) {
- mService.setMtu(mtu);
- return true;
- }
- @Override
- public boolean tun_builder_add_dns_server(String address, boolean ipv6) {
- mService.addDNS(address);
- return true;
- }
-
- @Override
- public boolean tun_builder_add_route(String address, int prefix_length,
- boolean ipv6) {
- if (address.equals("remote_host"))
- return false;
-
- if(ipv6)
- mService.addRoutev6(address + "/" + prefix_length,"tun");
- else
- mService.addRoute(new CIDRIP(address, prefix_length));
- return true;
- }
-
- @Override
- public boolean tun_builder_add_search_domain(String domain) {
- mService.setDomain(domain);
- return true;
- }
-
- @Override
- public int tun_builder_establish() {
- return mService.openTun().detachFd();
- }
-
- @Override
- public boolean tun_builder_set_session_name(String name) {
- VpnStatus.logInfo("We should call this session" + name);
- return true;
- }
-
-
-
- @Override
- public boolean tun_builder_add_address(String address, int prefix_length,
- boolean ipv6) {
- if(!ipv6)
- mService.setLocalIP(new CIDRIP(address, prefix_length));
- else
- mService.setLocalIPv6(address+ "/" + prefix_length);
- return true;
- }
-
- @Override
- public boolean tun_builder_new() {
-
- return true;
- }
-
- @Override
- public boolean tun_builder_reroute_gw(String server_address,
- boolean server_address_ipv6, boolean ipv4, boolean ipv6, long flags) {
- // ignore
- return true;
- }
-
- @Override
- public boolean tun_builder_exclude_route(String address, int prefix_length,
- boolean ipv6) {
- //ignore
- return true;
- }
-
-
- private boolean setConfig(String vpnconfig) {
-
- ClientAPI_Config config = new ClientAPI_Config();
- if(mVp.getPasswordPrivateKey()!=null)
- config.setPrivateKeyPassword(mVp.getPasswordPrivateKey());
-
- config.setContent(vpnconfig);
- config.setTunPersist(mVp.mPersistTun);
- config.setGuiVersion(mVp.getVersionEnvString(mService));
- config.setExternalPkiAlias("extpki");
-
- ClientAPI_EvalConfig ec = eval_config(config);
- if(ec.getExternalPki()) {
- VpnStatus.logError("OpenVPN seem to think as external PKI");
- }
- if (ec.getError()) {
- VpnStatus.logError("OpenVPN config file parse error: " + ec.getMessage());
- return false;
- } else {
- config.setContent(vpnconfig);
- return true;
- }
- }
-
- @Override
- public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest certreq) {
- VpnStatus.logError("EXT PKI CERT");
- String[] ks = mVp.getKeyStoreCertificates((Context) mService);
- if(ks==null) {
- certreq.setError(true);
- certreq.setErrorText("Error in pki cert request");
- return;
- }
-
- String supcerts = ks[0];
- /* FIXME: How to differentiate between chain and ca certs in OpenVPN 3? */
- if (ks[1]!=null)
- supcerts += "\n" + ks[1];
- certreq.setSupportingChain(supcerts);
- certreq.setCert(ks[2]);
- certreq.setError(false);
- }
-
- @Override
- public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest signreq) {
- signreq.setSig(mVp.getSignedData(signreq.getData()));
- }
-
- void setUserPW() {
- if(mVp.isUserPWAuth()) {
- ClientAPI_ProvideCreds creds = new ClientAPI_ProvideCreds();
- creds.setCachePassword(true);
- creds.setPassword(mVp.getPasswordAuth());
- creds.setUsername(mVp.mUsername);
- provide_creds(creds);
- }
- }
-
- @Override
- public boolean socket_protect(int socket) {
- boolean b= mService.protect(socket);
- return b;
-
- }
-
- public OpenVPNThreadv3(OpenVPNService openVpnService, VpnProfile vp) {
- init_process();
- mVp =vp;
- mService =openVpnService;
- }
-
- @Override
- public void pause(pauseReason pauseReason)
- {
- pause();
- }
-
- @Override
- public void log(ClientAPI_LogInfo arg0) {
- String logmsg =arg0.getText();
- while (logmsg.endsWith("\n"))
- logmsg = logmsg.substring(0, logmsg.length()-1);
-
- VpnStatus.logInfo(logmsg);
- }
-
- @Override
- public void event(ClientAPI_Event event) {
- VpnStatus.updateStateString(event.getName(), event.getInfo());
- if(event.getError())
- VpnStatus.logError(String.format("EVENT(Error): %s: %s",event.getName(),event.getInfo()));
- }
-
-
- // When a connection is close to timeout, the core will call this
- // method. If it returns false, the core will disconnect with a
- // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE
- // state.
-
- @Override
- public boolean pause_on_connection_timeout() {
- VpnStatus.logInfo("pause on connection timeout?! ");
- return true;
- }
-
- public boolean stopVPN() {
- stop();
- return true;
- }
-
- @Override
- public void reconnect() {
- reconnect(1);
- }
-
-}
diff --git a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java
index 03930c61..73de29bc 100644
--- a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java
+++ b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java
@@ -16,48 +16,28 @@
*/
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Display;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View.MeasureSpec;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Iterator;
-import org.json.JSONException;
-import org.json.JSONObject;
+import android.app.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.widget.*;
+
+import com.pedrogomez.renderers.*;
+
+import java.net.*;
+import java.util.*;
+
+import butterknife.*;
+
+import org.json.*;
+
+import javax.inject.Inject;
import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface;
import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface;
import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import se.leap.bitmaskclient.FragmentManagerEnhanced;
-
-import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.eip.Constants;
/**
* Activity that builds and shows the list of known available providers.
@@ -68,12 +48,18 @@ import se.leap.bitmaskclient.R;
*
*/
public class ConfigurationWizard extends Activity
-implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
+implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
+
- private ProgressBar mProgressBar;
- private TextView progressbar_description;
- private ProviderListFragment provider_list_fragment;
+ @InjectView(R.id.progressbar_configuration_wizard) ProgressBar mProgressBar;
+ @InjectView(R.id.progressbar_description) TextView progressbar_description;
+
+ @InjectView(R.id.provider_list) ListView provider_list_view;
+ @Inject ProviderListAdapter adapter;
+
+ private ProviderManager provider_manager;
private Intent mConfigState = new Intent();
+ private Provider selected_provider;
final public static String TAG = ConfigurationWizard.class.getSimpleName();
final public static String TYPE_OF_CERTIFICATE = "type_of_certificate";
@@ -83,6 +69,9 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
final protected static String PROVIDER_SET = "PROVIDER SET";
final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
final protected static String ASSETS_URL_FOLDER = "urls";
+
+ final private static String PROGRESSBAR_TEXT = TAG + "PROGRESSBAR_TEXT";
+ final private static String PROGRESSBAR_NUMBER = TAG + "PROGRESSBAR_NUMBER";
public ProviderAPIResultReceiver providerAPI_result_receiver;
private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update;
@@ -90,66 +79,94 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
private static SharedPreferences preferences;
FragmentManagerEnhanced fragment_manager;
private static boolean setting_up_provider = false;
+ private String progressbar_text = "";
+ private String provider_name = "";
+ private int progress = -1;
+
+ private void initProviderList() {
+ List<Renderer<Provider>> prototypes = new ArrayList<Renderer<Provider>>();
+ prototypes.add(new ProviderRenderer(this));
+ ProviderRendererBuilder providerRendererBuilder = new ProviderRendererBuilder(prototypes);
+ adapter = new ProviderListAdapter(getLayoutInflater(), providerRendererBuilder, provider_manager);
+ provider_list_view.setAdapter(adapter);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ if(mProgressBar != null)
+ outState.putInt(PROGRESSBAR_NUMBER, mProgressBar.getProgress());
+ if(progressbar_description != null)
+ outState.putString(PROGRESSBAR_TEXT, progressbar_description.getText().toString());
+ if(selected_provider != null)
+ outState.putParcelable(Provider.KEY, selected_provider);
+ outState.putParcelable(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+ super.onSaveInstanceState(outState);
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
-
+ provider_manager = ProviderManager.getInstance(getAssets(), getExternalFilesDir(null));
+
setUpInitialUI();
- loadPreseededProviders();
-
setUpProviderAPIResultReceiver();
-
- // Only create our fragments if we're not restoring a saved instance
- if ( savedInstanceState == null ) {
- // TODO Some welcome screen?
- // We will need better flow control when we have more Fragments (e.g. user auth)
- setUpProviderList();
+
+ setUpProviderList();
+
+ if ( savedInstanceState != null ) {
+ restoreState(savedInstanceState);
}
+ }
- // TODO: If exposing deep links into your app, handle intents here.
- }
+ private void restoreState(Bundle savedInstanceState) {
+ progressbar_text = savedInstanceState.getString(PROGRESSBAR_TEXT, "");
+ provider_name = savedInstanceState.getString(Provider.NAME, "");
+ selected_provider = savedInstanceState.getParcelable(Provider.KEY);
+ progress = savedInstanceState.getInt(PROGRESSBAR_NUMBER, -1);
+ providerAPI_result_receiver = savedInstanceState.getParcelable(ProviderAPI.RECEIVER_KEY);
+ providerAPI_result_receiver.setReceiver(this);
+ }
+
+ @Override
+ protected void onPostResume() {
+ super.onPostResume();
+ if(!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) {
+ progressbar_description.setText(progressbar_text);
+ //onItemSelectedUi(getProvider(provider_name));
+ mProgressBar.setProgress(progress);
+
+ progressbar_text = "";
+ provider_name = "";
+ progress = -1;
+ }
+ }
private void setUpInitialUI() {
setContentView(R.layout.configuration_wizard_activity);
-
+ ButterKnife.inject(this);
+
hideProgressBar();
}
private void hideProgressBar() {
- mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard);
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
- progressbar_description = (TextView) findViewById(R.id.progressbar_description);
progressbar_description.setVisibility(TextView.INVISIBLE);
}
private void setUpProviderList() {
- provider_list_fragment = ProviderListFragment.newInstance();
-
- Bundle arguments = new Bundle();
- int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1);
- if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER)
- arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true);
-
- provider_list_fragment.setArguments(arguments);
-
- putProviderListFragment(provider_list_fragment);
+ initProviderList();
}
- private void putProviderListFragment(ProviderListFragment fragment) {
- fragment_manager.replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG);
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterReceiver(providerAPI_broadcast_receiver_update);
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(providerAPI_broadcast_receiver_update);
- }
-
private void setUpProviderAPIResultReceiver() {
providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
providerAPI_result_receiver.setReceiver(this);
@@ -164,8 +181,15 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
public void onReceiveResult(int resultCode, Bundle resultData) {
if(resultCode == ProviderAPI.PROVIDER_OK) {
mConfigState.setAction(PROVIDER_SET);
+ try {
+ String provider_json_string = preferences.getString(Provider.KEY, "");
+ if(!provider_json_string.isEmpty())
+ selected_provider.define(new JSONObject(provider_json_string));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
- if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){
+ if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){
mConfigState.putExtra(SERVICES_RETRIEVED, true);
downloadAnonCert();
@@ -179,21 +203,21 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
} else if(resultCode == ProviderAPI.PROVIDER_NOK) {
hideProgressBar();
- preferences.edit().remove(Provider.KEY).commit();
+ preferences.edit().remove(Provider.KEY).apply();
setting_up_provider = false;
setResult(RESULT_CANCELED, mConfigState);
String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
- showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
+ showDownloadFailedDialog(reason_to_fail);
}
else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
mProgressBar.incrementProgressBy(1);
hideProgressBar();
- setResult(RESULT_OK);
-
showProviderDetails();
+
+ setResult(RESULT_OK);
} else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
hideProgressBar();
@@ -204,28 +228,30 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
}
- /**
- * Callback method from {@link ProviderListFragment.Callbacks}
- * indicating that the item with the given ID was selected.
- */
- @Override
- public void onItemSelected(String id) {
+ @OnItemClick(R.id.provider_list)
+ void onItemSelected(int position) {
//TODO Code 2 pane view
- ProviderItem selected_provider = getProvider(id);
- int provider_index = getProviderIndex(id);
+ selected_provider = adapter.getItem(position);
+ onItemSelectedUi(selected_provider);
+ onItemSelectedLogic(selected_provider);
+ }
- startProgressBar(provider_index+1);
- provider_list_fragment.hideAllBut(provider_index);
+ private void onItemSelectedLogic(Provider selected_provider) {
+ setUpProvider(selected_provider.mainUrl());
+ }
- setUpProvider(selected_provider.providerMainUrl());
+ private void onItemSelectedUi(Provider provider) {
+ startProgressBar();
+ adapter.hideAllBut(adapter.indexOf(provider));
}
@Override
public void onBackPressed() {
- if(setting_up_provider) {
- stopSettingUpProvider();
+ if(setting_up_provider) {
+ stopSettingUpProvider();
} else {
- usualBackButton();
+ askDashboardToQuitApp();
+ super.onBackPressed();
}
}
@@ -234,168 +260,53 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
mProgressBar.setVisibility(ProgressBar.GONE);
mProgressBar.setProgress(0);
progressbar_description.setVisibility(TextView.GONE);
- preferences.edit().remove(Provider.KEY).commit();
+
+ preferences.edit().remove(Provider.KEY).apply();
setting_up_provider = false;
showAllProviders();
}
private void usualBackButton() {
- try {
- boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false;
- boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false;
- if(!is_provider_set_up || !is_provider_set_up_truly) {
- askDashboardToQuitApp();
- } else {
- setResult(RESULT_OK);
- }
- } catch (JSONException e) {
- askDashboardToQuitApp();
- super.onBackPressed();
- e.printStackTrace();
- }
- super.onBackPressed();
+ if(preferences.getString(Provider.KEY, "").isEmpty()) {
+ askDashboardToQuitApp();
+ } else {
+ setResult(RESULT_OK);
+ }
+ super.onBackPressed();
}
private void askDashboardToQuitApp() {
Intent ask_quit = new Intent();
ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT);
setResult(RESULT_CANCELED, ask_quit);
}
-
- private ProviderItem getProvider(String name) {
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(name)) {
- return provider;
- }
- }
- return null;
- }
- private void startProgressBar() {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- progressbar_description.setVisibility(TextView.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- }
-
- private void startProgressBar(int list_item_index) {
- startProgressBar();
- int measured_height = listItemHeight(list_item_index);
- mProgressBar.setTranslationY(measured_height);
- progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
- }
-
- private int getProviderIndex(String id) {
- int index = 0;
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(id)) {
- break;
- } else index++;
- }
- return index;
+ private void startProgressBar() {
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ progressbar_description.setVisibility(TextView.VISIBLE);
+ mProgressBar.setProgress(0);
+ mProgressBar.setMax(3);
+
+ int measured_height = listItemHeight();
+ mProgressBar.setTranslationY(measured_height);
+ progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
}
- private int listItemHeight(int list_item_index) {
- ListView provider_list_view = (ListView)findViewById(android.R.id.list);
- ListAdapter provider_list_adapter = provider_list_view.getAdapter();
- View listItem = provider_list_adapter.getView(0, null, provider_list_view);
+ private int listItemHeight() {
+ View listItem = adapter.getView(0, null, provider_list_view);
listItem.setLayoutParams(new RelativeLayout.LayoutParams(
- RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT));
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT));
WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int screenWidth = display.getWidth(); // deprecated
int listViewWidth = screenWidth - 10 - 10;
- int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth,
- MeasureSpec.AT_MOST);
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth,
+ View.MeasureSpec.AT_MOST);
listItem.measure(widthSpec, 0);
return listItem.getMeasuredHeight();
-}
-
- /**
- * Loads providers data from url files contained in the assets folder
- * @return true if the files were correctly read
- */
- private boolean loadPreseededProviders() {
- boolean loaded_preseeded_providers = true;
- try {
- //TODO Put that folder in a better place (also inside the "for")
- String[] urls_filepaths = getAssets().list(ASSETS_URL_FOLDER);
- for(String url_filepath : urls_filepaths) {
- addNewProviderToList(url_filepath);
- }
- } catch (IOException e) {
- loaded_preseeded_providers = false;
- }
-
- return loaded_preseeded_providers;
- }
-
- private void addNewProviderToList(String url_filepath) {
- String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath);
- if(getId(provider_main_url).isEmpty()) {
- String provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString();
- ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url));
- }
- }
-
- private String extractProviderMainUrlFromAssetsFile(String filepath) {
- String provider_main_url = "";
- try {
- InputStream input_stream_file_contents = getAssets().open(filepath);
- byte[] urls_file_bytes = new byte[input_stream_file_contents.available()];
- input_stream_file_contents.read(urls_file_bytes);
- String urls_file_content = new String(urls_file_bytes);
- JSONObject file_contents = new JSONObject(urls_file_content);
- provider_main_url = file_contents.getString(Provider.MAIN_URL);
- } catch (JSONException e) {
- } catch (IOException e) {
- }
- return provider_main_url;
- }
-
- private String getId(String provider_main_url) {
- try {
- URL provider_url = new URL(provider_main_url);
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- URL aux_provider_url = new URL(provider.providerMainUrl());
- if(isSameURL(provider_url, aux_provider_url)) {
- return provider.name();
- }
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- return "";
- }
-
- /**
- * Checks, whether 2 urls are pointing to the same location.
- *
- * @param url a url
- * @param baseUrl an other url, that should be compared.
- * @return true, if the urls point to the same host and port and use the
- * same protocol, false otherwise.
- */
- private boolean isSameURL(final URL url, final URL baseUrl) {
- if (!url.getProtocol().equals(baseUrl.getProtocol())) {
- return false;
- }
- if (!url.getHost().equals(baseUrl.getHost())) {
- return false;
- }
- if (url.getPort() != baseUrl.getPort()) {
- return false;
- }
- return true;
}
/**
@@ -420,8 +331,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
*/
public void addAndSelectNewProvider() {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG);
- DialogFragment newFragment = NewProviderDialog.newInstance();
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
+ new NewProviderDialog().show(fragment_transaction, NewProviderDialog.TAG);
}
/**
@@ -430,7 +340,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
public void addAndSelectNewProvider(String main_url) {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG);
- DialogFragment newFragment = NewProviderDialog.newInstance();
+ DialogFragment newFragment = new NewProviderDialog();
Bundle data = new Bundle();
data.putString(Provider.MAIN_URL, main_url);
newFragment.setArguments(data);
@@ -441,10 +351,9 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
* Once selected a provider, this fragment offers the user to log in,
* use it anonymously (if possible)
* or cancel his/her election pressing the back button.
- * @param view
* @param reason_to_fail
*/
- public void showDownloadFailedDialog(View view, String reason_to_fail) {
+ public void showDownloadFailedDialog(String reason_to_fail) {
FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG);
DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail);
@@ -466,31 +375,32 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
}
- public void showAndSelectProvider(String provider_main_url) {
- if(getId(provider_main_url).isEmpty())
- showProvider(provider_main_url);
- autoSelectProvider(provider_main_url);
- }
-
- private void showProvider(final String provider_main_url) {
- String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
- ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url);
- provider_list_fragment.addItem(added_provider);
- }
-
- private void autoSelectProvider(String provider_main_url) {
- onItemSelected(getId(provider_main_url));
+ public void showAndSelectProvider(String provider_main_url) {
+ try {
+ selected_provider = new Provider(new URL((provider_main_url)));
+ adapter.add(selected_provider);
+ adapter.saveProviders();
+ autoSelectProvider(selected_provider);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
}
+ }
+
+ private void autoSelectProvider(Provider provider) {
+ selected_provider = provider;
+ onItemSelectedUi(selected_provider);
+ onItemSelectedLogic(selected_provider);
+ }
/**
* Asks ProviderAPI to download a new provider.json file
* @param provider_name
* @param provider_main_url
*/
- public void setUpProvider(String provider_main_url) {
+ public void setUpProvider(URL provider_main_url) {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider_main_url);
+ parameters.putString(Provider.MAIN_URL, provider_main_url.toString());
provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
@@ -533,35 +443,34 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD
}
}
- public void showAllProviders() {
- provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null)
- provider_list_fragment.unhideAll();
- }
+ public void showAllProviders() {
+ adapter.showAllProviders();
+ }
- public void cancelSettingUpProvider() {
- provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null) {
- provider_list_fragment.removeLastItem();
- }
- preferences.edit().remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
- }
+ public void cancelSettingUpProvider() {
+ adapter.showAllProviders();
+ setting_up_provider = false;
+ preferences.edit().remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).apply();
+ }
@Override
public void login() {
Intent ask_login = new Intent();
- ask_login.putExtra(LogInDialog.TAG, LogInDialog.TAG);
+ ask_login.putExtra(Provider.KEY, selected_provider);
+ ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG);
setResult(RESULT_OK, ask_login);
setting_up_provider = false;
finish();
}
- @Override
- public void use_anonymously() {
- setResult(RESULT_OK);
- setting_up_provider = false;
- finish();
- }
+ @Override
+ public void use_anonymously() {
+ Intent pass_provider = new Intent();
+ pass_provider.putExtra(Provider.KEY, selected_provider);
+ setResult(RESULT_OK, pass_provider);
+ setting_up_provider = false;
+ finish();
+ }
public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver {
diff --git a/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java b/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java
index 7ed1940e..f6709c22 100644
--- a/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java
+++ b/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -14,16 +14,16 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
+package se.leap.bitmaskclient;
+import butterknife.ButterKnife;
+import butterknife.InjectView;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import se.leap.bitmaskclient.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
-import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -33,33 +33,28 @@ import android.widget.Toast;
/**
* Implements the new custom provider dialog.
- *
+ *
* @author parmegv
*
*/
public class NewProviderDialog extends DialogFragment {
final public static String TAG = "newProviderDialog";
-
- public interface NewProviderDialogInterface {
+
+ @InjectView(R.id.new_provider_url)
+ EditText url_input_field;
+
+ public interface NewProviderDialogInterface {
public void showAndSelectProvider(String url_provider);
}
- NewProviderDialogInterface interface_with_ConfigurationWizard;
+ NewProviderDialogInterface interface_with_ConfigurationWizard;
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance() {
- NewProviderDialog dialog_fragment = new NewProviderDialog();
- return dialog_fragment;
- }
-
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity;
+ interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
@@ -67,51 +62,57 @@ public class NewProviderDialog extends DialogFragment {
}
@Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View new_provider_dialog_view = inflater.inflate(R.layout.new_provider_dialog, null);
- final EditText url_input_field = (EditText)new_provider_dialog_view.findViewById(R.id.new_provider_url);
- if(getArguments() != null && getArguments().containsKey(Provider.MAIN_URL)) {
- url_input_field.setText(getArguments().getString(Provider.MAIN_URL));
- }
-
- builder.setView(new_provider_dialog_view)
- .setMessage(R.string.introduce_new_provider)
- .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String entered_url = url_input_field.getText().toString().trim();
- if(!entered_url.startsWith("https://")) {
- if (entered_url.startsWith("http://")){
- entered_url = entered_url.substring("http://".length());
- }
- entered_url = "https://".concat(entered_url);
- }
- if(validURL(entered_url)) {
- interface_with_ConfigurationWizard.showAndSelectProvider(entered_url);
- Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();
- } else {
- url_input_field.setText("");
- Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();;
- }
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
- // Create the AlertDialog object and return it
- return builder.create();
- }
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View view = inflater.inflate(R.layout.new_provider_dialog, null);
+ ButterKnife.inject(this, view);
+ Bundle arguments = getArguments();
+ if(arguments != null) {
+ url_input_field.setText(arguments.getString(Provider.MAIN_URL, ""));
+ }
+
+ builder.setView(view)
+ .setMessage(R.string.introduce_new_provider)
+ .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ saveProvider();
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
+
+ private void saveProvider() {
+ String entered_url = url_input_field.getText().toString().trim();
+ if(!entered_url.startsWith("https://")) {
+ if (entered_url.startsWith("http://")){
+ entered_url = entered_url.substring("http://".length());
+ }
+ entered_url = "https://".concat(entered_url);
+ }
+
+ if(validURL(entered_url)) {
+ interface_with_ConfigurationWizard.showAndSelectProvider(entered_url);
+ Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();
+ } else {
+ url_input_field.setText("");
+ Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();;
+ }
+ }
/**
* Checks if the entered url is valid or not.
* @param entered_url
* @return true if it's not empty nor contains only the protocol.
*/
- boolean validURL(String entered_url) {
- //return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty();
- return android.util.Patterns.WEB_URL.matcher(entered_url).matches();
- }
+ boolean validURL(String entered_url) {
+ //return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty();
+ return android.util.Patterns.WEB_URL.matcher(entered_url).matches();
+ }
}
diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
index f419afaf..9d0b4db6 100644
--- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -17,59 +17,21 @@
package se.leap.bitmaskclient;
import android.app.IntentService;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.util.Base64;
-import android.util.Log;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
+import android.content.*;
+import android.os.*;
+import android.util.*;
+import java.io.*;
import java.math.BigInteger;
-import java.net.ConnectException;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.CookiePolicy;
-import java.net.MalformedURLException;
-import java.net.SocketTimeoutException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
import java.security.interfaces.RSAPrivateKey;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Scanner;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
+import java.util.*;
+import javax.net.ssl.*;
import org.apache.http.client.ClientProtocolException;
-import org.json.JSONException;
-import org.json.JSONObject;
-import se.leap.bitmaskclient.R;
+import org.json.*;
+import se.leap.bitmaskclient.eip.*;
/**
* Implements HTTP api methods used to manage communications with the provider server.
@@ -83,6 +45,7 @@ import se.leap.bitmaskclient.R;
public class ProviderAPI extends IntentService {
final public static String
+ TAG = ProviderAPI.class.getSimpleName(),
SET_UP_PROVIDER = "setUpProvider",
DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
SRP_REGISTER = "srpRegister",
@@ -95,23 +58,22 @@ public class ProviderAPI extends IntentService {
ERRORS = "errors",
UPDATE_PROGRESSBAR = "update_progressbar",
CURRENT_PROGRESS = "current_progress",
- TAG = ProviderAPI.class.getSimpleName();
+ DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE"
;
final public static int
- CUSTOM_PROVIDER_ADDED = 0,
- SRP_AUTHENTICATION_SUCCESSFUL = 3,
- SRP_AUTHENTICATION_FAILED = 4,
- SRP_REGISTRATION_SUCCESSFUL = 5,
- SRP_REGISTRATION_FAILED = 6,
- LOGOUT_SUCCESSFUL = 7,
+ SUCCESSFUL_LOGIN = 3,
+ FAILED_LOGIN = 4,
+ SUCCESSFUL_SIGNUP = 5,
+ FAILED_SIGNUP = 6,
+ SUCCESSFUL_LOGOUT = 7,
LOGOUT_FAILED = 8,
CORRECTLY_DOWNLOADED_CERTIFICATE = 9,
INCORRECTLY_DOWNLOADED_CERTIFICATE = 10,
PROVIDER_OK = 11,
PROVIDER_NOK = 12,
- CORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 13,
- INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14
+ CORRECTLY_DOWNLOADED_EIP_SERVICE = 13,
+ INCORRECTLY_DOWNLOADED_EIP_SERVICE= 14
;
private static boolean
@@ -121,12 +83,12 @@ public class ProviderAPI extends IntentService {
;
private static String last_provider_main_url;
- private static boolean setting_up_provider = true;
+ private static boolean go_ahead = true;
private static SharedPreferences preferences;
private static String provider_api_url;
public static void stop() {
- setting_up_provider = false;
+ go_ahead = false;
}
public ProviderAPI() {
@@ -137,14 +99,9 @@ public class ProviderAPI extends IntentService {
@Override
public void onCreate() {
super.onCreate();
+
preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
- if(provider_api_url == null && preferences.contains(Provider.KEY)) {
- try {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION);
- } catch (JSONException e) {}
- }
}
public static String lastProviderMainUrl() {
@@ -160,11 +117,20 @@ public class ProviderAPI extends IntentService {
final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY);
String action = command.getAction();
Bundle parameters = command.getBundleExtra(PARAMETERS);
- setting_up_provider = true;
+
+ if(provider_api_url == null && preferences.contains(Provider.KEY)) {
+ try {
+ JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
+ provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION);
+ go_ahead = true;
+ } catch (JSONException e) {
+ go_ahead = false;
+ }
+ }
if(action.equalsIgnoreCase(SET_UP_PROVIDER)) {
Bundle result = setUpProvider(parameters);
- if(setting_up_provider) {
+ if(go_ahead) {
if(result.getBoolean(RESULT_KEY)) {
receiver.send(PROVIDER_OK, result);
} else {
@@ -174,20 +140,20 @@ public class ProviderAPI extends IntentService {
} else if (action.equalsIgnoreCase(SRP_REGISTER)) {
Bundle result = tryToRegister(parameters);
if(result.getBoolean(RESULT_KEY)) {
- receiver.send(SRP_REGISTRATION_SUCCESSFUL, result);
+ receiver.send(SUCCESSFUL_SIGNUP, result);
} else {
- receiver.send(SRP_REGISTRATION_FAILED, result);
+ receiver.send(FAILED_SIGNUP, result);
}
} else if (action.equalsIgnoreCase(SRP_AUTH)) {
Bundle result = tryToAuthenticate(parameters);
if(result.getBoolean(RESULT_KEY)) {
- receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, result);
+ receiver.send(SUCCESSFUL_LOGIN, result);
} else {
- receiver.send(SRP_AUTHENTICATION_FAILED, result);
+ receiver.send(FAILED_LOGIN, result);
}
} else if (action.equalsIgnoreCase(LOG_OUT)) {
if(logOut()) {
- receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY);
+ receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY);
} else {
receiver.send(LOGOUT_FAILED, Bundle.EMPTY);
}
@@ -197,15 +163,22 @@ public class ProviderAPI extends IntentService {
} else {
receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
}
- }
+ } else if(action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) {
+ Bundle result = getAndSetEipServiceJson();
+ if(result.getBoolean(RESULT_KEY)) {
+ receiver.send(CORRECTLY_DOWNLOADED_EIP_SERVICE, result);
+ } else {
+ receiver.send(INCORRECTLY_DOWNLOADED_EIP_SERVICE, result);
+ }
+ }
}
private Bundle tryToRegister(Bundle task) {
Bundle session_id_bundle = new Bundle();
int progress = 0;
- String username = (String) task.get(SessionDialogInterface.USERNAME);
- String password = (String) task.get(SessionDialogInterface.PASSWORD);
+ String username = (String) task.get(SessionDialog.USERNAME);
+ String password = (String) task.get(SessionDialog.PASSWORD);
if(validUserLoginData(username, password)) {
session_id_bundle = register(username, password);
@@ -213,12 +186,12 @@ public class ProviderAPI extends IntentService {
} else {
if(!wellFormedPassword(password)) {
session_id_bundle.putBoolean(RESULT_KEY, false);
- session_id_bundle.putString(SessionDialogInterface.USERNAME, username);
- session_id_bundle.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true);
+ session_id_bundle.putString(SessionDialog.USERNAME, username);
+ session_id_bundle.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true);
}
if(username.isEmpty()) {
session_id_bundle.putBoolean(RESULT_KEY, false);
- session_id_bundle.putBoolean(SessionDialogInterface.USERNAME_MISSING, true);
+ session_id_bundle.putBoolean(SessionDialog.USERNAME_MISSING, true);
}
}
@@ -237,8 +210,8 @@ public class ProviderAPI extends IntentService {
if(api_result.has(ERRORS))
result = authFailedNotification(api_result, username);
else {
- result.putString(SessionDialogInterface.USERNAME, username);
- result.putString(SessionDialogInterface.PASSWORD, password);
+ result.putString(SessionDialog.USERNAME, username);
+ result.putString(SessionDialog.PASSWORD, password);
result.putBoolean(RESULT_KEY, true);
}
@@ -255,20 +228,20 @@ public class ProviderAPI extends IntentService {
Bundle result = new Bundle();
int progress = 0;
- String username = (String) task.get(SessionDialogInterface.USERNAME);
- String password = (String) task.get(SessionDialogInterface.PASSWORD);
+ String username = (String) task.get(SessionDialog.USERNAME);
+ String password = (String) task.get(SessionDialog.PASSWORD);
if(validUserLoginData(username, password)) {
result = authenticate(username, password);
broadcast_progress(progress++);
} else {
if(!wellFormedPassword(password)) {
result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialogInterface.USERNAME, username);
- result.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true);
+ result.putString(SessionDialog.USERNAME, username);
+ result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true);
}
if(username.isEmpty()) {
result.putBoolean(RESULT_KEY, false);
- result.putBoolean(SessionDialogInterface.USERNAME_MISSING, true);
+ result.putBoolean(SessionDialog.USERNAME_MISSING, true);
}
}
@@ -297,7 +270,7 @@ public class ProviderAPI extends IntentService {
}
} else {
result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialogInterface.USERNAME, username);
+ result.putString(SessionDialog.USERNAME, username);
result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message));
}
} catch (JSONException e) {
@@ -328,7 +301,7 @@ public class ProviderAPI extends IntentService {
} catch(JSONException e) {}
if(!username.isEmpty())
- user_notification_bundle.putString(SessionDialogInterface.USERNAME, username);
+ user_notification_bundle.putString(SessionDialog.USERNAME, username);
user_notification_bundle.putBoolean(RESULT_KEY, false);
return user_notification_bundle;
@@ -397,7 +370,7 @@ public class ProviderAPI extends IntentService {
* Sends an HTTP POST request to the api server to register a new user.
* @param server_url
* @param username
- * @param salted_password
+ * @param salt
* @param password_verifier
* @return response from authentication server
*/
@@ -514,6 +487,7 @@ public class ProviderAPI extends IntentService {
if(task != null && task.containsKey(Provider.MAIN_URL)) {
last_provider_main_url = task.getString(Provider.MAIN_URL);
CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false;
+ go_ahead = true;
}
if(!PROVIDER_JSON_DOWNLOADED)
@@ -546,7 +520,7 @@ public class ProviderAPI extends IntentService {
String cert_string = downloadWithCommercialCA(ca_cert_url);
result.putBoolean(RESULT_KEY, true);
- if(validCertificate(cert_string) && setting_up_provider) {
+ if(validCertificate(cert_string) && go_ahead) {
preferences.edit().putString(Provider.CA_CERT, cert_string).commit();
result.putBoolean(RESULT_KEY, true);
} else {
@@ -609,7 +583,7 @@ public class ProviderAPI extends IntentService {
private Bundle getAndSetProviderJson(String provider_main_url) {
Bundle result = new Bundle();
- if(setting_up_provider) {
+ if(go_ahead) {
String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json");
try {
@@ -619,8 +593,8 @@ public class ProviderAPI extends IntentService {
//TODO setProviderName(name);
preferences.edit().putString(Provider.KEY, provider_json.toString()).commit();
- preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit();
- preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit();
+ preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit();
+ preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit();
result.putBoolean(RESULT_KEY, true);
} catch (JSONException e) {
@@ -636,7 +610,7 @@ public class ProviderAPI extends IntentService {
private Bundle getAndSetEipServiceJson() {
Bundle result = new Bundle();
String eip_service_json_string = "";
- if(setting_up_provider) {
+ if(go_ahead) {
try {
JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
@@ -644,7 +618,7 @@ public class ProviderAPI extends IntentService {
JSONObject eip_service_json = new JSONObject(eip_service_json_string);
eip_service_json.getInt(Provider.API_RETURN_SERIAL);
- preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit();
+ preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit();
result.putBoolean(RESULT_KEY, true);
} catch (JSONException e) {
@@ -721,7 +695,7 @@ public class ProviderAPI extends IntentService {
/**
* Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider.
- * @param url as a string
+ * @param url_string as a string
* @return an empty string if it fails, the url content if not.
*/
private String downloadWithProviderCA(String url_string) {
@@ -882,28 +856,18 @@ public class ProviderAPI extends IntentService {
}
return true;
}
-
- private boolean updateVpnCertificate() {
- getNewCert();
-
- Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
- updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
- startService(updateEIP);
-
- return true;
- }
/**
* Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
*
* @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
*/
- private boolean getNewCert() {
+ private boolean updateVpnCertificate() {
try {
JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
String provider_main_url = provider_json.getString(Provider.API_URL);
- URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE);
+ URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE);
String cert_string = downloadWithProviderCA(new_cert_string_url.toString());
@@ -935,14 +899,14 @@ public class ProviderAPI extends IntentService {
certificateString = certAndKey[i++] + certAndKey[i];
}
}
+
RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString);
keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
- preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit();
+ preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit();
X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString);
certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT);
- preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
- preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit();
+ preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
return true;
} catch (CertificateException e) {
// TODO Auto-generated catch block
diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java
index 9252b8fa..97ce5245 100644
--- a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java
+++ b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java
@@ -1,22 +1,17 @@
-package se.leap.bitmaskclient;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
+package se.leap.bitmaskclient;
+
+import org.json.*;
+
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
+
+import android.app.*;
+import android.content.*;
+import android.os.Bundle;
+import android.view.*;
+import android.widget.TextView;
+
public class ProviderDetailFragment extends DialogFragment {
final public static String TAG = "providerDetailFragment";
@@ -66,7 +61,7 @@ public class ProviderDetailFragment extends DialogFragment {
private boolean anon_allowed(JSONObject provider_json) {
try {
JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(EIP.ALLOWED_ANON) && service_description.getBoolean(EIP.ALLOWED_ANON);
+ return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON);
} catch (JSONException e) {
return false;
}
@@ -85,7 +80,7 @@ public class ProviderDetailFragment extends DialogFragment {
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
- editor.remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
+ editor.remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
interface_with_configuration_wizard.showAllProviders();
}