summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient/base/models
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2020-12-29 00:54:08 +0100
committercyBerta <cyberta@riseup.net>2020-12-29 00:54:08 +0100
commit6b032b751324a30120cfaabe88940f95171df11f (patch)
treeb6b26b84358726a02e27558562e7e9ea70a7aaa0 /app/src/main/java/se/leap/bitmaskclient/base/models
parent16da1eeb5180cbb4a0d916785a08ccbcd3c1d74e (diff)
new year cleanup: restructure messy project
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/base/models')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java168
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/DefaultedURL.java48
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java593
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java39
5 files changed, 854 insertions, 0 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
new file mode 100644
index 00000000..d649aaf5
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2020 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.base.models;
+
+import android.text.TextUtils;
+
+import se.leap.bitmaskclient.BuildConfig;
+
+public interface Constants {
+
+ //////////////////////////////////////////////
+ // PREFERENCES CONSTANTS
+ /////////////////////////////////////////////
+
+ String SHARED_PREFERENCES = "LEAPPreferences";
+ String PREFERENCES_APP_VERSION = "bitmask version";
+ String ALWAYS_ON_SHOW_DIALOG = "DIALOG.ALWAYS_ON_SHOW_DIALOG";
+ String CLEARLOG = "clearlogconnect";
+ String LAST_USED_PROFILE = "last_used_profile";
+ String EXCLUDED_APPS = "excluded_apps";
+ String USE_PLUGGABLE_TRANSPORTS = "usePluggableTransports";
+ String ALLOW_TETHERING_BLUETOOTH = "tethering_bluetooth";
+ String ALLOW_TETHERING_WIFI = "tethering_wifi";
+ String ALLOW_TETHERING_USB = "tethering_usb";
+ String SHOW_EXPERIMENTAL = "show_experimental";
+ String USE_IPv6_FIREWALL = "use_ipv6_firewall";
+ String RESTART_ON_UPDATE = "restart_on_update";
+ String LAST_UPDATE_CHECK = "last_update_check";
+
+
+ //////////////////////////////////////////////
+ // REQUEST CODE CONSTANTS
+ /////////////////////////////////////////////
+
+ String REQUEST_CODE_KEY = "request_code";
+ int REQUEST_CODE_CONFIGURE_LEAP = 0;
+ int REQUEST_CODE_SWITCH_PROVIDER = 1;
+ int REQUEST_CODE_LOG_IN = 2;
+ int REQUEST_CODE_ADD_PROVIDER = 3;
+ int REQUEST_CODE_REQUEST_UPDATE = 4;
+
+
+ //////////////////////////////////////////////
+ // APP CONSTANTS
+ /////////////////////////////////////////////
+
+ String APP_ACTION_QUIT = "quit";
+ String APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE = "configure always-on profile";
+ String DEFAULT_BITMASK = "normal";
+ String CUSTOM_BITMASK = "custom";
+ String DANGER_ON = "danger_on";
+
+
+ String ASK_TO_CANCEL_VPN = "ask_to_cancel_vpn";
+
+
+ //////////////////////////////////////////////
+ // EIP CONSTANTS
+ /////////////////////////////////////////////
+
+ String EIP_ACTION_CHECK_CERT_VALIDITY = "EIP.CHECK_CERT_VALIDITY";
+ String EIP_ACTION_START = "se.leap.bitmaskclient.EIP.START";
+ String EIP_ACTION_STOP = "se.leap.bitmaskclient.EIP.STOP";
+ String EIP_ACTION_IS_RUNNING = "se.leap.bitmaskclient.EIP.IS_RUNNING";
+ String EIP_ACTION_START_ALWAYS_ON_VPN = "se.leap.bitmaskclient.START_ALWAYS_ON_VPN";
+ String EIP_ACTION_START_BLOCKING_VPN = "se.leap.bitmaskclient.EIP_ACTION_START_BLOCKING_VPN";
+ String EIP_ACTION_STOP_BLOCKING_VPN = "se.leap.bitmaskclient.EIP_ACTION_STOP_BLOCKING_VPN";
+ String EIP_ACTION_PREPARE_VPN = "se.leap.bitmaskclient.EIP_ACTION_PREPARE_VPN";
+ String EIP_ACTION_CONFIGURE_TETHERING = "se.leap.bitmaskclient.EIP_ACTION_CONFIGURE_TETHERING";
+
+ String EIP_RECEIVER = "EIP.RECEIVER";
+ String EIP_REQUEST = "EIP.REQUEST";
+ String EIP_RESTART_ON_BOOT = "EIP.RESTART_ON_BOOT";
+ String EIP_IS_ALWAYS_ON = "EIP.EIP_IS_ALWAYS_ON";
+ String EIP_EARLY_ROUTES = "EIP.EARLY_ROUTES";
+ String EIP_N_CLOSEST_GATEWAY = "EIP.N_CLOSEST_GATEWAY";
+
+
+ //////////////////////////////////////////////
+ // PROVIDER CONSTANTS
+ /////////////////////////////////////////////
+
+ String PROVIDER_ALLOW_ANONYMOUS = "allow_anonymous";
+ String PROVIDER_ALLOWED_REGISTERED = "allow_registration";
+ String PROVIDER_VPN_CERTIFICATE = "cert";
+ String PROVIDER_PRIVATE_KEY = "Constants.PROVIDER_PRIVATE_KEY";
+ String PROVIDER_KEY = "Constants.PROVIDER_KEY";
+ String PROVIDER_CONFIGURED = "Constants.PROVIDER_CONFIGURED";
+ String PROVIDER_EIP_DEFINITION = "Constants.EIP_DEFINITION";
+ String PROVIDER_PROFILE_UUID = "Constants.PROVIDER_PROFILE_UUID";
+ String PROVIDER_PROFILE = "Constants.PROVIDER_PROFILE";
+
+ //////////////////////////////////////////////
+ // CREDENTIAL CONSTANTS
+ /////////////////////////////////////////////
+
+ String CREDENTIALS_USERNAME = "username";
+ String CREDENTIALS_PASSWORD = "password";
+
+ enum CREDENTIAL_ERRORS {
+ USERNAME_MISSING,
+ PASSWORD_INVALID_LENGTH,
+ RISEUP_WARNING
+ }
+
+ //////////////////////////////////////////////
+ // BROADCAST CONSTANTS
+ /////////////////////////////////////////////
+
+ String BROADCAST_EIP_EVENT = "BROADCAST.EIP_EVENT";
+ String BROADCAST_PROVIDER_API_EVENT = "BROADCAST.PROVIDER_API_EVENT";
+ String BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT = "BROADCAST.GATEWAY_SETUP_WATCHER_EVENT";
+ String BROADCAST_RESULT_CODE = "BROADCAST.RESULT_CODE";
+ String BROADCAST_RESULT_KEY = "BROADCAST.RESULT_KEY";
+ String BROADCAST_DOWNLOAD_SERVICE_EVENT = "BROADCAST.DOWNLOAD_SERVICE_EVENT";
+
+
+ //////////////////////////////////////////////
+ // ICS-OPENVPN CONSTANTS
+ /////////////////////////////////////////////
+ String DEFAULT_SHARED_PREFS_BATTERY_SAVER = "screenoff";
+
+ //////////////////////////////////////////////
+ // CUSTOM CONSTANTS
+ /////////////////////////////////////////////
+ boolean ENABLE_DONATION = BuildConfig.enable_donation;
+ boolean ENABLE_DONATION_REMINDER = BuildConfig.enable_donation_reminder;
+ int DONATION_REMINDER_DURATION = BuildConfig.donation_reminder_duration;
+ String DONATION_URL = TextUtils.isEmpty(BuildConfig.donation_url) ?
+ BuildConfig.default_donation_url : BuildConfig.donation_url;
+ String LAST_DONATION_REMINDER_DATE = "last_donation_reminder_date";
+ String FIRST_TIME_USER_DATE = "first_time_user_date";
+
+
+ //////////////////////////////////////////////
+ // JSON KEYS
+ /////////////////////////////////////////////
+ String IP_ADDRESS = "ip_address";
+ String REMOTE = "remote";
+ String PORTS = "ports";
+ String PROTOCOLS = "protocols";
+ String CAPABILITIES = "capabilities";
+ String TRANSPORT = "transport";
+ String TYPE = "type";
+ String OPTIONS = "options";
+ String VERSION = "version";
+ String NAME = "name";
+ String TIMEZONE = "timezone";
+ String LOCATIONS = "locations";
+ String LOCATION = "location";
+ String OPENVPN_CONFIGURATION = "openvpn_configuration";
+ String GATEWAYS = "gateways";
+ String HOST = "host";
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/DefaultedURL.java b/app/src/main/java/se/leap/bitmaskclient/base/models/DefaultedURL.java
new file mode 100644
index 00000000..4bb7e4ee
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/DefaultedURL.java
@@ -0,0 +1,48 @@
+package se.leap.bitmaskclient.base.models;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class DefaultedURL {
+ private URL DEFAULT_URL;
+ private String default_url = "https://example.net";
+
+ private URL url;
+
+ DefaultedURL() {
+ try {
+ DEFAULT_URL = new URL(default_url);
+ url = DEFAULT_URL;
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isDefault() { return url.equals(DEFAULT_URL); }
+
+ public void setUrl(URL url) {
+ this.url = url;
+ }
+
+ public String getDomain() {
+ return url.getHost();
+ }
+
+ public URL getUrl() {
+ return url;
+ }
+
+ @Override
+ public String toString() {
+ return url.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof DefaultedURL) {
+ return url.equals(((DefaultedURL) o).getUrl());
+ }
+ return false;
+ }
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java
new file mode 100644
index 00000000..7b3f1888
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java
@@ -0,0 +1,6 @@
+package se.leap.bitmaskclient.base.models;
+
+public interface FeatureVersionCode {
+ int RENAMED_EIP_IN_PREFERENCES = 132;
+ int GEOIP_SERVICE = 148;
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
new file mode 100644
index 00000000..97f1019b
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -0,0 +1,593 @@
+/**
+ * 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.base.models;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.gson.Gson;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
+import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES;
+import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGISTERED;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS;
+import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
+import static se.leap.bitmaskclient.base.models.Constants.TYPE;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
+
+/**
+ * @author Sean Leonard <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
+ */
+public final class Provider implements Parcelable {
+
+ private static long EIP_SERVICE_TIMEOUT = 1000 * 60 * 60 * 24 * 3;
+ private static long GEOIP_SERVICE_TIMEOUT = 1000 * 60 * 60;
+ private JSONObject definition = new JSONObject(); // Represents our Provider's provider.json
+ private JSONObject eipServiceJson = new JSONObject();
+ private JSONObject geoIpJson = new JSONObject();
+ private DefaultedURL mainUrl = new DefaultedURL();
+ private DefaultedURL apiUrl = new DefaultedURL();
+ private DefaultedURL geoipUrl = new DefaultedURL();
+ private String providerIp = "";
+ private String providerApiIp = "";
+ private String certificatePin = "";
+ private String certificatePinEncoding = "";
+ private String caCert = "";
+ private String apiVersion = "";
+ private String privateKey = "";
+ private String vpnCertificate = "";
+ private long lastEipServiceUpdate = 0L;
+ private long lastGeoIpUpdate = 0L;
+
+ private boolean allowAnonymous;
+ private boolean allowRegistered;
+
+ final public static String
+ API_URL = "api_uri",
+ API_VERSION = "api_version",
+ ALLOW_REGISTRATION = "allow_registration",
+ API_RETURN_SERIAL = "serial",
+ SERVICE = "service",
+ KEY = "provider",
+ CA_CERT = "ca_cert",
+ CA_CERT_URI = "ca_cert_uri",
+ CA_CERT_FINGERPRINT = "ca_cert_fingerprint",
+ NAME = "name",
+ DESCRIPTION = "description",
+ DOMAIN = "domain",
+ MAIN_URL = "main_url",
+ PROVIDER_IP = "provider_ip",
+ PROVIDER_API_IP = "provider_api_ip",
+ GEOIP_URL = "geoip_url";
+
+ private static final String API_TERM_NAME = "name";
+
+ public Provider() { }
+
+ public Provider(String mainUrl) {
+ this(mainUrl, null);
+ }
+
+ public Provider(String mainUrl, String geoipUrl) {
+ try {
+ this.mainUrl.setUrl(new URL(mainUrl));
+ } catch (MalformedURLException e) {
+ this.mainUrl = new DefaultedURL();
+ }
+ setGeoipUrl(geoipUrl);
+ }
+
+ public Provider(String mainUrl, String providerIp, String providerApiIp) {
+ this(mainUrl, null, providerIp, providerApiIp);
+ }
+
+ public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp) {
+ try {
+ this.mainUrl.setUrl(new URL(mainUrl));
+ if (providerIp != null) {
+ this.providerIp = providerIp;
+ }
+ if (providerApiIp != null) {
+ this.providerApiIp = providerApiIp;
+ }
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ return;
+ }
+ setGeoipUrl(geoipUrl);
+ }
+
+
+ public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp, String caCert, String definition) {
+ this(mainUrl, geoipUrl, providerIp, providerApiIp);
+ if (caCert != null) {
+ this.caCert = caCert;
+ }
+ if (definition != null) {
+ try {
+ define(new JSONObject(definition));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ public static final Parcelable.Creator<Provider> CREATOR
+ = new Parcelable.Creator<Provider>() {
+ public Provider createFromParcel(Parcel in) {
+ return new Provider(in);
+ }
+
+ public Provider[] newArray(int size) {
+ return new Provider[size];
+ }
+ };
+
+ public boolean isConfigured() {
+ return !mainUrl.isDefault() &&
+ !apiUrl.isDefault() &&
+ hasCaCert() &&
+ hasDefinition() &&
+ hasVpnCertificate() &&
+ hasEIP() &&
+ hasPrivateKey();
+ }
+
+ public boolean supportsPluggableTransports() {
+ try {
+ JSONArray gatewayJsons = eipServiceJson.getJSONArray(GATEWAYS);
+ for (int i = 0; i < gatewayJsons.length(); i++) {
+ JSONArray transports = gatewayJsons.getJSONObject(i).
+ getJSONObject(CAPABILITIES).
+ getJSONArray(TRANSPORT);
+ for (int j = 0; j < transports.length(); j++) {
+ if (OBFS4.toString().equals(transports.getJSONObject(j).getString(TYPE))) {
+ return true;
+ }
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ return false;
+ }
+
+ public String getIpForHostname(String host) {
+ if (host != null) {
+ if (host.equals(mainUrl.getUrl().getHost())) {
+ return providerIp;
+ } else if (host.equals(apiUrl.getUrl().getHost())) {
+ return providerApiIp;
+ }
+ }
+ return "";
+ }
+
+ public String getProviderApiIp() {
+ return this.providerApiIp;
+ }
+
+ public void setProviderApiIp(String providerApiIp) {
+ if (providerApiIp == null) return;
+ this.providerApiIp = providerApiIp;
+ }
+
+ public void setProviderIp(String providerIp) {
+ if (providerIp == null) return;
+ this.providerIp = providerIp;
+ }
+
+ public String getProviderIp() {
+ return this.providerIp;
+ }
+
+ public void setMainUrl(URL url) {
+ mainUrl.setUrl(url);
+ }
+
+ public void setMainUrl(String url) {
+ try {
+ mainUrl.setUrl(new URL(url));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean define(JSONObject providerJson) {
+ definition = providerJson;
+ return parseDefinition(definition);
+ }
+
+ public JSONObject getDefinition() {
+ return definition;
+ }
+
+ public String getDefinitionString() {
+ return getDefinition().toString();
+ }
+
+ public String getDomain() {
+ return mainUrl.getDomain();
+ }
+
+ public String getMainUrlString() {
+ return getMainUrl().toString();
+ }
+
+ public DefaultedURL getMainUrl() {
+ return mainUrl;
+ }
+
+ protected DefaultedURL getApiUrl() {
+ return apiUrl;
+ }
+
+ public DefaultedURL getGeoipUrl() {
+ return geoipUrl;
+ }
+
+ public void setGeoipUrl(String url) {
+ try {
+ this.geoipUrl.setUrl(new URL(url));
+ } catch (MalformedURLException e) {
+ this.geoipUrl = new DefaultedURL();
+ }
+ }
+
+ public String getApiUrlWithVersion() {
+ return getApiUrlString() + "/" + getApiVersion();
+ }
+
+
+ public String getApiUrlString() {
+ return getApiUrl().toString();
+ }
+
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ public boolean hasCaCert() {
+ return caCert != null && !caCert.isEmpty();
+ }
+
+ public boolean hasDefinition() {
+ return definition != null && definition.length() > 0;
+ }
+
+ public boolean hasGeoIpJson() {
+ return geoIpJson != null && geoIpJson.length() > 0;
+ }
+
+
+ public String getCaCert() {
+ return caCert;
+ }
+
+ public String getName() {
+ // Should we pass the locale in, or query the system here?
+ String lang = Locale.getDefault().getLanguage();
+ String name = "";
+ try {
+ if (definition != null)
+ name = definition.getJSONObject(API_TERM_NAME).getString(lang);
+ else throw new JSONException("Provider not defined");
+ } catch (JSONException e) {
+ try {
+ name = definition.getJSONObject(API_TERM_NAME).getString("en");
+ } catch (JSONException e2) {
+ if (mainUrl != null) {
+ String host = mainUrl.getDomain();
+ name = host.substring(0, host.indexOf("."));
+ }
+ }
+ }
+
+ return name;
+ }
+
+ public String getDescription() {
+ String lang = Locale.getDefault().getLanguage();
+ String desc = null;
+ try {
+ desc = definition.getJSONObject("description").getString(lang);
+ } catch (JSONException e) {
+ // TODO: handle exception!!
+ try {
+ desc = definition.getJSONObject("description").getString(definition.getString("default_language"));
+ } catch (JSONException e2) {
+ // TODO: i can't believe you're doing it again!
+ }
+ }
+
+ return desc;
+ }
+
+ public boolean hasEIP() {
+ return getEipServiceJson() != null && getEipServiceJson().length() > 0
+ && !getEipServiceJson().has(ERRORS);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(getMainUrlString());
+ parcel.writeString(getProviderIp());
+ parcel.writeString(getProviderApiIp());
+ parcel.writeString(getGeoipUrl().toString());
+ parcel.writeString(getDefinitionString());
+ parcel.writeString(getCaCert());
+ parcel.writeString(getEipServiceJsonString());
+ parcel.writeString(getGeoIpJsonString());
+ parcel.writeString(getPrivateKey());
+ parcel.writeString(getVpnCertificate());
+ parcel.writeLong(lastEipServiceUpdate);
+ parcel.writeLong(lastGeoIpUpdate);
+ }
+
+
+ //TODO: write a test for marshalling!
+ private Provider(Parcel in) {
+ try {
+ mainUrl.setUrl(new URL(in.readString()));
+ String tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ providerIp = tmpString;
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ providerApiIp = tmpString;
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ geoipUrl.setUrl(new URL(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ definition = new JSONObject((tmpString));
+ parseDefinition(definition);
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.caCert = tmpString;
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setEipServiceJson(new JSONObject(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setGeoIpJson(new JSONObject(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setPrivateKey(tmpString);
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setVpnCertificate(tmpString);
+ }
+ this.lastEipServiceUpdate = in.readLong();
+ this.lastGeoIpUpdate = in.readLong();
+ } catch (MalformedURLException | JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Provider) {
+ Provider p = (Provider) o;
+ return p.getDomain().equals(getDomain()) &&
+ definition.toString().equals(p.getDefinition().toString()) &&
+ eipServiceJson.toString().equals(p.getEipServiceJsonString()) &&
+ geoIpJson.toString().equals(p.getGeoIpJsonString()) &&
+ providerIp.equals(p.getProviderIp()) &&
+ providerApiIp.equals(p.getProviderApiIp()) &&
+ apiUrl.equals(p.getApiUrl()) &&
+ geoipUrl.equals(p.getGeoipUrl()) &&
+ certificatePin.equals(p.getCertificatePin()) &&
+ certificatePinEncoding.equals(p.getCertificatePinEncoding()) &&
+ caCert.equals(p.getCaCert()) &&
+ apiVersion.equals(p.getApiVersion()) &&
+ privateKey.equals(p.getPrivateKey()) &&
+ vpnCertificate.equals(p.getVpnCertificate()) &&
+ allowAnonymous == p.allowsAnonymous() &&
+ allowRegistered == p.allowsRegistered();
+ } else return false;
+ }
+
+
+ public JSONObject toJson() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put(Provider.MAIN_URL, mainUrl);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ @Override
+ public int hashCode() {
+ return getDomain().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new Gson().toJson(this);
+ }
+
+ private boolean parseDefinition(JSONObject definition) {
+ try {
+ String pin = definition.getString(CA_CERT_FINGERPRINT);
+ this.certificatePin = pin.split(":")[1].trim();
+ this.certificatePinEncoding = pin.split(":")[0].trim();
+ this.apiUrl.setUrl(new URL(definition.getString(API_URL)));
+ 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) {
+ return false;
+ }
+ }
+
+ public void setCaCert(String cert) {
+ this.caCert = cert;
+ }
+
+ public boolean allowsAnonymous() {
+ return allowAnonymous;
+ }
+
+ public boolean allowsRegistered() {
+ return allowRegistered;
+ }
+
+ public void setLastEipServiceUpdate(long timestamp) {
+ lastEipServiceUpdate = timestamp;
+ }
+
+ public boolean shouldUpdateEipServiceJson() {
+ return System.currentTimeMillis() - lastEipServiceUpdate >= EIP_SERVICE_TIMEOUT;
+ }
+
+
+ public void setLastGeoIpUpdate(long timestamp) {
+ lastGeoIpUpdate = timestamp;
+ }
+
+ public boolean shouldUpdateGeoIpJson() {
+ return System.currentTimeMillis() - lastGeoIpUpdate >= GEOIP_SERVICE_TIMEOUT;
+ }
+
+
+ public boolean setEipServiceJson(JSONObject eipServiceJson) {
+ if (eipServiceJson.has(ERRORS)) {
+ return false;
+ }
+ this.eipServiceJson = eipServiceJson;
+ return true;
+ }
+
+ public boolean setGeoIpJson(JSONObject geoIpJson) {
+ if (geoIpJson.has(ERRORS)) {
+ return false;
+ }
+ this.geoIpJson = geoIpJson;
+ return true;
+ }
+
+ public JSONObject getEipServiceJson() {
+ return eipServiceJson;
+ }
+
+ public JSONObject getGeoIpJson() {
+ return geoIpJson;
+ }
+
+ public String getGeoIpJsonString() {
+ return geoIpJson.toString();
+ }
+
+ public String getEipServiceJsonString() {
+ return getEipServiceJson().toString();
+ }
+
+ public boolean isDefault() {
+ return getMainUrl().isDefault() &&
+ getApiUrl().isDefault() &&
+ getGeoipUrl().isDefault() &&
+ certificatePin.isEmpty() &&
+ certificatePinEncoding.isEmpty() &&
+ caCert.isEmpty();
+ }
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public void setPrivateKey(String privateKey) {
+ this.privateKey = privateKey;
+ }
+
+ public boolean hasPrivateKey() {
+ return privateKey != null && privateKey.length() > 0;
+ }
+
+ public String getVpnCertificate() {
+ return vpnCertificate;
+ }
+
+ public void setVpnCertificate(String vpnCertificate) {
+ this.vpnCertificate = vpnCertificate;
+ }
+
+ public boolean hasVpnCertificate() {
+ return getVpnCertificate() != null && getVpnCertificate().length() >0 ;
+ }
+
+ public String getCertificatePin() {
+ return certificatePin;
+ }
+
+ public String getCertificatePinEncoding() {
+ return certificatePinEncoding;
+ }
+
+ public String getCaCertFingerprint() {
+ return getCertificatePinEncoding() + ":" + getCertificatePin();
+ }
+
+ /**
+ * resets everything except the main url, the providerIp and the geoip
+ * service url (currently preseeded)
+ */
+ public void reset() {
+ definition = new JSONObject();
+ eipServiceJson = new JSONObject();
+ geoIpJson = new JSONObject();
+ apiUrl = new DefaultedURL();
+ certificatePin = "";
+ certificatePinEncoding = "";
+ caCert = "";
+ apiVersion = "";
+ privateKey = "";
+ vpnCertificate = "";
+ allowRegistered = false;
+ allowAnonymous = false;
+ lastGeoIpUpdate = 0L;
+ lastEipServiceUpdate = 0L;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java
new file mode 100644
index 00000000..19555504
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java
@@ -0,0 +1,39 @@
+package se.leap.bitmaskclient.base.models;
+
+import java.util.Observable;
+
+/**
+ * Created by cyberta on 05.12.18.
+ */
+public class ProviderObservable extends Observable {
+ private static ProviderObservable instance;
+ private Provider currentProvider;
+ private Provider providerForDns;
+
+ public static ProviderObservable getInstance() {
+ if (instance == null) {
+ instance = new ProviderObservable();
+ }
+ return instance;
+ }
+
+ public synchronized void updateProvider(Provider provider) {
+ instance.currentProvider = provider;
+ instance.providerForDns = null;
+ instance.setChanged();
+ instance.notifyObservers();
+ }
+
+ public Provider getCurrentProvider() {
+ return instance.currentProvider;
+ }
+
+ public void setProviderForDns(Provider provider) {
+ this.providerForDns = provider;
+ }
+
+ public Provider getProviderForDns() {
+ return instance.providerForDns;
+ }
+
+}