summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java42
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java20
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/MainActivity.java11
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java35
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java41
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java30
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderManager.java53
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/StartActivity.java9
-rw-r--r--app/src/main/res/layout-xlarge/eip_service_fragment.xml9
-rw-r--r--app/src/main/res/layout/eip_service_fragment.xml9
-rw-r--r--app/src/main/res/menu/configuration_wizard_activity.xml15
15 files changed, 156 insertions, 141 deletions
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 6c312c87..f701b7aa 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -913,7 +913,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// CONNECTED
// Does not work :(
notificationManager.buildOpenVpnNotification(
- mProfile.mName,
+ mProfile != null ? mProfile.mName : "",
VpnStatus.getLastCleanLogMessage(this),
VpnStatus.getLastCleanLogMessage(this),
level,
@@ -944,7 +944,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
humanReadableByteCount(out, false, getResources()),
humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true, getResources()));
notificationManager.buildOpenVpnNotification(
- mProfile.mName,
+ mProfile != null ? mProfile.mName : "",
netstat,
null,
LEVEL_CONNECTED,
@@ -987,7 +987,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
public void requestInputFromUser(int resid, String needed) {
VpnStatus.updateStateString("NEED", "need " + needed, resid, LEVEL_WAITING_FOR_USER_INPUT);
notificationManager.buildOpenVpnNotification(
- mProfile.mName,
+ mProfile != null ? mProfile.mName : "",
getString(resid),
getString(resid),
LEVEL_WAITING_FOR_USER_INPUT,
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index 50d23106..f07a2a23 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -29,6 +29,8 @@ import org.spongycastle.util.encoders.Base64;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -49,9 +51,11 @@ import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import static android.R.attr.name;
import static se.leap.bitmaskclient.Constants.DEFAULT_SHARED_PREFS_BATTERY_SAVER;
@@ -77,7 +81,7 @@ public class ConfigHelper {
public static boolean checkErroneousDownload(String downloadedString) {
try {
- if (downloadedString == null || downloadedString.isEmpty() || new JSONObject(downloadedString).has(ProviderAPI.ERRORS)) {
+ if (downloadedString == null || downloadedString.isEmpty() || new JSONObject(downloadedString).has(ProviderAPI.ERRORS) || new JSONObject(downloadedString).has(ProviderAPI.BACKEND_ERROR_KEY)) {
return true;
} else {
return false;
@@ -128,36 +132,14 @@ public class ConfigHelper {
return (X509Certificate) certificate;
}
+ public static String loadInputStreamAsString(java.io.InputStream is) {
+ java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
+ return s.hasNext() ? s.next() : "";
+ }
- public static String loadInputStreamAsString(InputStream inputStream) {
- BufferedReader in = null;
- try {
- StringBuilder buf = new StringBuilder();
- in = new BufferedReader(new InputStreamReader(inputStream));
-
- String str;
- boolean isFirst = true;
- while ( (str = in.readLine()) != null ) {
- if (isFirst)
- isFirst = false;
- else
- buf.append('\n');
- buf.append(str);
- }
- return buf.toString();
- } catch (IOException e) {
- Log.e(TAG, "Error opening asset " + name);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- Log.e(TAG, "Error closing asset " + name);
- }
- }
- }
-
- return null;
+ //allows us to mock FileInputStream
+ public static InputStream getInputStreamFrom(String filePath) throws FileNotFoundException {
+ return new FileInputStream(filePath);
}
protected static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
index ea328216..f0e2de85 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
@@ -1,16 +1,19 @@
package se.leap.bitmaskclient;
import android.content.SharedPreferences;
+import android.graphics.PorterDuff;
+import android.os.Build;
import android.os.Bundle;
-import android.os.PersistableBundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
+import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.AppCompatTextView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import butterknife.InjectView;
@@ -38,6 +41,9 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
@InjectView(R.id.loading_screen)
protected LinearLayout loadingScreen;
+ @InjectView(R.id.progressbar)
+ protected ProgressBar progressBar;
+
@InjectView(R.id.progressbar_description)
protected AppCompatTextView progressbarText;
@@ -59,6 +65,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
super.setContentView(view);
if (provider != null)
setProviderHeaderText(provider.getName());
+ setProgressbarColorForPreLollipop();
}
@Override
@@ -66,6 +73,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
super.setContentView(layoutResID);
if (provider != null)
setProviderHeaderText(provider.getName());
+ setProgressbarColorForPreLollipop();
}
@Override
@@ -73,8 +81,18 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
super.setContentView(view, params);
if (provider != null)
setProviderHeaderText(provider.getName());
+ setProgressbarColorForPreLollipop();
}
+ private void setProgressbarColorForPreLollipop() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ progressBar.getIndeterminateDrawable().setColorFilter(
+ ContextCompat.getColor(this, R.color.colorPrimary),
+ PorterDuff.Mode.SRC_IN);
+ }
+ }
+
+
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index 7b84657c..34617af3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -31,6 +31,7 @@ import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatImageView;
+import android.support.v7.widget.AppCompatTextView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -60,7 +61,7 @@ import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
-import static se.leap.bitmaskclient.ProviderCredentialsBaseActivity.USER_MESSAGE;
+import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE;
import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message;
public class EipFragment extends Fragment implements Observer {
@@ -84,10 +85,10 @@ public class EipFragment extends Fragment implements Observer {
Button mainButton;
@InjectView(R.id.routed_text)
- TextView routedText;
+ AppCompatTextView routedText;
@InjectView(R.id.vpn_route)
- TextView vpnRoute;
+ AppCompatTextView vpnRoute;
private EipStatus eipStatus;
diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
index 952f2d1f..19294618 100644
--- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
@@ -73,7 +73,7 @@ import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFI
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
-import static se.leap.bitmaskclient.ProviderCredentialsBaseActivity.USER_MESSAGE;
+import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE;
import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed;
import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message;
@@ -82,12 +82,7 @@ public class MainActivity extends AppCompatActivity implements Observer {
public final static String TAG = MainActivity.class.getSimpleName();
- private static final String KEY_ACTIVITY_STATE = "key state of activity";
- private static final String DEFAULT_UI_STATE = "default state";
- private static final String SHOW_DIALOG_STATE = "show dialog";
- private static final String REASON_TO_FAIL = "reason to fail";
-
- private static Provider provider = new Provider();
+ private Provider provider = new Provider();
private SharedPreferences preferences;
private EipStatus eipStatus;
private NavigationDrawerFragment navigationDrawerFragment;
@@ -213,7 +208,7 @@ public class MainActivity extends AppCompatActivity implements Observer {
break;
}
}
-
+ //TODO: Why do we want this --v? legacy and redundant?
Fragment fragment = new EipFragment();
Bundle arguments = new Bundle();
arguments.putParcelable(PROVIDER_KEY, provider);
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 7104143c..fd067bf9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -90,9 +90,8 @@ public final class Provider implements Parcelable {
}
if (definition != null) {
try {
- this.definition = new JSONObject(definition);
- parseDefinition(this.definition);
- } catch (JSONException | NullPointerException e) {
+ define(new JSONObject(definition));
+ } catch (JSONException e) {
e.printStackTrace();
}
}
@@ -133,26 +132,8 @@ public final class Provider implements Parcelable {
}
public boolean define(JSONObject providerJson) {
- /*
- * fix against "api_uri": "https://calyx.net.malicious.url.net:4430",
- * This method aims to prevent attacks where the provider.json file got manipulated by a third party.
- * The main url should not change.
- */
-
- try {
- String providerApiUrl = providerJson.getString(Provider.API_URL);
- String providerDomain = providerJson.getString(Provider.DOMAIN);
- if (getMainUrlString().contains(providerDomain) && providerApiUrl.contains(providerDomain + ":")) {
- definition = providerJson;
- parseDefinition(definition);
- return true;
- } else {
- return false;
- }
- } catch (JSONException e) {
- e.printStackTrace();
- return false;
- }
+ definition = providerJson;
+ return parseDefinition(definition);
}
public JSONObject getDefinition() {
@@ -297,8 +278,6 @@ public final class Provider implements Parcelable {
try {
json.put(Provider.MAIN_URL, mainUrl);
//TODO: add other fields here?
- //this is used to save custom providers as json. I guess this doesn't work correctly
- //TODO 2: verify that
} catch (JSONException e) {
e.printStackTrace();
}
@@ -345,7 +324,7 @@ public final class Provider implements Parcelable {
}
}
- private void parseDefinition(JSONObject definition) {
+ private boolean parseDefinition(JSONObject definition) {
try {
String pin = definition.getString(CA_CERT_FINGERPRINT);
this.certificatePin = pin.split(":")[1].trim();
@@ -354,8 +333,9 @@ public final class Provider implements Parcelable {
this.allowAnonymous = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS);
this.allowRegistered = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED);
this.apiVersion = getDefinition().getString(Provider.API_VERSION);
+ return true;
} catch (JSONException | ArrayIndexOutOfBoundsException | MalformedURLException e) {
- e.printStackTrace();
+ return false;
}
}
@@ -446,5 +426,4 @@ public final class Provider implements Parcelable {
allowRegistered = false;
allowAnonymous = false;
}
-
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
index f5efde05..f1f474d7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -51,6 +51,7 @@ public class ProviderAPI extends IntentService implements ProviderApiManagerBase
ERRORID = "errorId",
BACKEND_ERROR_KEY = "error",
BACKEND_ERROR_MESSAGE = "message",
+ USER_MESSAGE = "userMessage",
DOWNLOAD_SERVICE_JSON = "ProviderAPI.DOWNLOAD_SERVICE_JSON",
PROVIDER_SET_UP = "ProviderAPI.PROVIDER_SET_UP";
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
index b93abaeb..2cde431e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
@@ -46,6 +46,7 @@ import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import javax.net.ssl.SSLHandshakeException;
@@ -63,19 +64,16 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_KEY;
import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_MESSAGE;
-import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
-import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
-import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
-import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
-import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_SERVICE_JSON;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.ERRORID;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.FAILED_LOGIN;
import static se.leap.bitmaskclient.ProviderAPI.FAILED_SIGNUP;
-import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.LOGOUT_FAILED;
import static se.leap.bitmaskclient.ProviderAPI.LOG_IN;
import static se.leap.bitmaskclient.ProviderAPI.LOG_OUT;
@@ -90,15 +88,18 @@ import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGIN;
import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGOUT;
import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_SIGNUP;
import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROVIDER_DETAILS;
+import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE;
+import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
+import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
+import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
import static se.leap.bitmaskclient.R.string.certificate_error;
-import static se.leap.bitmaskclient.R.string.switch_provider_menu_option;
-import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid;
import static se.leap.bitmaskclient.R.string.error_io_exception_user_message;
import static se.leap.bitmaskclient.R.string.error_json_exception_user_message;
import static se.leap.bitmaskclient.R.string.error_no_such_algorithm_exception_user_message;
import static se.leap.bitmaskclient.R.string.malformed_url;
import static se.leap.bitmaskclient.R.string.server_unreachable_message;
import static se.leap.bitmaskclient.R.string.service_is_down_error;
+import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid;
import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert;
import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_details;
import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert;
@@ -290,7 +291,7 @@ public abstract class ProviderApiManagerBase {
JSONObject stepResult = null;
OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult);
if (okHttpClient == null) {
- return authFailedNotification(stepResult, username);
+ return backendErrorNotification(stepResult, username);
}
LeapSRPSession client = new LeapSRPSession(username, password);
@@ -302,7 +303,7 @@ public abstract class ProviderApiManagerBase {
Bundle result = new Bundle();
if (api_result.has(ERRORS) || api_result.has(BACKEND_ERROR_KEY))
- result = authFailedNotification(api_result, username);
+ result = backendErrorNotification(api_result, username);
else {
result.putString(CREDENTIALS_USERNAME, username);
result.putString(CREDENTIALS_PASSWORD, password);
@@ -349,7 +350,7 @@ public abstract class ProviderApiManagerBase {
OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult);
if (okHttpClient == null) {
- return authFailedNotification(stepResult, username);
+ return backendErrorNotification(stepResult, username);
}
LeapSRPSession client = new LeapSRPSession(username, password);
@@ -367,15 +368,15 @@ public abstract class ProviderApiManagerBase {
if (client.verify(M2)) {
result.putBoolean(BROADCAST_RESULT_KEY, true);
} else {
- authFailedNotification(step_result, username);
+ backendErrorNotification(step_result, username);
}
} else {
result.putBoolean(BROADCAST_RESULT_KEY, false);
result.putString(CREDENTIALS_USERNAME, username);
- result.putString(resources.getString(R.string.user_message), resources.getString(R.string.error_srp_math_error_user_message));
+ result.putString(USER_MESSAGE, resources.getString(R.string.error_srp_math_error_user_message));
}
} catch (JSONException e) {
- result = authFailedNotification(step_result, username);
+ result = backendErrorNotification(step_result, username);
e.printStackTrace();
}
@@ -391,7 +392,7 @@ public abstract class ProviderApiManagerBase {
return true;
}
- private Bundle authFailedNotification(JSONObject result, String username) {
+ private Bundle backendErrorNotification(JSONObject result, String username) {
Bundle userNotificationBundle = new Bundle();
if (result.has(ERRORS)) {
Object baseErrorMessage = result.opt(ERRORS);
@@ -400,14 +401,14 @@ public abstract class ProviderApiManagerBase {
JSONObject errorMessage = result.getJSONObject(ERRORS);
String errorType = errorMessage.keys().next().toString();
String message = errorMessage.get(errorType).toString();
- userNotificationBundle.putString(resources.getString(R.string.user_message), message);
- } catch (JSONException e) {
+ userNotificationBundle.putString(USER_MESSAGE, message);
+ } catch (JSONException | NoSuchElementException | NullPointerException e) {
e.printStackTrace();
}
} else if (baseErrorMessage instanceof String) {
try {
String errorMessage = result.getString(ERRORS);
- userNotificationBundle.putString(resources.getString(R.string.user_message), errorMessage);
+ userNotificationBundle.putString(USER_MESSAGE, errorMessage);
} catch (JSONException e) {
e.printStackTrace();
}
@@ -418,7 +419,7 @@ public abstract class ProviderApiManagerBase {
if (result.has(BACKEND_ERROR_MESSAGE)) {
backendErrorMessage = resources.getString(R.string.error) + result.getString(BACKEND_ERROR_MESSAGE);
}
- userNotificationBundle.putString(resources.getString(R.string.user_message), backendErrorMessage);
+ userNotificationBundle.putString(USER_MESSAGE, backendErrorMessage);
} catch (JSONException e) {
e.printStackTrace();
}
@@ -431,7 +432,7 @@ public abstract class ProviderApiManagerBase {
return userNotificationBundle;
}
- void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) {
+ private void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) {
if (resultData == null || resultData == Bundle.EMPTY) {
resultData = new Bundle();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
index d41be512..15cd9617 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
@@ -30,6 +30,7 @@ import org.json.JSONException;
import butterknife.InjectView;
import butterknife.OnClick;
import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS;
+import se.leap.bitmaskclient.eip.EipCommand;
import se.leap.bitmaskclient.userstatus.User;
import static android.view.View.GONE;
@@ -41,9 +42,12 @@ import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.CREDENTIALS_PASSWORD;
import static se.leap.bitmaskclient.Constants.CREDENTIALS_USERNAME;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_KEY;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.LOG_IN;
import static se.leap.bitmaskclient.ProviderAPI.SIGN_UP;
+import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE;
/**
* Base Activity for activities concerning a provider interaction
@@ -59,7 +63,6 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
final private static String SHOWING_FORM = "SHOWING_FORM";
final private static String PERFORMING_ACTION = "PERFORMING_ACTION";
- final public static String USER_MESSAGE = "USER_MESSAGE";
final private static String USERNAME_ERROR = "USERNAME_ERROR";
final private static String PASSWORD_ERROR = "PASSWORD_ERROR";
final private static String PASSWORD_VERIFICATION_ERROR = "PASSWORD_VERIFICATION_ERROR";
@@ -183,7 +186,11 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
String username = usernameField.getText().toString();
String providerDomain = provider.getDomain();
if (username.endsWith(providerDomain)) {
- return username.split("@" + providerDomain)[0];
+ try {
+ return username.split("@" + providerDomain)[0];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "";
+ }
}
return username;
}
@@ -237,9 +244,15 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
@Override
public void afterTextChanged(Editable s) {
if (getUsername().equalsIgnoreCase("")) {
+ s.clear();
usernameError.setError(getString(R.string.username_ask));
} else {
usernameError.setError(null);
+ String suffix = "@" + provider.getDomain();
+ if (!usernameField.getText().toString().endsWith(suffix)) {
+ s.append(suffix);
+ usernameField.setSelection(usernameField.getText().toString().indexOf('@'));
+ }
}
}
});
@@ -344,8 +357,8 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
if (arguments.containsKey(CREDENTIAL_ERRORS.USERNAME_MISSING.toString())) {
usernameError.setError(getString(R.string.username_ask));
}
- if (arguments.containsKey(getString(R.string.user_message))) {
- String userMessageString = arguments.getString(getString(R.string.user_message));
+ if (arguments.containsKey(USER_MESSAGE)) {
+ String userMessageString = arguments.getString(USER_MESSAGE);
try {
userMessageString = new JSONArray(userMessageString).getString(0);
} catch (JSONException e) {
@@ -395,6 +408,10 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
switch (resultCode) {
case ProviderAPI.SUCCESSFUL_SIGNUP:
+ String password = resultData.getString(CREDENTIALS_PASSWORD);
+ String username = resultData.getString(CREDENTIALS_USERNAME);
+ login(username, password);
+ break;
case ProviderAPI.SUCCESSFUL_LOGIN:
downloadVpnCertificate(handledProvider);
break;
@@ -403,12 +420,11 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
handleReceivedErrors((Bundle) intent.getParcelableExtra(BROADCAST_RESULT_KEY));
break;
+ case ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE:
+ // error handling takes place in MainActivity
case ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE:
successfullyFinished(handledProvider);
break;
- case ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE:
- // TODO activity.setResult(RESULT_CANCELED);
- break;
}
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
index e961b0a2..75fffaf7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
@@ -207,7 +207,8 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
void handleProviderSetUp(Provider handledProvider) {
this.provider = handledProvider;
-
+ adapter.add(provider);
+ adapter.saveProviders();
if (provider.allowsAnonymous()) {
mConfigState.putExtra(SERVICES_RETRIEVED, true);
downloadVpnCertificate();
@@ -368,12 +369,6 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
}
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
- return true;
- }
-
public class ProviderAPIBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
index ed41be67..97ba3b98 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
@@ -31,6 +31,8 @@ public class ProviderManager implements AdapteeCollection<Provider> {
private File externalFilesDir;
private Set<Provider> defaultProviders;
private Set<Provider> customProviders;
+ private Set<URL> defaultProviderURLs;
+ private Set<URL> customProviderURLs;
private static ProviderManager instance;
@@ -52,11 +54,20 @@ public class ProviderManager implements AdapteeCollection<Provider> {
private void addDefaultProviders(AssetManager assets_manager) {
try {
defaultProviders = providersFromAssets(URLS, assets_manager.list(URLS));
+ defaultProviderURLs = getProviderUrlSetFromProviderSet(defaultProviders);
} catch (IOException e) {
e.printStackTrace();
}
}
+ private Set<URL> getProviderUrlSetFromProviderSet(Set<Provider> providers) {
+ HashSet<URL> providerUrls = new HashSet<>();
+ for (Provider provider : providers) {
+ providerUrls.add(provider.getMainUrl().getUrl());
+ }
+ return providerUrls;
+ }
+
private Set<Provider> providersFromAssets(String directory, String[] relativeFilePaths) {
Set<Provider> providers = new HashSet<>();
@@ -89,13 +100,14 @@ public class ProviderManager implements AdapteeCollection<Provider> {
customProviders = externalFilesDir != null && externalFilesDir.isDirectory() ?
providersFromFiles(externalFilesDir.list()) :
new HashSet<Provider>();
+ customProviderURLs = getProviderUrlSetFromProviderSet(customProviders);
}
private Set<Provider> providersFromFiles(String[] files) {
Set<Provider> providers = new HashSet<>();
try {
for (String file : files) {
- String mainUrl = extractMainUrlFromInputStream(new FileInputStream(externalFilesDir.getAbsolutePath() + "/" + file));
+ String mainUrl = extractMainUrlFromInputStream(ConfigHelper.getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file));
providers.add(new Provider(new URL(mainUrl)));
}
} catch (MalformedURLException | FileNotFoundException e) {
@@ -132,6 +144,8 @@ public class ProviderManager implements AdapteeCollection<Provider> {
allProviders.addAll(defaultProviders);
if(customProviders != null)
allProviders.addAll(customProviders);
+ //add an option to add a custom provider
+ //TODO: refactor me?
allProviders.add(new Provider());
return allProviders;
}
@@ -153,32 +167,59 @@ public class ProviderManager implements AdapteeCollection<Provider> {
@Override
public boolean add(Provider element) {
- return !defaultProviders.contains(element) || customProviders.add(element);
+ return element != null &&
+ !defaultProviderURLs.contains(element.getMainUrl().getUrl()) &&
+ customProviders.add(element) &&
+ customProviderURLs.add(element.getMainUrl().getUrl());
}
@Override
public boolean remove(Object element) {
- return customProviders.remove(element);
+ return element instanceof Provider &&
+ customProviders.remove(element) &&
+ customProviderURLs.remove(((Provider) element).getMainUrl().getUrl());
}
@Override
public boolean addAll(Collection<? extends Provider> elements) {
- return customProviders.addAll(elements);
+ Iterator iterator = elements.iterator();
+ boolean addedAll = true;
+ while (iterator.hasNext()) {
+ Provider p = (Provider) iterator.next();
+ addedAll = customProviders.add(p) &&
+ customProviderURLs.add(p.getMainUrl().getUrl()) &&
+ addedAll;
+ }
+ return addedAll;
}
@Override
public boolean removeAll(Collection<?> elements) {
- if(!elements.getClass().equals(Provider.class))
+ Iterator iterator = elements.iterator();
+ boolean removedAll = true;
+ try {
+ while (iterator.hasNext()) {
+ Provider p = (Provider) iterator.next();
+ removedAll = ((defaultProviders.remove(p) && defaultProviderURLs.remove(p.getMainUrl().getUrl())) ||
+ (customProviders.remove(p) && customProviderURLs.remove(p.getMainUrl().getUrl()))) &&
+ removedAll;
+ }
+ } catch (ClassCastException e) {
return false;
- return defaultProviders.removeAll(elements) || customProviders.removeAll(elements);
+ }
+
+ return removedAll;
}
@Override
public void clear() {
defaultProviders.clear();
customProviders.clear();
+ customProviderURLs.clear();
+ defaultProviderURLs.clear();
}
+ //FIXME: removed custom providers should be deleted here as well
void saveCustomProvidersToFile() {
try {
for (Provider provider : customProviders) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
index 39717bd8..6bbdeb4f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
@@ -13,12 +13,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EIP;
import se.leap.bitmaskclient.eip.EipCommand;
import se.leap.bitmaskclient.userstatus.User;
import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE;
-import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION;
import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
@@ -32,7 +30,7 @@ import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
* and acts and calls another activity accordingly.
*
*/
-public class StartActivity extends Activity {
+public class StartActivity extends Activity{
public static final String TAG = StartActivity.class.getSimpleName();
@Retention(RetentionPolicy.SOURCE)
@@ -184,12 +182,9 @@ public class StartActivity extends Activity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (data == null) {
- return;
- }
if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) {
- if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
+ if (resultCode == RESULT_OK && data != null && data.hasExtra(Provider.KEY)) {
Provider provider = data.getParcelableExtra(Provider.KEY);
ConfigHelper.storeProviderInPreferences(preferences, provider);
EipCommand.startVPN(this, false);
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 b7af5797..c09bda2d 100644
--- a/app/src/main/res/layout-xlarge/eip_service_fragment.xml
+++ b/app/src/main/res/layout-xlarge/eip_service_fragment.xml
@@ -54,7 +54,7 @@
app:srcCompat="@drawable/ic_colorsquare" />
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/eipLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -65,6 +65,7 @@
android:layout_marginRight="@dimen/stdpadding"
android:text="@string/eip_service_label"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -97,7 +98,7 @@
style="@style/BitmaskButtonBlack"
/>
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/routed_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -107,12 +108,13 @@
android:layout_marginLeft="@dimen/stdpadding"
android:layout_marginRight="@dimen/stdpadding"
android:text="@string/vpn_securely_routed"
+ android:gravity="center"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/eipLabel" />
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/vpn_route"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -120,6 +122,7 @@
android:layout_marginStart="@dimen/stdpadding"
android:layout_marginLeft="@dimen/stdpadding"
android:layout_marginRight="@dimen/stdpadding"
+ android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/routed_text" />
diff --git a/app/src/main/res/layout/eip_service_fragment.xml b/app/src/main/res/layout/eip_service_fragment.xml
index 814ec310..30b94de9 100644
--- a/app/src/main/res/layout/eip_service_fragment.xml
+++ b/app/src/main/res/layout/eip_service_fragment.xml
@@ -52,7 +52,7 @@
app:srcCompat="@drawable/ic_colorsquare" />
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/eipLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -63,6 +63,7 @@
android:layout_marginRight="@dimen/stdpadding"
android:text="@string/eip_service_label"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -97,7 +98,7 @@
style="@style/BitmaskButtonBlack"
/>
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/routed_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -107,12 +108,13 @@
android:layout_marginLeft="@dimen/stdpadding"
android:layout_marginRight="@dimen/stdpadding"
android:text="@string/vpn_securely_routed"
+ android:gravity="center"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/eipLabel" />
- <TextView
+ <android.support.v7.widget.AppCompatTextView
android:id="@+id/vpn_route"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -120,6 +122,7 @@
android:layout_marginStart="@dimen/stdpadding"
android:layout_marginLeft="@dimen/stdpadding"
android:layout_marginRight="@dimen/stdpadding"
+ android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/routed_text" />
diff --git a/app/src/main/res/menu/configuration_wizard_activity.xml b/app/src/main/res/menu/configuration_wizard_activity.xml
deleted file mode 100644
index 21591547..00000000
--- a/app/src/main/res/menu/configuration_wizard_activity.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <item
- android:id="@+id/about_leap"
- android:orderInCategory="110"
- android:title="@string/about"/>
-
- <item
- android:id="@+id/new_provider"
- android:orderInCategory="210"
- android:title="@string/add_provider"
- android:showAsAction="ifRoom|withText"
- android:icon="@drawable/ic_menu_add"
- />
-</menu> \ No newline at end of file