From 08ed7bcd70750b066af2a6d6845d6bd904981e2a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:33:35 +0100 Subject: add MotdClient, a Java wrapper around golang's motd --- .../se/leap/bitmaskclient/motd/MotdClient.java | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 app/src/main/java/se/leap/bitmaskclient/motd/MotdClient.java diff --git a/app/src/main/java/se/leap/bitmaskclient/motd/MotdClient.java b/app/src/main/java/se/leap/bitmaskclient/motd/MotdClient.java new file mode 100644 index 00000000..d80a8992 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/motd/MotdClient.java @@ -0,0 +1,47 @@ +package se.leap.bitmaskclient.motd; + +import androidx.annotation.WorkerThread; + +import org.json.JSONException; +import org.json.JSONObject; + +import de.blinkt.openvpn.core.VpnStatus; +import motd.IMessages; +import motd.IMotd; +import motd.Motd; +import se.leap.bitmaskclient.base.models.Provider; + +public class MotdClient { + IMotd motd; + + public MotdClient(Provider provider) { + motd = Motd.newMotd(provider.getMotdUrl().toString(), provider.getName(), "android"); + } + + @WorkerThread + public IMessages fetch() { + if (!VpnStatus.isVPNActive()) { + VpnStatus.logError("Tried to fetch Message of the Day while VPN was off."); + return null; + } + + return Motd.newMessages(motd.fetchLatestAsJson()); + } + + @WorkerThread + public JSONObject fetchJson() { + if (!VpnStatus.isVPNActive()) { + VpnStatus.logError("Tried to fetch Message of the Day while VPN was off."); + return null; + } + + try { + return new JSONObject(motd.fetchLatestAsJson()); + } catch (NullPointerException | JSONException e) { + e.printStackTrace(); + return null; + } + + } + +} -- cgit v1.2.3 From 7c8bcb7efe39ce62fb19f90ad5c758d522be64a0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:35:02 +0100 Subject: add BuildConfig field to set motd url in custom branded clients --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 239190fd..1e17f01d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,6 +68,7 @@ android { buildConfigField "String", "customProviderIp", '""' buildConfigField "String", "customProviderApiIp", '""' buildConfigField "String", "geoipUrl", '""' + buildConfigField "String", "customProviderMotdUrl", '""' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dexOptions { @@ -133,6 +134,9 @@ android { buildConfigField "String", "customProviderApiIp", customProviderApiIp def geoipUrl = '"https://api.black.riseup.net:9001/json"' buildConfigField "String", "geoipUrl", geoipUrl + //URL for the message of the day, see https://0xacab.org/leap/motd#motd-message-of-the-day + def customProviderMotdUrl = '"https://static.riseup.net/vpn/motd.json"' + buildConfigField "String", "customProviderMotdUrl", customProviderMotdUrl //Change the versionCode as needed //versionCode 1 //Change the versionName as needed -- cgit v1.2.3 From 5955d67700ef6d674c50202247ab21d0de83048d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:43:18 +0100 Subject: add motd properties to Provider model --- .../leap/bitmaskclient/base/models/Provider.java | 156 ++++++++++++++++++--- 1 file changed, 135 insertions(+), 21 deletions(-) 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 index 13463167..b0f3d09f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -16,8 +16,23 @@ */ package se.leap.bitmaskclient.base.models; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; +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.LOCATIONS; +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.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; + import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; + +import androidx.annotation.NonNull; import com.google.gson.Gson; @@ -27,22 +42,14 @@ import org.json.JSONObject; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; -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.LOCATIONS; -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.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; - -import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Connection.TransportType; +import motd.IStringCollection; +import motd.Motd; /** * @author Sean Leonard @@ -50,14 +57,17 @@ import de.blinkt.openvpn.core.connection.Connection.TransportType; */ 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 static final long EIP_SERVICE_TIMEOUT = 1000 * 60 * 60 * 24 * 3; + private static final long GEOIP_SERVICE_TIMEOUT = 1000 * 60 * 60; + private static final long MOTD_TIMEOUT = 1000 * 60 * 60 * 24; private JSONObject definition = new JSONObject(); // Represents our Provider's provider.json private JSONObject eipServiceJson = new JSONObject(); private JSONObject geoIpJson = new JSONObject(); + private JSONObject motdJson = new JSONObject(); private DefaultedURL mainUrl = new DefaultedURL(); private DefaultedURL apiUrl = new DefaultedURL(); private DefaultedURL geoipUrl = new DefaultedURL(); + private DefaultedURL motdUrl = new DefaultedURL(); private String domain = ""; private String providerIp = ""; // ip of the provider main url private String providerApiIp = ""; // ip of the provider api url @@ -69,6 +79,9 @@ public final class Provider implements Parcelable { private String vpnCertificate = ""; private long lastEipServiceUpdate = 0L; private long lastGeoIpUpdate = 0L; + private long lastMotdUpdate = 0L; + private long lastMotdSeen = 0L; + private Set lastMotdSeenHashes = new HashSet<>(); private boolean shouldUpdateVpnCertificate; private boolean allowAnonymous; @@ -90,7 +103,8 @@ public final class Provider implements Parcelable { MAIN_URL = "main_url", PROVIDER_IP = "provider_ip", PROVIDER_API_IP = "provider_api_ip", - GEOIP_URL = "geoip_url"; + GEOIP_URL = "geoip_url", + MOTD_URL = "motd_url"; private static final String API_TERM_NAME = "name"; @@ -110,10 +124,10 @@ public final class Provider implements Parcelable { } public Provider(String mainUrl, String providerIp, String providerApiIp) { - this(mainUrl, null, providerIp, providerApiIp); + this(mainUrl, null, null, providerIp, providerApiIp); } - public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp) { + public Provider(String mainUrl, String geoipUrl, String motdUrl, String providerIp, String providerApiIp) { try { this.mainUrl.setUrl(new URL(mainUrl)); if (providerIp != null) { @@ -127,11 +141,11 @@ public final class Provider implements Parcelable { return; } setGeoipUrl(geoipUrl); + setMotdUrl(motdUrl); } - - public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp, String caCert, String definition) { - this(mainUrl, geoipUrl, providerIp, providerApiIp); + public Provider(String mainUrl, String geoipUrl, String motdUrl, String providerIp, String providerApiIp, String caCert, String definition) { + this(mainUrl, geoipUrl, motdUrl, providerIp, providerApiIp); if (caCert != null) { this.caCert = caCert; } @@ -281,6 +295,21 @@ public final class Provider implements Parcelable { } } + public DefaultedURL getMotdUrl() { + return this.motdUrl; + } + + public void setMotdUrl(String url) { + try { + this.motdUrl.setUrl(new URL(url)); + Log.d("PROVIDER", "setMotdUrl provider: " + this.domain + " - motd url: " + motdUrl.toString()); + } catch (MalformedURLException e) { + e.printStackTrace(); + Log.d("PROVIDER", "setMotdUrl exception!!! provider: " + this.domain + " - motd url: " + motdUrl.toString() + " obj:" + this.toString()); + this.motdUrl = new DefaultedURL(); + } + } + public String getApiUrlWithVersion() { return getApiUrlString() + "/" + getApiVersion(); } @@ -375,14 +404,19 @@ public final class Provider implements Parcelable { parcel.writeString(getProviderIp()); parcel.writeString(getProviderApiIp()); parcel.writeString(getGeoipUrl().toString()); + parcel.writeString(getMotdUrl().toString()); parcel.writeString(getDefinitionString()); parcel.writeString(getCaCert()); parcel.writeString(getEipServiceJsonString()); parcel.writeString(getGeoIpJsonString()); + parcel.writeString(getMotdJsonString()); parcel.writeString(getPrivateKey()); parcel.writeString(getVpnCertificate()); parcel.writeLong(lastEipServiceUpdate); parcel.writeLong(lastGeoIpUpdate); + parcel.writeLong(lastMotdUpdate); + parcel.writeLong(lastMotdSeen); + parcel.writeStringList(new ArrayList<>(lastMotdSeenHashes)); parcel.writeInt(shouldUpdateVpnCertificate ? 0 : 1); } @@ -405,6 +439,10 @@ public final class Provider implements Parcelable { geoipUrl.setUrl(new URL(tmpString)); } tmpString = in.readString(); + if (!tmpString.isEmpty()) { + motdUrl.setUrl(new URL(tmpString)); + } + tmpString = in.readString(); if (!tmpString.isEmpty()) { definition = new JSONObject((tmpString)); parseDefinition(definition); @@ -422,6 +460,10 @@ public final class Provider implements Parcelable { this.setGeoIpJson(new JSONObject(tmpString)); } tmpString = in.readString(); + if (!tmpString.isEmpty()) { + this.setMotdJson(new JSONObject(tmpString)); + } + tmpString = in.readString(); if (!tmpString.isEmpty()) { this.setPrivateKey(tmpString); } @@ -431,6 +473,11 @@ public final class Provider implements Parcelable { } this.lastEipServiceUpdate = in.readLong(); this.lastGeoIpUpdate = in.readLong(); + this.lastMotdUpdate = in.readLong(); + this.lastMotdSeen = in.readLong(); + ArrayList lastMotdSeenHashes = new ArrayList<>(); + in.readStringList(lastMotdSeenHashes); + this.lastMotdSeenHashes = new HashSet<>(lastMotdSeenHashes); this.shouldUpdateVpnCertificate = in.readInt() == 0; } catch (MalformedURLException | JSONException e) { e.printStackTrace(); @@ -447,10 +494,12 @@ public final class Provider implements Parcelable { definition.toString().equals(p.getDefinition().toString()) && eipServiceJson.toString().equals(p.getEipServiceJsonString()) && geoIpJson.toString().equals(p.getGeoIpJsonString()) && + motdJson.toString().equals(p.getMotdJsonString()) && providerIp.equals(p.getProviderIp()) && providerApiIp.equals(p.getProviderApiIp()) && apiUrl.equals(p.getApiUrl()) && geoipUrl.equals(p.getGeoipUrl()) && + motdUrl.equals(p.getMotdUrl()) && certificatePin.equals(p.getCertificatePin()) && certificatePinEncoding.equals(p.getCertificatePinEncoding()) && caCert.equals(p.getCaCert()) && @@ -527,6 +576,70 @@ public final class Provider implements Parcelable { return shouldUpdateVpnCertificate; } + public void setLastMotdSeen(long timestamp) { + lastMotdSeen = timestamp; + } + + public long getLastMotdSeen() { + return lastMotdSeen; + } + + /** + * shouldShowMotdSeen + * @return true if last message of the day was shown more than 24h ago + */ + public boolean shouldShowMotdSeen() { + return !motdUrl.isDefault() && System.currentTimeMillis() - lastMotdSeen >= MOTD_TIMEOUT; + } + + /** + * setLastSeenHashes + * @param hashes hashes of messages of type 'once' that have already been seen + */ + public void setMotdLastSeenHashes(Set hashes) { + lastMotdSeenHashes = hashes; + } + + public Set getMotdLastSeenHashes() { + return lastMotdSeenHashes; + } + + /** + * getLastSeenHashCollection + * @return go ffi compatible IStringCollection interface of message hashes of type 'once' + */ + public IStringCollection getMotdLastSeenHashCollection() { + IStringCollection stringCollection = Motd.newStringCollection(); + for (String hash : lastMotdSeenHashes) { + stringCollection.add(hash); + } + return stringCollection; + } + + public void setLastMotdUpdate(long timestamp) { + lastMotdUpdate = timestamp; + } + + public long getLastMotdUpdate() { + return lastMotdUpdate; + } + + public boolean shouldUpdateMotdJson() { + return !motdUrl.isDefault() && System.currentTimeMillis() - lastMotdUpdate >= MOTD_TIMEOUT; + } + + public void setMotdJson(@NonNull JSONObject motdJson) { + this.motdJson = motdJson; + } + + public JSONObject getMotdJson() { + return motdJson; + } + + public String getMotdJsonString() { + return motdJson.toString(); + } + public void setLastGeoIpUpdate(long timestamp) { lastGeoIpUpdate = timestamp; } @@ -621,6 +734,7 @@ public final class Provider implements Parcelable { definition = new JSONObject(); eipServiceJson = new JSONObject(); geoIpJson = new JSONObject(); + motdJson = new JSONObject(); apiUrl = new DefaultedURL(); certificatePin = ""; certificatePinEncoding = ""; -- cgit v1.2.3 From 5af434e68ccc24858083e247690bc1948741bebb Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:44:55 +0100 Subject: set motd url for Riseup in Bitmask --- app/src/normal/assets/urls/riseup.net.url | 3 ++- app/src/normalProductionFatDebug/assets/urls/riseup.net.url | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/normal/assets/urls/riseup.net.url b/app/src/normal/assets/urls/riseup.net.url index a33898c4..ad24ee99 100644 --- a/app/src/normal/assets/urls/riseup.net.url +++ b/app/src/normal/assets/urls/riseup.net.url @@ -2,5 +2,6 @@ "main_url" : "https://black.riseup.net", "provider_ip" : "198.252.153.70", "provider_api_ip" : "198.252.153.107", - "geoip_url" : "https://api.black.riseup.net:9001/json" + "geoip_url" : "https://api.black.riseup.net:9001/json", + "motd_url": "https://static.riseup.net/vpn/motd.json" } diff --git a/app/src/normalProductionFatDebug/assets/urls/riseup.net.url b/app/src/normalProductionFatDebug/assets/urls/riseup.net.url index a33898c4..ad24ee99 100644 --- a/app/src/normalProductionFatDebug/assets/urls/riseup.net.url +++ b/app/src/normalProductionFatDebug/assets/urls/riseup.net.url @@ -2,5 +2,6 @@ "main_url" : "https://black.riseup.net", "provider_ip" : "198.252.153.70", "provider_api_ip" : "198.252.153.107", - "geoip_url" : "https://api.black.riseup.net:9001/json" + "geoip_url" : "https://api.black.riseup.net:9001/json", + "motd_url": "https://static.riseup.net/vpn/motd.json" } -- cgit v1.2.3 From f0d45d2ad5e593212d6b7a4a89ac9ff318b86b8b Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:46:29 +0100 Subject: parse motd url from assets folder and initialize Provider accordingly --- .../java/se/leap/bitmaskclient/providersetup/ProviderManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java index 88413087..1ae2a033 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java @@ -24,6 +24,7 @@ import static se.leap.bitmaskclient.base.models.Constants.EXT_PEM; import static se.leap.bitmaskclient.base.models.Constants.URLS; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; import static se.leap.bitmaskclient.base.models.Provider.MAIN_URL; +import static se.leap.bitmaskclient.base.models.Provider.MOTD_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; import static se.leap.bitmaskclient.base.utils.FileHelper.createFile; @@ -91,6 +92,7 @@ public class ProviderManager implements AdapteeCollection { String certificate = null; String providerDefinition = null; String geoipUrl = null; + String motdUrl = null; try { String provider = file.substring(0, file.length() - ".url".length()); InputStream providerFile = assetsManager.open(directory + "/" + file); @@ -98,12 +100,13 @@ public class ProviderManager implements AdapteeCollection { providerIp = extractKeyFromInputStream(providerFile, PROVIDER_IP); providerApiIp = extractKeyFromInputStream(providerFile, PROVIDER_API_IP); geoipUrl = extractKeyFromInputStream(providerFile, GEOIP_URL); + motdUrl = extractKeyFromInputStream(providerFile, MOTD_URL); certificate = loadInputStreamAsString(assetsManager.open(provider + EXT_PEM)); providerDefinition = loadInputStreamAsString(assetsManager.open(provider + EXT_JSON)); } catch (IOException e) { e.printStackTrace(); } - providers.add(new Provider(mainUrl, geoipUrl, providerIp, providerApiIp, certificate, providerDefinition)); + providers.add(new Provider(mainUrl, geoipUrl, motdUrl, providerIp, providerApiIp, certificate, providerDefinition)); } return providers; -- cgit v1.2.3 From 952b8533a0d8fad9dec20d2ac10834628fbaab4e Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:47:11 +0100 Subject: fix TestSetupHelper after updating Provider model --- .../sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java index 0fdc94ca..72791ba6 100644 --- a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java +++ b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java @@ -84,6 +84,7 @@ public class TestSetupHelper { Provider p = new Provider( domain, geoipUrl, + null, providerIp, providerApiIp, getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)), -- cgit v1.2.3 From 853f6a4ac44ba9804ccc4572fb565e9a2cacf6d2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:48:01 +0100 Subject: add missing motd constants --- app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 index fd9f2a9b..d0af8112 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -53,7 +53,7 @@ public interface Constants { String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location"; - ////////////////////////////////////////////// + ////////////////////////////////////////////// // REQUEST CODE CONSTANTS ///////////////////////////////////////////// @@ -114,6 +114,10 @@ public interface Constants { String PROVIDER_EIP_DEFINITION = "Constants.EIP_DEFINITION"; String PROVIDER_PROFILE_UUID = "Constants.PROVIDER_PROFILE_UUID"; String PROVIDER_PROFILE = "Constants.PROVIDER_PROFILE"; + String PROVIDER_MOTD = "Constants.PROVIDER_MOTD"; + String PROVIDER_MOTD_HASHES = "Constants.PROVIDER_MOTD_HASHES"; + String PROVIDER_MOTD_LAST_SEEN = "Constants.PROVIDER_MOTD_LAST_SEEN"; + String PROVIDER_MOTD_LAST_UPDATED = "Constants.PROVIDER_MOTD_LAST_UPDATED"; //////////////////////////////////////////////// // PRESHIPPED PROVIDER CONFIG -- cgit v1.2.3 From 6ea9aa6601624e33b7b7f5377ce1ac49d714020d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 01:50:31 +0100 Subject: initialize custom branded Provider model with motd url --- .../providersetup/activities/CustomProviderSetupActivity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java index 0fff1ee2..9cd46049 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java @@ -36,6 +36,7 @@ import se.leap.bitmaskclient.providersetup.ProviderAPICommand; import static se.leap.bitmaskclient.BuildConfig.customProviderApiIp; import static se.leap.bitmaskclient.BuildConfig.customProviderIp; +import static se.leap.bitmaskclient.BuildConfig.customProviderMotdUrl; import static se.leap.bitmaskclient.BuildConfig.customProviderUrl; import static se.leap.bitmaskclient.BuildConfig.geoipUrl; import static se.leap.bitmaskclient.base.models.Constants.EXT_JSON; @@ -72,7 +73,7 @@ public class CustomProviderSetupActivity extends ProviderSetupBaseActivity { private void setDefaultProvider() { try { AssetManager assetsManager = getAssets(); - Provider customProvider = new Provider(customProviderUrl, geoipUrl, customProviderIp, customProviderApiIp); + Provider customProvider = new Provider(customProviderUrl, geoipUrl, customProviderMotdUrl, customProviderIp, customProviderApiIp); String domain = ConfigHelper.getDomainFromMainURL(customProviderUrl); String certificate = loadInputStreamAsString(assetsManager.open(domain + EXT_PEM)); String providerDefinition = loadInputStreamAsString(assetsManager.open(domain + EXT_JSON)); @@ -81,7 +82,7 @@ public class CustomProviderSetupActivity extends ProviderSetupBaseActivity { setProvider(customProvider); } catch (IOException | JSONException e) { e.printStackTrace(); - setProvider(new Provider(customProviderUrl, geoipUrl, customProviderIp, customProviderApiIp)); + setProvider(new Provider(customProviderUrl, geoipUrl, customProviderMotdUrl, customProviderIp, customProviderApiIp)); } } -- cgit v1.2.3 From c6435f2e9831b6c99836701b42a45a10ea81bb61 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 02:15:20 +0100 Subject: implement motd download in ProviderAPI Service, persist motd --- .../bitmaskclient/base/utils/PreferenceHelper.java | 70 +++++++++++++++++++--- .../bitmaskclient/providersetup/ProviderAPI.java | 1 + .../providersetup/ProviderApiManagerBase.java | 48 ++++++++++++++- 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 4abeed1a..76e54794 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -20,6 +20,10 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.RESTART_ON_UPDATE; @@ -62,11 +66,16 @@ public class PreferenceHelper { provider.setProviderIp(preferences.getString(Provider.PROVIDER_IP, "")); provider.setProviderApiIp(preferences.getString(Provider.PROVIDER_API_IP, "")); provider.setGeoipUrl(preferences.getString(Provider.GEOIP_URL, "")); + provider.setMotdUrl(preferences.getString(Provider.MOTD_URL, "")); provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); provider.setCaCert(preferences.getString(Provider.CA_CERT, "")); provider.setVpnCertificate(preferences.getString(PROVIDER_VPN_CERTIFICATE, "")); provider.setPrivateKey(preferences.getString(PROVIDER_PRIVATE_KEY, "")); provider.setEipServiceJson(new JSONObject(preferences.getString(PROVIDER_EIP_DEFINITION, ""))); + provider.setMotdJson(new JSONObject(preferences.getString(PROVIDER_MOTD, ""))); + provider.setLastMotdSeen(preferences.getLong(PROVIDER_MOTD_LAST_SEEN, 0L)); + provider.setLastMotdUpdate(preferences.getLong(PROVIDER_MOTD_LAST_UPDATED, 0L)); + provider.setMotdLastSeenHashes(preferences.getStringSet(PROVIDER_MOTD_HASHES, new HashSet<>())); } catch (MalformedURLException | JSONException e) { e.printStackTrace(); } @@ -78,12 +87,31 @@ public class PreferenceHelper { return preferences.getString(toFetch + "." + providerDomain, ""); } + public static long getLongFromPersistedProvider(String toFetch, String providerDomain, SharedPreferences preferences) { + return preferences.getLong(toFetch + "." + providerDomain, 0L); + } + + public static Set getStringSetFromPersistedProvider(String toFetch, String providerDomain, SharedPreferences preferences) { + return preferences.getStringSet(toFetch + "." + providerDomain, new HashSet<>()); + } + + public static void persistProvider(Context context, Provider provider) { + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + storeProviderInPreferences(preferences, provider, true); + } + + public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { + storeProviderInPreferences(preferences, provider, false); + } + // TODO: replace commit with apply after refactoring EIP //FIXME: don't save private keys in shared preferences! use the keystore - public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { - preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). + public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider, boolean apply) { + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean(PROVIDER_CONFIGURED, true). putString(Provider.PROVIDER_IP, provider.getProviderIp()). putString(Provider.GEOIP_URL, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL, provider.getMotdUrl().toString()). putString(Provider.PROVIDER_API_IP, provider.getProviderApiIp()). putString(Provider.MAIN_URL, provider.getMainUrlString()). putString(Provider.KEY, provider.getDefinitionString()). @@ -91,7 +119,15 @@ public class PreferenceHelper { putString(PROVIDER_EIP_DEFINITION, provider.getEipServiceJsonString()). putString(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()). putString(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()). - commit(); + putString(PROVIDER_MOTD, provider.getMotdJsonString()). + putStringSet(PROVIDER_MOTD_HASHES, provider.getMotdLastSeenHashes()). + putLong(PROVIDER_MOTD_LAST_SEEN, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED, provider.getLastMotdUpdate()); + if (apply) { + editor.apply(); + } else { + editor.commit(); + } String providerDomain = provider.getDomain(); preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). @@ -99,9 +135,14 @@ public class PreferenceHelper { putString(Provider.PROVIDER_API_IP + "." + providerDomain, provider.getProviderApiIp()). putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()). putString(Provider.GEOIP_URL + "." + providerDomain, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL + "." + providerDomain, provider.getMotdUrl().toString()). putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()). putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()). putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()). + putString(PROVIDER_MOTD + "." + providerDomain, provider.getMotdJsonString()). + putStringSet(PROVIDER_MOTD_HASHES + "." + providerDomain, provider.getMotdLastSeenHashes()). + putLong(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain, provider.getLastMotdUpdate()). apply(); } @@ -132,9 +173,14 @@ public class PreferenceHelper { remove(Provider.PROVIDER_API_IP + "." + providerDomain). remove(Provider.MAIN_URL + "." + providerDomain). remove(Provider.GEOIP_URL + "." + providerDomain). + remove(Provider.MOTD_URL + "." + providerDomain). remove(PROVIDER_EIP_DEFINITION + "." + providerDomain). remove(PROVIDER_PRIVATE_KEY + "." + providerDomain). remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain). + remove(PROVIDER_MOTD + "." + providerDomain). + remove(PROVIDER_MOTD_HASHES + "." + providerDomain). + remove(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain). + remove(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain). apply(); } @@ -146,9 +192,14 @@ public class PreferenceHelper { remove(Provider.PROVIDER_API_IP). remove(Provider.MAIN_URL). remove(Provider.GEOIP_URL). + remove(Provider.MOTD_URL). remove(PROVIDER_EIP_DEFINITION). remove(PROVIDER_PRIVATE_KEY). remove(PROVIDER_VPN_CERTIFICATE). + remove(PROVIDER_MOTD). + remove(PROVIDER_MOTD_HASHES). + remove(PROVIDER_MOTD_LAST_SEEN). + remove(PROVIDER_MOTD_LAST_UPDATED). apply(); } @@ -360,10 +411,7 @@ public class PreferenceHelper { } public static void setExcludedApps(Context context, Set apps) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - SharedPreferences.Editor prefsedit = prefs.edit(); - prefsedit.putStringSet(EXCLUDED_APPS, apps); - prefsedit.apply(); + putStringSet(context, EXCLUDED_APPS, apps); } public static Set getExcludedApps(Context context) { @@ -415,6 +463,14 @@ public class PreferenceHelper { preferences.edit().putString(key, value).apply(); } + public static void putStringSet(Context context, String key, Set value) { + if (context == null) { + return; + } + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences.edit().putStringSet(key, value).apply(); + } + public static boolean getBoolean(Context context, String key, Boolean defValue) { if (context == null) { return false; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java index e45add50..86ce577b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java @@ -60,6 +60,7 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB SET_UP_PROVIDER = "setUpProvider", UPDATE_PROVIDER_DETAILS = "updateProviderDetails", DOWNLOAD_GEOIP_JSON = "downloadGeoIpJson", + DOWNLOAD_MOTD = "downloadMotd", SIGN_UP = "srpRegister", LOG_IN = "srpAuth", LOG_OUT = "logOut", diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 7b6a3ad6..14308875 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -35,10 +35,15 @@ import static se.leap.bitmaskclient.base.models.Constants.CREDENTIALS_PASSWORD; import static se.leap.bitmaskclient.base.models.Constants.CREDENTIALS_USERNAME; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; +import static se.leap.bitmaskclient.base.models.Provider.MOTD_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; @@ -47,6 +52,8 @@ import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormatted import static se.leap.bitmaskclient.base.utils.ConfigHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider; import static se.leap.bitmaskclient.providersetup.ProviderAPI.BACKEND_ERROR_KEY; import static se.leap.bitmaskclient.providersetup.ProviderAPI.BACKEND_ERROR_MESSAGE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE; @@ -55,6 +62,7 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOAD import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DELAY; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_MOTD; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_SERVICE_JSON; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; @@ -124,6 +132,7 @@ import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.TimeoutException; import javax.net.ssl.SSLHandshakeException; @@ -138,6 +147,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipStatus; +import se.leap.bitmaskclient.motd.MotdClient; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; import se.leap.bitmaskclient.providersetup.models.SrpCredentials; @@ -299,6 +309,17 @@ public abstract class ProviderApiManagerBase { } ProviderObservable.getInstance().setProviderForDns(null); break; + case DOWNLOAD_MOTD: + MotdClient client = new MotdClient(provider); + JSONObject motd = client.fetchJson(); + if (motd != null) { + provider.setMotdJson(motd); + provider.setLastMotdUpdate(System.currentTimeMillis()); + } + PreferenceHelper.storeProviderInPreferences(preferences, provider); + ProviderObservable.getInstance().updateProvider(provider); + break; + case UPDATE_INVALID_VPN_CERTIFICATE: ProviderObservable.getInstance().setProviderForDns(provider); result = updateVpnCertificate(provider); @@ -914,7 +935,11 @@ public abstract class ProviderApiManagerBase { provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain)); provider.setProviderApiIp(getPersistedProviderApiIp(providerDomain)); provider.setProviderIp(getPersistedProviderIp(providerDomain)); - provider.setGeoipUrl(getPersistedGeoIp(providerDomain)); + provider.setGeoipUrl(getPersistedGeoIp(providerDomain)); // TODO: do we really need to persist the Geoip URL?? + provider.setLastMotdSeen(getPersistedMotdLastSeen(providerDomain)); + provider.setMotdLastSeenHashes(getPersistedMotdHashes(providerDomain)); + provider.setLastMotdUpdate(getPersistedMotdLastUpdate(providerDomain)); + provider.setMotdJson(getPersistedMotd(providerDomain)); } } @@ -1045,6 +1070,27 @@ public abstract class ProviderApiManagerBase { return getFromPersistedProvider(GEOIP_URL, providerDomain, preferences); } + protected JSONObject getPersistedMotd(String providerDomain) { + try { + return new JSONObject(getFromPersistedProvider(PROVIDER_MOTD, providerDomain, preferences)); + } catch (JSONException e) { + return new JSONObject(); + } + } + + protected long getPersistedMotdLastSeen(String providerDomain) { + return getLongFromPersistedProvider(PROVIDER_MOTD_LAST_SEEN, providerDomain, preferences); + } + + protected long getPersistedMotdLastUpdate(String providerDomain) { + return getLongFromPersistedProvider(PROVIDER_MOTD_LAST_UPDATED, providerDomain, preferences); + } + + protected Set getPersistedMotdHashes(String providerDomain) { + return getStringSetFromPersistedProvider(PROVIDER_MOTD_HASHES, providerDomain, preferences); + } + + protected boolean hasUpdatedProviderDetails(String domain) { return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(CA_CERT + "." + domain); } -- cgit v1.2.3 From 7d5e33aeab1ba02148be041c29ad6b4220d83b27 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 18:50:23 +0100 Subject: stub implementation to start motd UI on app start if required --- .../se/leap/bitmaskclient/base/StartActivity.java | 74 +++++++++++++++++----- .../leap/bitmaskclient/base/utils/DateHelper.java | 11 ++++ .../leap/bitmaskclient/eip/EipSetupObserver.java | 7 ++ 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 8d11105f..537c6c91 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -16,6 +16,17 @@ */ package se.leap.bitmaskclient.base; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; + import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; @@ -28,27 +39,22 @@ import androidx.annotation.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Set; import de.blinkt.openvpn.core.VpnStatus; +import motd.IMessage; +import motd.IMessages; +import motd.IStringCollection; +import motd.Motd; import se.leap.bitmaskclient.BuildConfig; -import se.leap.bitmaskclient.providersetup.ProviderListActivity; -import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.base.models.FeatureVersionCode; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; +import se.leap.bitmaskclient.base.utils.DateHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; - -import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSION; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; +import se.leap.bitmaskclient.eip.EipCommand; +import se.leap.bitmaskclient.providersetup.ProviderListActivity; +import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; /** * Activity shown at startup. Evaluates if App is started for the first time or has been upgraded @@ -202,12 +208,13 @@ public class StartActivity extends Activity{ EipCommand.startVPN(this, true); finish(); } else if (PreferenceHelper.getRestartOnUpdate(this.getApplicationContext())) { + // This is relevant for web build flavor apks PreferenceHelper.restartOnUpdate(this.getApplicationContext(), false); EipCommand.startVPN(this, false); - showMainActivity(); + showNextActivity(provider); finish(); } else { - showMainActivity(); + showNextActivity(provider); } } else { configureLeapProvider(); @@ -234,13 +241,46 @@ public class StartActivity extends Activity{ storeProviderInPreferences(preferences, provider); ProviderObservable.getInstance().updateProvider(provider); EipCommand.startVPN(this, false); - showMainActivity(); + showNextActivity(provider); } else if (resultCode == RESULT_CANCELED) { finish(); } } } + private void showNextActivity(Provider provider) { + if (provider.shouldShowMotdSeen()) { + try { + IMessages messages = Motd.newMessages(provider.getMotdJsonString()); + + IStringCollection stringCollection = Motd.newStringCollection(); //provider.getMotdLastSeenHashCollection(); + String formattedDate = DateHelper.getFormattedDateWithTimezone(provider.getLastMotdSeen()); + IMessage message = messages.getFirstMessage(formattedDate, stringCollection); + if (message != null) { + IMessage imessage = Motd.newMessage(message.toJson()); + showMotd(provider, imessage); + return; + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "Couldn't show Motd. Invalid timestamp."); + } + } + showMainActivity(); + } + + private void showMotd(Provider p, IMessage message) { + if (message.mType().equals(Motd.MESSAGE_TYPE_ONCE)) { + Set lastSeenHashes = p.getMotdLastSeenHashes(); + String hash = message.hash(); + lastSeenHashes.add(hash); + p.setMotdLastSeenHashes(lastSeenHashes); + PreferenceHelper.persistProvider(this, p); + ProviderObservable.getInstance().updateProvider(p); + } + //TODO: show Motd Activity! + showMainActivity(); + } + private void showMainActivity() { Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/DateHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/DateHelper.java index 0476bf12..2e9c2b24 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/DateHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/DateHelper.java @@ -12,6 +12,7 @@ import java.util.Locale; */ public class DateHelper { private static final String DATE_PATTERN = "dd/MM/yyyy"; + private static final String DATE_PATTERN_RFC822_NUMERIC_ZONE = "dd MMM yy hh:mm Z"; // RFC822 with numeric zone private static final int ONE_DAY = 86400000; //1000*60*60*24 public static long getDateDiffToCurrentDateInDays(String startDate) throws ParseException { @@ -26,4 +27,14 @@ public class DateHelper { Date lastDate = new Date(); return sdf.format(lastDate); } + + /** + * Return date in a specific format bitmaskcore can handle. + * @param milliSeconds Date in milliseconds + * @return String representing date in specified format + */ + public static String getFormattedDateWithTimezone(long milliSeconds) throws IllegalArgumentException { + SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN_RFC822_NUMERIC_ZONE, Locale.US); + return sdf.format(milliSeconds); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java index 05991390..85cdb06c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -40,6 +40,7 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOAD import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DELAY; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_MOTD; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE; @@ -385,6 +386,12 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta parameters.putLong(DELAY, 500); ProviderAPICommand.execute(appContext, QUIETLY_UPDATE_VPN_CERTIFICATE, parameters, provider); } + + if (provider.shouldUpdateMotdJson()) { + Bundle parameters = new Bundle(); + parameters.putLong(DELAY, 500); + ProviderAPICommand.execute(appContext, DOWNLOAD_MOTD, parameters, provider); + } finishGatewaySetup(false); } else if ("TCP_CONNECT".equals(state)) { changingGateway.set(false); -- cgit v1.2.3 From cac2c849e8d7d35bd9c72fc8c9bb8bc322eb24a0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 12 Nov 2022 22:21:31 +0100 Subject: create UI for message of the day --- .../se/leap/bitmaskclient/base/MainActivity.java | 84 ++++++++++----- .../se/leap/bitmaskclient/base/StartActivity.java | 18 +++- .../bitmaskclient/base/fragments/MotdFragment.java | 103 ++++++++++++++++++ .../leap/bitmaskclient/base/models/Constants.java | 1 + app/src/main/res/drawable-hdpi/ic_arrow_right.png | Bin 0 -> 562 bytes app/src/main/res/drawable-ldpi/ic_arrow_right.png | Bin 0 -> 458 bytes app/src/main/res/drawable-mdpi/ic_arrow_right.png | Bin 0 -> 551 bytes app/src/main/res/drawable-xhdpi/ic_arrow_right.png | Bin 0 -> 753 bytes .../main/res/drawable-xxhdpi/ic_arrow_right.png | Bin 0 -> 784 bytes .../main/res/drawable-xxxhdpi/ic_arrow_right.png | Bin 0 -> 1168 bytes app/src/main/res/layout/f_motd.xml | 116 +++++++++++++++++++++ 11 files changed, 290 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/fragments/MotdFragment.java create mode 100644 app/src/main/res/drawable-hdpi/ic_arrow_right.png create mode 100644 app/src/main/res/drawable-ldpi/ic_arrow_right.png create mode 100644 app/src/main/res/drawable-mdpi/ic_arrow_right.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_arrow_right.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_arrow_right.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_arrow_right.png create mode 100644 app/src/main/res/layout/f_motd.xml diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index 8cb12652..e2fa0783 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -17,6 +17,34 @@ package se.leap.bitmaskclient.base; +import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; +import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; +import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; +import static se.leap.bitmaskclient.base.models.Constants.EIP_REQUEST; +import static se.leap.bitmaskclient.base.models.Constants.EXTRA_MOTD_MSG; +import static se.leap.bitmaskclient.base.models.Constants.LOCATION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_EXCEPTION; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_TIMEOUT; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; + import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -40,6 +68,7 @@ import se.leap.bitmaskclient.base.fragments.EipFragment; import se.leap.bitmaskclient.base.fragments.ExcludeAppsFragment; import se.leap.bitmaskclient.base.fragments.LogFragment; import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; +import se.leap.bitmaskclient.base.fragments.MotdFragment; import se.leap.bitmaskclient.base.fragments.NavigationDrawerFragment; import se.leap.bitmaskclient.base.fragments.SettingsFragment; import se.leap.bitmaskclient.base.models.Provider; @@ -49,38 +78,10 @@ import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipSetupListener; import se.leap.bitmaskclient.eip.EipSetupObserver; -import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.providersetup.ProviderAPI; import se.leap.bitmaskclient.providersetup.activities.LoginActivity; import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; -import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; -import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; -import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; -import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; -import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; -import static se.leap.bitmaskclient.base.models.Constants.EIP_REQUEST; -import static se.leap.bitmaskclient.base.models.Constants.LOCATION; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; -import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; -import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_EXCEPTION; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_TIMEOUT; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; - public class MainActivity extends AppCompatActivity implements EipSetupListener, Observer { @@ -93,6 +94,7 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, public final static String ACTION_SHOW_VPN_FRAGMENT = "action_show_vpn_fragment"; public final static String ACTION_SHOW_LOG_FRAGMENT = "action_show_log_fragment"; public final static String ACTION_SHOW_DIALOG_FRAGMENT = "action_show_dialog_fragment"; + public final static String ACTION_SHOW_MOTD_FRAGMENT = "action_show_motd_fragment"; /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. @@ -161,10 +163,22 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, bundle.putParcelable(PROVIDER_KEY, provider); fragment.setArguments(bundle); hideActionBarSubTitle(); + showActionBar(); + break; + case ACTION_SHOW_MOTD_FRAGMENT: + fragment = new MotdFragment(); + Bundle motdBundle = new Bundle(); + if (intent.hasExtra(EXTRA_MOTD_MSG)) { + motdBundle.putString(EXTRA_MOTD_MSG, intent.getStringExtra(EXTRA_MOTD_MSG)); + } + fragment.setArguments(motdBundle); + hideActionBarSubTitle(); + hideActionBar(); break; case ACTION_SHOW_LOG_FRAGMENT: fragment = new LogFragment(); setActionBarTitle(R.string.log_fragment_title); + showActionBar(); break; case ACTION_SHOW_DIALOG_FRAGMENT: if (intent.hasExtra(EIP.ERRORID)) { @@ -186,6 +200,20 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } } + private void hideActionBar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.hide(); + } + } + + private void showActionBar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.show(); + } + } + private void hideActionBarSubTitle() { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 537c6c91..6e557236 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -16,9 +16,11 @@ */ package se.leap.bitmaskclient.base; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_MOTD_FRAGMENT; import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.EXTRA_MOTD_MSG; import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; @@ -265,7 +267,7 @@ public class StartActivity extends Activity{ Log.e(TAG, "Couldn't show Motd. Invalid timestamp."); } } - showMainActivity(); + showVPNFragment(); } private void showMotd(Provider p, IMessage message) { @@ -277,15 +279,23 @@ public class StartActivity extends Activity{ PreferenceHelper.persistProvider(this, p); ProviderObservable.getInstance().updateProvider(p); } - //TODO: show Motd Activity! - showMainActivity(); + showMotdFragment(message); } - private void showMainActivity() { + private void showVPNFragment() { Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setAction(ACTION_SHOW_VPN_FRAGMENT); startActivity(intent); finish(); } + + private void showMotdFragment(IMessage message) { + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setAction(ACTION_SHOW_MOTD_FRAGMENT); + intent.putExtra(EXTRA_MOTD_MSG, message.toJson()); + startActivity(intent); + finish(); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/MotdFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/MotdFragment.java new file mode 100644 index 00000000..16834ab5 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/MotdFragment.java @@ -0,0 +1,103 @@ +package se.leap.bitmaskclient.base.fragments; + +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static se.leap.bitmaskclient.base.models.Constants.EXTRA_MOTD_MSG; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.Html; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageButton; +import androidx.appcompat.widget.AppCompatTextView; +import androidx.fragment.app.Fragment; + +import java.util.Locale; + +import de.blinkt.openvpn.core.VpnStatus; +import motd.IMessage; +import motd.Motd; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.databinding.FMotdBinding; + + +public class MotdFragment extends Fragment { + + private static final String TAG = MotdFragment.class.getSimpleName(); + private IMessage message; + FMotdBinding binding; + AppCompatTextView messageView; + AppCompatImageButton nextButton; + + public MotdFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + String messageString = getArguments().getString(EXTRA_MOTD_MSG); + if (messageString != null) { + Log.d(TAG, "MotdFragment received: " + messageString); + message = Motd.newMessage(messageString); + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + binding = FMotdBinding.inflate(getLayoutInflater()); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + messageView = binding.motdContent; + nextButton = binding.nextBtn; + String currentLang = Locale.getDefault().getLanguage(); + String text = message.getLocalizedText(currentLang); + if (TextUtils.isEmpty(text)) { + text = message.getLocalizedText("en"); + } + + if (TextUtils.isEmpty(text)) { + String error = "Message of the day cannot be shown. Unsupported app language and unknown default langauge."; + Log.e(TAG, error); + VpnStatus.logError(error); + showVpnFragment(view.getContext()); + return; + } + + Log.d(TAG, "set motd text: " + text); + messageView.setText(Html.fromHtml(text)); + messageView.setMovementMethod(LinkMovementMethod.getInstance()); + nextButton.setOnClickListener(v -> { + showVpnFragment(v.getContext()); + }); + + } + + private void showVpnFragment(Context context) { + try { + Intent intent = new Intent(context, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setAction(ACTION_SHOW_VPN_FRAGMENT); + context.startActivity(intent); + } catch (NullPointerException npe) { + npe.printStackTrace(); + } + + } +} \ No newline at end of file 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 index d0af8112..ee5bd2a7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -77,6 +77,7 @@ public interface Constants { String ASK_TO_CANCEL_VPN = "ask_to_cancel_vpn"; + String EXTRA_MOTD_MSG = "extra_motd_message"; ////////////////////////////////////////////// diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_right.png b/app/src/main/res/drawable-hdpi/ic_arrow_right.png new file mode 100644 index 00000000..2d081384 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-ldpi/ic_arrow_right.png b/app/src/main/res/drawable-ldpi/ic_arrow_right.png new file mode 100644 index 00000000..7fc572af Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_right.png b/app/src/main/res/drawable-mdpi/ic_arrow_right.png new file mode 100644 index 00000000..60702e35 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_right.png b/app/src/main/res/drawable-xhdpi/ic_arrow_right.png new file mode 100644 index 00000000..f1f4f691 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png new file mode 100644 index 00000000..e0031ca8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right.png new file mode 100644 index 00000000..1b4f4239 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/layout/f_motd.xml b/app/src/main/res/layout/f_motd.xml new file mode 100644 index 00000000..3cfe7dfe --- /dev/null +++ b/app/src/main/res/layout/f_motd.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 1a9004432b1733ae30f9cc8ebb85a70af8d93d34 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 12 Nov 2022 23:18:12 +0100 Subject: use gradient for motd background, simple button style --- app/src/main/res/drawable/background_motd.xml | 9 ++++++ app/src/main/res/layout/f_motd.xml | 42 +++++++++++++++------------ app/src/main/res/values/colors.xml | 1 + 3 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 app/src/main/res/drawable/background_motd.xml diff --git a/app/src/main/res/drawable/background_motd.xml b/app/src/main/res/drawable/background_motd.xml new file mode 100644 index 00000000..519e0233 --- /dev/null +++ b/app/src/main/res/drawable/background_motd.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/f_motd.xml b/app/src/main/res/layout/f_motd.xml index 3cfe7dfe..3202e95b 100644 --- a/app/src/main/res/layout/f_motd.xml +++ b/app/src/main/res/layout/f_motd.xml @@ -8,26 +8,13 @@ tools:context=".base.fragments.MotdFragment" android:fitsSystemWindows="true"> - - - - + app:layout_constraintBottom_toTopOf="@+id/next_btn" + /> + + + + diff --git a/app/src/main/res/drawable/motd_img.xml b/app/src/main/res/drawable/motd_img.xml new file mode 100644 index 00000000..4a330b8f --- /dev/null +++ b/app/src/main/res/drawable/motd_img.xml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/f_motd.xml b/app/src/main/res/layout/f_motd.xml index 3202e95b..6e763c75 100644 --- a/app/src/main/res/layout/f_motd.xml +++ b/app/src/main/res/layout/f_motd.xml @@ -66,18 +66,6 @@ android:orientation="horizontal" app:layout_constraintGuide_percent="0.4" /> - - Date: Sun, 13 Nov 2022 00:20:55 +0100 Subject: add unit test to verify the required date formatting is correct --- .../leap/bitmaskclient/base/utils/DateHelperTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java diff --git a/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java new file mode 100644 index 00000000..c857c103 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java @@ -0,0 +1,19 @@ +package se.leap.bitmaskclient.base.utils; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DateHelperTest { + + @Test + public void getFormattedDateWithTimezone() { + Pattern datePattern = Pattern.compile("^10 Nov 22 11:26 [+-][0-9]{4}$"); + String formattedDate = DateHelper.getFormattedDateWithTimezone(1668075969744L); + Matcher matcher = datePattern.matcher(formattedDate); + assertTrue(matcher.find()); + } +} \ No newline at end of file -- cgit v1.2.3 From 37468f03b05301d1afb07799b08c5937a612900f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 13 Nov 2022 00:22:10 +0100 Subject: remove unused imports --- .../se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java | 4 ---- .../main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java | 1 - 2 files changed, 5 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java index 6829d9f1..2c0fdd69 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java @@ -7,7 +7,6 @@ import android.app.Dialog; import android.os.Bundle; import android.text.TextUtils; import android.view.View; -import android.widget.ArrayAdapter; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -15,9 +14,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDialogFragment; import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatEditText; -import androidx.appcompat.widget.AppCompatSpinner; - -import java.util.ArrayList; import se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java index 59c1290a..5f7fa74a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java @@ -19,7 +19,6 @@ import android.content.Context; import android.os.FileObserver; import android.util.Log; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.torproject.jni.ClientTransportPluginInterface; -- cgit v1.2.3 From 9263739bb87cf6353fd5ba994c387e1ab4d28b46 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 13 Nov 2022 00:22:57 +0100 Subject: add missing call to super in ProviderListBaseActivity --- .../bitmaskclient/providersetup/activities/ProviderListBaseActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java index 002335db..90ebfb4d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java @@ -95,6 +95,7 @@ public abstract class ProviderListBaseActivity extends ProviderSetupBaseActivity @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) { if (resultCode == RESULT_OK) { setResult(resultCode, data); -- cgit v1.2.3 From 9bb7ba825f6fbe68da66f702497e914f318011a2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 13 Nov 2022 20:50:56 +0100 Subject: improve motd icon for riseup --- app/src/custom/res/drawable/ic_motd.png | Bin 44157 -> 34639 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/custom/res/drawable/ic_motd.png b/app/src/custom/res/drawable/ic_motd.png index 27f9a7f0..5d2efea4 100644 Binary files a/app/src/custom/res/drawable/ic_motd.png and b/app/src/custom/res/drawable/ic_motd.png differ -- cgit v1.2.3 From dbb32301d2cbd489c326b22cb0c43b885f9618a2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 14 Nov 2022 21:38:32 +0100 Subject: update test vpn cert and key - we should find a better way to mock both instead of relying on real keys and certs --- app/src/test/resources/v4/riseup.net.cert | 96 +++++++++++++++---------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/app/src/test/resources/v4/riseup.net.cert b/app/src/test/resources/v4/riseup.net.cert index 86bc0b55..1beff4bd 100644 --- a/app/src/test/resources/v4/riseup.net.cert +++ b/app/src/test/resources/v4/riseup.net.cert @@ -1,54 +1,54 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAwtqqSbTsB/JchPr41KdSyTWfG+qBxRfbqYw5hx8VxzuVNPn4 -nEmKm4KbtEhZLT3Kk0yJa+9X3UBVkeTrI6IZQmsK1s1lq9YTcwjsryza//xtw6gM -7Wd8X8FaMnaYPBBRpaWWi//RsrLmztm0kSU1pJbgSL1VJsngGImWPcnAPvhPS4IG -6XD/4DLyog7Hyg0yuZyBf6DzvQUMFh/B9Sm+ogY8nG+vEaoN/RaKn25M+uC6NC2v -X+9wcqLyQeh0JsIA23foyyWlA2sW2+ad4VWfI3DpXwYCnCuJZlD3JZoLP8OoQacl -PsBIll+n6KeVcE7H7af2CkNinFa+0CgMYtvpgQIDAQABAoIBAQC5ufkkRinQLUfY -jOuOrmovVUfyMOU+es4qXnka/RsiCv3eQAGi3koajjRhc7BkeghTvFkkIz9pqX+m -jz89eK2A7Eypj5/AWU2ykSgglK2t3+qz2sNvqfsXvlF91iKm5ZsdO6cyjEVRgkqT -kVkWHBR0bEcdrjGyxisu2D33aQ0wNo1ENoJYJEe+F+fcm3IhVsSCMWEoYeX+RXXq -scwGgwNSn3V4fEqQA7Hs77ri+gjbuIf6KZ3DPcQTpJ4ST6UcJkyXowLLYFmPgVJt -XOqJ5sjDUNLgX2F6LJj8r0C2V0UmRoed/ZONmB2AVr/e/BmGB4zLVOFv4NLK52CP -m3B4SrPNAoGBAPEJcfFPAOAHIW51xz2l61W4d4rqvu54IuHYMGWRJjtNx/zqIxwE -I4hTHz9jz++JZaJH9anOliosIqzmieds57JX0MBEOIVG8wb0BgxziIO8E5hdfptr -DWtfmnFnCiz2qEb38UU8GiifiwCrU6NkEniAaoCVkMMx+B0cycLfeeUHAoGBAM7z -SOUbZooN7ZAz/KFe05wHOwngb7ikEuENXFLziyaOa+0zXyv0PitWese0GdGbU1nH -Alkw/qA8kozGobmfSWrLxBCjJDtz4wuDilwI4OT0hO6+VZlF89C84BjAVA/RXjzo -CcIUrIvZv8OaopESicuC67KB1ujB4p+XFTEmlmM3AoGABSNTZ3ZsqVndj5I5JgpE -YvZkrfRlD4ZGEBRgq7mVXAxDaBPBndZEv6It91b0VsHSBcyM4wrBTrLUJmVfqSw8 -ICQZEhAiOE0T3yESg+9uiIhYzpWnnj6A8bn++83bfKvhWGnunbAzSoxkFSaRyNjY -P/NU0dreVBrblBtJ/bpvyb8CgYBOX13kvdq4P4wPB1EN/65dsXNPSzqkDybDKd8j -3u18nYUL4F+Tcry0htyakn8QnSUUo8Qk6OQU5LuPKo4GkOcp1Z8budy30yxRqPAV -6Jrauis5isU59X7fNxga54MuNljc8fb4FAJAOCdiOUaFcCLU+nCuOnOb1Akx7PJu -mbFsQwKBgQCfOLsXqDHMRTnyRCwGOx9aIbYt0qW5ZE08f8vbqKMz2KeX9uN7G/7s -NO36Zakppn9IS9nQVPmBDQhQ+8VQYqX7VaB1ug7d1OhuP+dbvXGBq4nN9f2iqy6Z -G5PyYZpI8Qo+Cr04TkXacz9Lc4NFOxyqw/Ln1tuOLYAZY8dSaTHOsg== +MIIEowIBAAKCAQEAqSkd5UbKh+HbWSH603MJNgSkomeBnPooE0dlxYXIOQa/HnTl +5+7CV47JDWjFWSj1h+zeAmXcgkQxDRF1rbZ+oov26SYyGingBQgn9qvoCZwIdesE +N5Xhdvt23FK8edanCMN/tn1CnyaO5xvHdWRvhpmEf9zAsVwo9qfx1vmRsJfzvcnH +rHoCgH3nxzK1VZm5xNGRdAm9jA2odYYIuSKN1hSYgjcnXVvNHm3bWs+B4RzgtrZG +vy+vsSSd6AaYGQ4sCj3DOuKNOWqXZ8yFpfjbi0rYsOmzxEFiZiequxhrafSM+2uy +NbdPsPXKd0veZh1ApDEHW/6I+qP0bnHE6Dtr+wIDAQABAoIBABnwxjbcrj48Mmju +vwoh/+2atKx69vNdoTujnUW3CEdGc5R2FLOGd6L5sHcv8+OCVnSrrDft6uzHDEaW +wNcMv0qp8Ak85D4C4emjoI1BO2oN1XZPvevQPi0Czu1meqSseBzt7e3MM6U4Qn3K +UsH7zuZzMFBzR9Fq8pUwl/OBfgf4ZWF0IeHFx1/T+3A/lCTdki2wZ8M7pN7djED1 +fqmbwXt3KSnhhOAjZm17qhVM6K+kA3EInsijShbeUTtQMyZCifIrtj5EHYf/sr3f +mlXdspIaR5Wh5tKQo9TRrBNgmMxg+GhBz7fwaM2P1uZXVWTAK4L35vz17o0AQR0P +aItWxyECgYEA3fEGWgH53tATZklxiXaEInCve+XNpE2m80g1hNkIS36D676e0Mxm +L1PlgO+YDRgLBAQVbSdUbfQrcc8Zlcn7R2a0X1a12OH/4pKFXNM4doS/3k5wN1TI +Zr7+AqP4vaLVNt8fjYBhRYpOdwpr5PTjJCpP9dh3ItuIOyH/w+2k4iMCgYEAwx6Y +Cjkn7IaBJOr0kK5JORlGx10jfUmMLMiaJATs49vAcgxt7rKTiEUNvS1YArR4Vh/n +hAYmsC76folGTeZjotmzQbUkm/yZ3OMTSrcja85uM7NJbt9CnUPiDkKDEY4Exhuh +K/Ls+Lp6/eIyJ+b4/xpFEzlUQyY4WiZ6UWcEUEkCgYEAxsqVYtd0RQPg7HSKMpMq +RWLje7lZWXqIOE6MSWLQUDaQ2P6TZ/g86tVdswBoFApeC4nQ20UoFZhntXfHtegF +n225z89t8EZ1mS6eL4etglLjPK7LSnQxT/5wrFLMgKcyDQULUQYVmmEIaQ23mItU +TFdt6YmrJFi4jCam3YqlbjsCgYACzTSnqOxu0/uUuR7r2OTKQhenEypIST8PAY5d +CAkSuHwJ5y3I6J1/rmYlGjqSR18W9XxQg/oYO4RzPqtYwP8bPn75aY1uA/F9n3EO +eJS0npEsgt2CDwiY03mydLgHD3/4DDuDMwi+BYdwj8filMlseEcXoJIaKLlUagsF +kjIYqQKBgEDDiM51YU2V1k4rzdzICdfo5mqa7FiQ2JiRs3yG20gNg3nDReQZk0Q4 +poJkZksuojQabDOnHzWc2jfUehll6gC1ijtRzaoSeRH2m8X5JXb3vfAe5/TFZHBg +bErDqPo+En9Y72LIcGG5vlzQHfE0l24C0oQ64cssLHA9+VnYmwhw -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIEmzCCAoOgAwIBAgIQdYL065go8MY1TA6uhbuzrzANBgkqhkiG9w0BAQsFADB1 +MIIEmzCCAoOgAwIBAgIQejc1yqfKGehUKDMdybDH+DANBgkqhkiG9w0BAQsFADB1 MRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlz ZXVwLm5ldDE8MDoGA1UEAwwzUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EgKGNsaWVu -dCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTIyMDYxODAwMDAwMFoXDTIyMDkxODAw -MDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVENnZteWZ1MHpsdmlucmprdTN3Y2hp -OTZsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMLaqkm07AfyXIT6 -+NSnUsk1nxvqgcUX26mMOYcfFcc7lTT5+JxJipuCm7RIWS09ypNMiWvvV91AVZHk -6yOiGUJrCtbNZavWE3MI7K8s2v/8bcOoDO1nfF/BWjJ2mDwQUaWllov/0bKy5s7Z -tJElNaSW4Ei9VSbJ4BiJlj3JwD74T0uCBulw/+Ay8qIOx8oNMrmcgX+g870FDBYf -wfUpvqIGPJxvrxGqDf0Wip9uTPrgujQtr1/vcHKi8kHodCbCANt36MslpQNrFtvm -neFVnyNw6V8GApwriWZQ9yWaCz/DqEGnJT7ASJZfp+inlXBOx+2n9gpDYpxWvtAo -DGLb6YECAwEAAaNvMG0wHQYDVR0OBBYEFGy9LFCeTCtyoVbQYY18zgpX0N98MAsG +dCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTIyMTAxNDAwMDAwMFoXDTIzMDExNDAw +MDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEMTMxaXF4cHB0cHljYnN3eGRueXRu +aHhiMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkpHeVGyofh21kh ++tNzCTYEpKJngZz6KBNHZcWFyDkGvx505efuwleOyQ1oxVko9Yfs3gJl3IJEMQ0R +da22fqKL9ukmMhop4AUIJ/ar6AmcCHXrBDeV4Xb7dtxSvHnWpwjDf7Z9Qp8mjucb +x3Vkb4aZhH/cwLFcKPan8db5kbCX873Jx6x6AoB958cytVWZucTRkXQJvYwNqHWG +CLkijdYUmII3J11bzR5t21rPgeEc4La2Rr8vr7EknegGmBkOLAo9wzrijTlql2fM +haX424tK2LDps8RBYmYnqrsYa2n0jPtrsjW3T7D1yndL3mYdQKQxB1v+iPqj9G5x +xOg7a/sCAwEAAaNvMG0wHQYDVR0OBBYEFEFB2IaA9Z5TOAPtMw3vgKvRR+tpMAsG A1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1Ud -IwQYMBaAFBf0G9XlKgEBTWuiXTYKKQmWZYBGMA0GCSqGSIb3DQEBCwUAA4ICAQBy -MezxBB08bn5L5ye3pTOvENyM0DLGdoy1N+oEHhjMW/QmxPuXzKviyxNEtFCbyZeT -n+uQPY3zwhj4vF5PZoUXI22USISMo+bPHHo4dTfXfzln7CuPuXnUR1bFKSFGU7+B -6TZb5qmFkWfCiZ8KE1ogKXLX2mwmnIKVpPiu07pp6msR+pxfQHBBbrzafLs5PSa8 -kTxW900eozF4KJYwcryu6A/tdkTrQqsji/NrwqJRnFqzzDV0x7iFpnp0J9xRi1oa -nkETZXMSHkDkqL3RdTwg11RX+bnYS/GK+//z3G17iwB/rGIi9O2qN6uMhX/ZFwom -AAqbSAzOnSU2ERaSuc7a0t9c9cNnusbYiDaNISAi7bOGs5tCbLRBwSznvIo9Dfx8 -aRnDucYp+I6Vl7xW2mM155/44laemiWn4SPRbvBgZgBWObptnuIqu9Nipwp69z/Q -x/BBcnNu+PbdkuC9zO+OtwosK3WVkL+QiKWbT4fxXNqJV90NM1R+CteDWvixs+Bn -xVGCH4c6+svnBmyRhDYID7ZmoeE/gnPkceh63igZ6V+w0UAnGtT9cfLK9cLawfZO -GnO7P8YTawjRoVz9FmhUnirghq8xk0MCdGHWzT+FqGS+l270F+bbD4eUD2nQhV4J -QJ0J3BGyzELKzFtIBIpnzPVDJDSIQkPTT/yP7gAEPg== ------END CERTIFICATE----- \ No newline at end of file +IwQYMBaAFBf0G9XlKgEBTWuiXTYKKQmWZYBGMA0GCSqGSIb3DQEBCwUAA4ICAQB0 +x+RhbfmWuKQ7clT2oBhLOep1USJ9y98BLMsEmqZ84q0CnG+tI2QLhZvaMiGiMplI +saHhK1lIHbO/UATHOhE+ZbY9vAaGK1JaBdlOTshjo+cijZ2nWwfwa9Qj/Cx64sSO +cee3Lbg5IcsFc/0KGCTw0k9PheD/CudRSnLCxImA8DmJO+1w1NUoBBm48tdD6usD +fLU35FvChvNwW/7GO/q3TGXF/jrreBnrJZMjsffwFOJC8SWZIAScmF/OrqWyruYb +ZS9/0ZXR21TT1mvUFjIs+0uY2crfli/f91ZbB9eRoiyHkck8RtotiH9PrmYt7j02 +5cwos2BqRs+kZ7AgYvZjWErwIyCsXSzrk0WztLa2vslqZSZSt12VlW5iIyKTyx8T +snQLEdHwzRT5C+9daq3PneOvD5KhgyySlwWSoMuJdg2n3cTs/0uMDQE7FIim11XM +Fz8liZf4PcWv8YLFUBHQ367SvbAiyZLzpXZETQyDaYNYGTwYBCGs9Yhq3KM85Kmz +f0rgrBpm61ujLQ/OBSCq6/RA9BN8UYdO+YS0vengYtIdc+aw1PzLhcC9dLLXC4ef +zH25zfe7vkt58UcuG+YCsaIR8Hy3I/yDQWVkbNawEYUboEHHRd8pQmUIkHLaYibt +eq1SXtuulUUDIkyfRATiA/GkPVPPnJImL8XK12WFPQ== +-----END CERTIFICATE----- -- cgit v1.2.3 From 24363464d6336ea3ac61bf4fe59b2e253676eaf2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 14 Nov 2022 21:40:09 +0100 Subject: fix tests --- .../leap/bitmaskclient/base/models/Provider.java | 4 --- .../leap/bitmaskclient/testutils/MockHelper.java | 34 ++++++++++++++++++++++ .../testutils/MockSharedPreferences.java | 3 +- 3 files changed, 36 insertions(+), 5 deletions(-) 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 index b0f3d09f..53f864cf 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -30,7 +30,6 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; import androidx.annotation.NonNull; @@ -302,10 +301,7 @@ public final class Provider implements Parcelable { public void setMotdUrl(String url) { try { this.motdUrl.setUrl(new URL(url)); - Log.d("PROVIDER", "setMotdUrl provider: " + this.domain + " - motd url: " + motdUrl.toString()); } catch (MalformedURLException e) { - e.printStackTrace(); - Log.d("PROVIDER", "setMotdUrl exception!!! provider: " + this.domain + " - motd url: " + motdUrl.toString() + " obj:" + this.toString()); this.motdUrl = new DefaultedURL(); } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index c6ba1e6f..e14fa4c3 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -12,11 +12,17 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.utils.FileHelper.createFile; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getEipDefinitionFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider; import android.content.Context; import android.content.Intent; @@ -474,11 +480,39 @@ public class MockHelper { return providerFromPrefs.getCaCert(); case Provider.GEOIP_URL: return providerFromPrefs.getGeoipUrl().toString(); + case Provider.MOTD_URL: + return providerFromPrefs.getMotdUrl().toString(); + case PROVIDER_MOTD: + return providerFromPrefs.getMotdJsonString(); } return null; } }); + when(getLongFromPersistedProvider(anyString(), anyString(), any(SharedPreferences.class))).thenAnswer(new Answer() { + @Override + public Long answer(InvocationOnMock invocation) throws Throwable { + String key = (String) invocation.getArguments()[0]; + switch (key) { + case PROVIDER_MOTD_LAST_SEEN: + return providerFromPrefs.getLastMotdSeen(); + case PROVIDER_MOTD_LAST_UPDATED: + return providerFromPrefs.getLastMotdUpdate(); + } + return 0L; + } + }); + when(getStringSetFromPersistedProvider(anyString(), anyString(), any(SharedPreferences.class))).thenAnswer(new Answer>() { + @Override + public Set answer(InvocationOnMock invocation) throws Throwable { + String key = (String) invocation.getArguments()[0]; + switch (key) { + case PROVIDER_MOTD_HASHES: + return providerFromPrefs.getMotdLastSeenHashes(); + } + return null; + } + }); } public static void mockPreferenceHelper(MockSharedPreferences preferences) { diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java index be0cf41f..4fabc2c0 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java @@ -21,6 +21,7 @@ import android.content.SharedPreferences; import androidx.annotation.Nullable; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -48,7 +49,7 @@ public class MockSharedPreferences implements SharedPreferences { @Nullable @Override public Set getStringSet(String key, @Nullable Set defValues) { - return null; + return new HashSet<>(); } @Override -- cgit v1.2.3 From 7fb33a023010f5fd4430486a421306caf3142d42 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 22 Nov 2022 14:16:15 +0100 Subject: debug failing test in CI - print out formatted date --- app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java index c857c103..3d38cb8a 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java @@ -14,6 +14,7 @@ public class DateHelperTest { Pattern datePattern = Pattern.compile("^10 Nov 22 11:26 [+-][0-9]{4}$"); String formattedDate = DateHelper.getFormattedDateWithTimezone(1668075969744L); Matcher matcher = datePattern.matcher(formattedDate); - assertTrue(matcher.find()); + System.out.println(formattedDate); + assertTrue("date should be formatted similar to 10 Nov 22 11:26 +0100", matcher.find()); } } \ No newline at end of file -- cgit v1.2.3 From 2d20c8e269a502945e981662abe1f7818090a618 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 22 Nov 2022 16:37:59 +0100 Subject: improve pattern matching for getFormattedDateWithTimezone() test --- app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java index 3d38cb8a..2651a64d 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/utils/DateHelperTest.java @@ -11,7 +11,7 @@ public class DateHelperTest { @Test public void getFormattedDateWithTimezone() { - Pattern datePattern = Pattern.compile("^10 Nov 22 11:26 [+-][0-9]{4}$"); + Pattern datePattern = Pattern.compile("^10 Nov 22 [1]?[0-9]:26 [+-][0-9]{4}$"); String formattedDate = DateHelper.getFormattedDateWithTimezone(1668075969744L); Matcher matcher = datePattern.matcher(formattedDate); System.out.println(formattedDate); -- cgit v1.2.3