summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2024-02-26 21:33:52 +0100
committercyBerta <cyberta@riseup.net>2024-02-26 21:33:52 +0100
commit5b07bb3df03cc95d6b50a8eec2bd30563a6d5b43 (patch)
tree3737978877d4779221680e4591d792fc795796a3 /app/src/main
parent2522e75f41b2bc2f3d21baee09338527f271ba7c (diff)
save manually added providers in encrypted shared preferences instead of external files dir
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java45
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java113
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModel.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModelFactory.java8
9 files changed, 82 insertions, 127 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
index 18590f0b..754491f8 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,6 +53,7 @@ public interface Constants {
String OBFUSCATION_PINNING_KCP = "obfuscation_pinning_udp";
String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location";
String USE_SYSTEM_PROXY = "usesystemproxy";
+ String CUSTOM_PROVIDER_DOMAINS = "custom_provider_domains";
//////////////////////////////////////////////
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
index 6dfe0861..34082bcb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
@@ -15,30 +15,6 @@ import de.blinkt.openvpn.core.NativeUtils;
*/
public class InputStreamHelper {
- public interface InputStreamHelperInterface {
- InputStream getInputStreamFrom(String filePath) throws FileNotFoundException;
-
- }
-
- private static InputStreamHelperInterface instance = new DefaultInputStreamHelper();
-
- private static class DefaultInputStreamHelper implements InputStreamHelperInterface {
- @Override
- public InputStream getInputStreamFrom(String filePath) throws FileNotFoundException {
- return new FileInputStream(filePath);
- }
- }
-
- public InputStreamHelper(InputStreamHelperInterface helperInterface) {
- if (!NativeUtils.isUnitTest()) {
- throw new IllegalStateException("InputStreamHelper injected with InputStreamHelperInterface outside of an unit test");
- }
- instance = helperInterface;
- }
- //allows us to mock FileInputStream
- public static InputStream getInputStreamFrom(String filePath) throws FileNotFoundException {
- return instance.getInputStreamFrom(filePath);
- }
public static String loadInputStreamAsString(InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
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 2420a797..eee3bfb2 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
@@ -7,6 +7,7 @@ import static se.leap.bitmaskclient.base.models.Constants.ALLOW_TETHERING_USB;
import static se.leap.bitmaskclient.base.models.Constants.ALLOW_TETHERING_WIFI;
import static se.leap.bitmaskclient.base.models.Constants.ALWAYS_ON_SHOW_DIALOG;
import static se.leap.bitmaskclient.base.models.Constants.CLEARLOG;
+import static se.leap.bitmaskclient.base.models.Constants.CUSTOM_PROVIDER_DOMAINS;
import static se.leap.bitmaskclient.base.models.Constants.DEFAULT_SHARED_PREFS_BATTERY_SAVER;
import static se.leap.bitmaskclient.base.models.Constants.EIP_IS_ALWAYS_ON;
import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT;
@@ -59,6 +60,7 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -185,8 +187,49 @@ public class PreferenceHelper {
}
}
+ /**
+ *
+ * @return HashMap with main URL string as key and Provider as value
+ */
+ public static HashMap<String, Provider> getCustomProviders() {
+ Set<String> providerDomains = getCustomProviderDomains();
+ HashMap<String, Provider> customProviders = new HashMap<>();
+ for (String domain : providerDomains) {
+ String mainURL = preferences.getString(Provider.MAIN_URL + "." + domain, null);
+ if (mainURL != null) {
+ customProviders.put(mainURL, Provider.createCustomProvider(mainURL, domain));
+ }
+ }
+ return customProviders;
+ }
+
+ public static void setCustomProviders(Set<Provider> providers) {
+ Set<String> newProviderDomains = new HashSet<>();
+
+ // add
+ SharedPreferences.Editor editor = preferences.edit();
+ for (Provider provider : providers) {
+ String providerDomain = provider.getDomain();
+ editor.putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString());
+ newProviderDomains.add(providerDomain);
+ }
+
+ // remove
+ Set<String> removedProviderDomains = getCustomProviderDomains();
+ removedProviderDomains.removeAll(newProviderDomains);
+ for (String providerDomain : removedProviderDomains) {
+ editor.remove(Provider.MAIN_URL + "." + providerDomain);
+ }
+
+ editor.putStringSet(CUSTOM_PROVIDER_DOMAINS, newProviderDomains);
+ editor.apply();
+ }
+
+ static Set<String> getCustomProviderDomains() {
+ return preferences.getStringSet(CUSTOM_PROVIDER_DOMAINS, new HashSet<>());
+ }
+
// TODO: replace commit with apply after refactoring EIP
- //FIXME: don't save private keys in shared preferences! use the keystore
public static void storeProviderInPreferences(Provider provider, boolean async) {
synchronized (LOCK) {
SharedPreferences.Editor editor = preferences.edit();
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 bb6f5e01..68699da2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java
@@ -31,7 +31,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.concurrent.TimeoutException;
import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
import se.leap.bitmaskclient.tor.TorServiceCommand;
@@ -180,9 +179,9 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB
@Override
public void saveProvider(Provider p) {
- ProviderManager pm = ProviderManager.getInstance(this.getAssets(), this.getExternalFilesDir(null));
+ ProviderManager pm = ProviderManager.getInstance(this.getAssets());
pm.add(p);
- pm.saveCustomProvidersToFile();
+ pm.saveCustomProviders();
}
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 39f117ea..9eacae5d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java
@@ -3,15 +3,11 @@ package se.leap.bitmaskclient.providersetup;
import static se.leap.bitmaskclient.base.models.Constants.EXT_JSON;
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.DOMAIN;
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;
-import static se.leap.bitmaskclient.base.utils.FileHelper.persistFile;
-import static se.leap.bitmaskclient.base.utils.InputStreamHelper.getInputStreamFrom;
import static se.leap.bitmaskclient.base.utils.InputStreamHelper.inputStreamToJson;
import static se.leap.bitmaskclient.base.utils.InputStreamHelper.loadInputStreamAsString;
@@ -21,18 +17,18 @@ import androidx.annotation.VisibleForTesting;
import org.json.JSONObject;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import se.leap.bitmaskclient.base.models.Provider;
+import se.leap.bitmaskclient.base.utils.PreferenceHelper;
/**
* Created by parmegv on 4/12/14.
@@ -40,18 +36,17 @@ import se.leap.bitmaskclient.base.models.Provider;
public class ProviderManager {
private final AssetManager assetsManager;
- private File externalFilesDir;
private Set<Provider> defaultProviders;
- private Set<Provider> customProviders;
+ // key: MainURL String, value: Provider
+ private HashMap<String, Provider> customProviders;
private Set<String> defaultProviderURLs;
- private Set<String> customProviderURLs;
private static ProviderManager instance;
private boolean addDummyEntry = false;
- public static ProviderManager getInstance(AssetManager assetsManager, File externalFilesDir) {
+ public static ProviderManager getInstance(AssetManager assetsManager) {
if (instance == null)
- instance = new ProviderManager(assetsManager, externalFilesDir);
+ instance = new ProviderManager(assetsManager);
return instance;
}
@@ -65,10 +60,10 @@ public class ProviderManager {
this.addDummyEntry = addDummyEntry;
}
- private ProviderManager(AssetManager assetManager, File externalFilesDir) {
+ private ProviderManager(AssetManager assetManager) {
this.assetsManager = assetManager;
addDefaultProviders(assetManager);
- addCustomProviders(externalFilesDir);
+ addCustomProviders();
}
private void addDefaultProviders(AssetManager assetManager) {
@@ -122,29 +117,8 @@ public class ProviderManager {
}
- private void addCustomProviders(File externalFilesDir) {
- this.externalFilesDir = externalFilesDir;
- customProviders = externalFilesDir != null && externalFilesDir.isDirectory() ?
- customProvidersFromFiles(externalFilesDir.list()) :
- new HashSet<>();
- customProviderURLs = getProviderUrlSetFromProviderSet(customProviders);
- }
-
- private Set<Provider> customProvidersFromFiles(String[] files) {
- Set<Provider> providers = new HashSet<>();
- try {
- for (String file : files) {
- InputStream inputStream = getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file);
- JSONObject providerConfig = inputStreamToJson(inputStream);
- String mainUrl = providerConfig.optString(MAIN_URL);
- String domain = providerConfig.optString(DOMAIN);
- providers.add(Provider.createCustomProvider(mainUrl, domain));
- }
- } catch (FileNotFoundException | NullPointerException e) {
- e.printStackTrace();
- }
-
- return providers;
+ private void addCustomProviders() {
+ customProviders = PreferenceHelper.getCustomProviders();
}
public List<Provider> providers() {
@@ -155,7 +129,7 @@ public class ProviderManager {
List<Provider> allProviders = new ArrayList<>();
allProviders.addAll(defaultProviders);
if(customProviders != null)
- allProviders.addAll(customProviders);
+ allProviders.addAll(customProviders.values());
if (addEmptyProvider) {
//add an option to add a custom provider
allProviders.add(new Provider());
@@ -177,16 +151,19 @@ public class ProviderManager {
}
public boolean add(Provider element) {
- return element != null &&
- !defaultProviderURLs.contains(element.getMainUrl().toString()) &&
- customProviders.add(element) &&
- customProviderURLs.add(element.getMainUrl().toString());
+ boolean addElement = element != null &&
+ !defaultProviderURLs.contains(element.getMainUrlString()) &&
+ !customProviders.containsKey(element.getMainUrlString());
+ if (addElement) {
+ customProviders.put(element.getMainUrlString(), element);
+ return true;
+ }
+ return false;
}
public boolean remove(Object element) {
return element instanceof Provider &&
- customProviders.remove(element) &&
- customProviderURLs.remove(((Provider) element).getMainUrl().toString());
+ customProviders.remove(((Provider) element).getMainUrlString()) != null;
}
public boolean addAll(Collection<? extends Provider> elements) {
@@ -194,9 +171,11 @@ public class ProviderManager {
boolean addedAll = true;
while (iterator.hasNext()) {
Provider p = (Provider) iterator.next();
- addedAll = customProviders.add(p) &&
- customProviderURLs.add(p.getMainUrl().toString()) &&
- addedAll;
+ boolean containsKey = customProviders.containsKey(p.getMainUrlString());
+ if (!containsKey) {
+ customProviders.put(p.getMainUrlString(), p);
+ }
+ addedAll = !containsKey && addedAll;
}
return addedAll;
}
@@ -204,15 +183,8 @@ public class ProviderManager {
public boolean removeAll(Collection<?> elements) {
Iterator iterator = elements.iterator();
boolean removedAll = true;
- try {
- while (iterator.hasNext()) {
- Provider p = (Provider) iterator.next();
- removedAll = ((defaultProviders.remove(p) && defaultProviderURLs.remove(p.getMainUrl().toString())) ||
- (customProviders.remove(p) && customProviderURLs.remove(p.getMainUrl().toString()))) &&
- removedAll;
- }
- } catch (ClassCastException e) {
- return false;
+ while (iterator.hasNext()) {
+ removedAll = remove(iterator.next()) && removedAll;
}
return removedAll;
@@ -221,37 +193,10 @@ public class ProviderManager {
public void clear() {
defaultProviders.clear();
customProviders.clear();
- customProviderURLs.clear();
defaultProviderURLs.clear();
}
- public void saveCustomProvidersToFile() {
- try {
- deleteLegacyCustomProviders();
-
- for (Provider provider : customProviders) {
- File providerFile = createFile(externalFilesDir, provider.getName() + EXT_JSON);
- if (!providerFile.exists()) {
- persistFile(providerFile, provider.toJson().toString());
- }
- }
- } catch (IOException | SecurityException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Deletes persisted custom providers from from internal storage that are not in customProviders list anymore
- */
- private void deleteLegacyCustomProviders() throws IOException, SecurityException {
- Set<Provider> persistedCustomProviders = externalFilesDir != null && externalFilesDir.isDirectory() ?
- customProvidersFromFiles(externalFilesDir.list()) : new HashSet<Provider>();
- persistedCustomProviders.removeAll(customProviders);
- for (Provider providerToDelete : persistedCustomProviders) {
- File providerFile = createFile(externalFilesDir, providerToDelete.getName() + EXT_JSON);
- if (providerFile.exists()) {
- providerFile.delete();
- }
- }
+ public void saveCustomProviders() {
+ PreferenceHelper.setCustomProviders(new HashSet<>(customProviders.values()));
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
index cdb8bd78..58fccc65 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
@@ -78,8 +78,7 @@ public class CircumventionSetupFragment extends BaseSetupFragment implements Can
}
private void loadProviderFromAssets() {
- ProviderManager providerManager = ProviderManager.getInstance(getContext().getApplicationContext().getAssets(),
- getContext().getExternalFilesDir(null));
+ ProviderManager providerManager = ProviderManager.getInstance(getContext().getApplicationContext().getAssets());
providerManager.setAddDummyEntry(false);
setupActivityCallback.onProviderSelected(providerManager.providers().get(0));
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
index e8f37e43..8ccfee22 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
@@ -2,7 +2,6 @@ package se.leap.bitmaskclient.providersetup.fragments;
import static se.leap.bitmaskclient.providersetup.fragments.viewmodel.ProviderSelectionViewModel.ADD_PROVIDER;
-import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Editable;
@@ -20,7 +19,6 @@ import java.util.ArrayList;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.models.ProviderObservable;
import se.leap.bitmaskclient.base.utils.ViewHelper;
import se.leap.bitmaskclient.databinding.FProviderSelectionBinding;
import se.leap.bitmaskclient.providersetup.activities.CancelCallback;
@@ -46,8 +44,7 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this,
new ProviderSelectionViewModelFactory(
- getContext().getApplicationContext().getAssets(),
- getContext().getExternalFilesDir(null))).
+ getContext().getApplicationContext().getAssets())).
get(ProviderSelectionViewModel.class);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModel.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModel.java
index aa2fe7cb..53d02b46 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModel.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModel.java
@@ -8,7 +8,6 @@ import android.webkit.URLUtil;
import androidx.lifecycle.ViewModel;
-import java.io.File;
import java.util.List;
import se.leap.bitmaskclient.R;
@@ -22,8 +21,8 @@ public class ProviderSelectionViewModel extends ViewModel {
private int selected = 0;
private String customUrl;
- public ProviderSelectionViewModel(AssetManager assetManager, File externalFilesDir) {
- providerManager = ProviderManager.getInstance(assetManager, externalFilesDir);
+ public ProviderSelectionViewModel(AssetManager assetManager) {
+ providerManager = ProviderManager.getInstance(assetManager);
providerManager.setAddDummyEntry(false);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModelFactory.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModelFactory.java
index a21e4924..f6d86e07 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModelFactory.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/viewmodel/ProviderSelectionViewModelFactory.java
@@ -6,22 +6,18 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
-import java.io.File;
-
public class ProviderSelectionViewModelFactory implements ViewModelProvider.Factory {
private final AssetManager assetManager;
- private final File externalFilesDir;
- public ProviderSelectionViewModelFactory(AssetManager assetManager, File externalFilesDir) {
+ public ProviderSelectionViewModelFactory(AssetManager assetManager) {
this.assetManager = assetManager;
- this.externalFilesDir = externalFilesDir;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(ProviderSelectionViewModel.class)) {
- return (T) new ProviderSelectionViewModel(assetManager, externalFilesDir);
+ return (T) new ProviderSelectionViewModel(assetManager);
}
throw new IllegalArgumentException("Unknown ViewModel class");
}