Skip to content

Commit

Permalink
Added proxy functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
martenrebane committed Dec 20, 2023
1 parent 41e4f62 commit 7e11306
Show file tree
Hide file tree
Showing 60 changed files with 2,765 additions and 1,078 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.text.Normalizer;
Expand All @@ -49,12 +50,14 @@
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import ee.ria.DigiDoc.BuildConfig;
import ee.ria.DigiDoc.R;
import ee.ria.DigiDoc.android.Activity;
import ee.ria.DigiDoc.android.ApplicationApp;
import ee.ria.DigiDoc.android.accessibility.AccessibilityUtils;
import ee.ria.DigiDoc.android.main.settings.SettingsDataStore;
import ee.ria.DigiDoc.android.utils.ClickableDialogUtil;
import ee.ria.DigiDoc.android.utils.TSLException;
import ee.ria.DigiDoc.android.utils.TSLUtil;
Expand All @@ -64,6 +67,10 @@
import ee.ria.DigiDoc.android.utils.navigator.Transaction;
import ee.ria.DigiDoc.android.utils.widget.ConfirmationDialog;
import ee.ria.DigiDoc.common.FileUtil;
import ee.ria.DigiDoc.common.ManualProxy;
import ee.ria.DigiDoc.common.ProxyConfig;
import ee.ria.DigiDoc.common.ProxySetting;
import ee.ria.DigiDoc.common.ProxyUtil;
import ee.ria.DigiDoc.configuration.ConfigurationDateUtil;
import ee.ria.DigiDoc.configuration.ConfigurationManagerService;
import ee.ria.DigiDoc.configuration.ConfigurationProvider;
Expand All @@ -72,19 +79,24 @@
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.Authenticator;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.tls.OkHostnameVerifier;
import timber.log.Timber;

public final class DiagnosticsView extends CoordinatorLayout implements ContentView {

private final AppBarLayout appBarLayout;
private final NestedScrollView scrollView;
private final Toolbar toolbarView;
private static final int DEFAULT_TIMEOUT = 5;

private final Navigator navigator;
private final SimpleDateFormat dateFormat;
private final ConfirmationDialog diagnosticsRestartConfirmationDialog;
private final SettingsDataStore settingsDataStore;

private final ViewDisposables disposables;

Expand Down Expand Up @@ -112,14 +124,15 @@ public DiagnosticsView(Context context, AttributeSet attrs, int defStyleAttr) {
scrollView = findViewById(R.id.scrollView);
View saveDiagnosticsButton = findViewById(R.id.configurationSaveButton);
navigator = ApplicationApp.component(context).navigator();
settingsDataStore = ApplicationApp.component(context).settingsDataStore();

ContentView.addInvisibleElement(getContext(), this);

diagnosticsRestartConfirmationDialog = new ConfirmationDialog(navigator.activity(),
R.string.main_diagnostics_restart_message, R.id.mainDiagnosticsRestartConfirmationDialog);

SwitchCompat activateLogFileGenerating = findViewById(R.id.mainDiagnosticsLogging);
activateLogFileGenerating.setChecked(((Activity) this.getContext()).getSettingsDataStore().getIsLogFileGenerationEnabled());
activateLogFileGenerating.setChecked(settingsDataStore.getIsLogFileGenerationEnabled());
Button saveLogFileButton = findViewById(R.id.mainDiagnosticsSaveLoggingButton);
saveLogFileButton.setVisibility(
(activateLogFileGenerating.isChecked() &&
Expand Down Expand Up @@ -150,27 +163,27 @@ public DiagnosticsView(Context context, AttributeSet attrs, int defStyleAttr) {
private void fileLogToggleListener(SwitchCompat activateLogFileGenerating) {
activateLogFileGenerating.setOnCheckedChangeListener((buttonView, isChecked) -> {
Activity activityContext = ((Activity) this.getContext());
boolean isLogFileGenerationEnabled = activityContext.getSettingsDataStore().getIsLogFileGenerationEnabled();
boolean isLogFileGenerationEnabled = settingsDataStore.getIsLogFileGenerationEnabled();
if (isChecked) {
diagnosticsRestartConfirmationDialog.show();
ClickableDialogUtil.makeLinksInDialogClickable(diagnosticsRestartConfirmationDialog);
diagnosticsRestartConfirmationDialog.positiveButtonClicks()
.doOnNext(next -> {
diagnosticsRestartConfirmationDialog.dismiss();
activityContext.getSettingsDataStore().setIsLogFileGenerationEnabled(true);
settingsDataStore.setIsLogFileGenerationEnabled(true);
activityContext.restartAppWithIntent(activityContext.getIntent(), true);
})
.subscribe();
diagnosticsRestartConfirmationDialog.cancels()
.doOnNext(next -> {
diagnosticsRestartConfirmationDialog.dismiss();
activateLogFileGenerating.setChecked(false);
activityContext.getSettingsDataStore().setIsLogFileGenerationEnabled(false);
settingsDataStore.setIsLogFileGenerationEnabled(false);
})
.subscribe();
} else {
activityContext.getSettingsDataStore().setIsLogFileGenerationEnabled(false);
activityContext.getSettingsDataStore().setIsLogFileGenerationRunning(false);
settingsDataStore.setIsLogFileGenerationEnabled(false);
settingsDataStore.setIsLogFileGenerationRunning(false);
if (isLogFileGenerationEnabled) {
activityContext.restartAppWithIntent(activityContext.getIntent(), true);
}
Expand Down Expand Up @@ -387,7 +400,7 @@ private void setData(ConfigurationProvider configurationProvider) {
}

private void appendTslVersion(TextView tslUrlTextView, String tslUrl) {
tslVersionDisposable = getObservableTslVersion(tslUrl )
tslVersionDisposable = getObservableTslVersion(tslUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
Expand All @@ -396,9 +409,35 @@ private void appendTslVersion(TextView tslUrlTextView, String tslUrl) {
);
}

private ProxySetting getProxySetting() {
return settingsDataStore.getProxySetting();
}

private ManualProxy getManualProxySettings() {
return new ManualProxy(
settingsDataStore.getProxyHost(),
settingsDataStore.getProxyPort(),
settingsDataStore.getProxyUsername(),
settingsDataStore.getProxyPassword(navigator.activity())
);
}

private Observable<Integer> getObservableTslVersion(String tslUrl) {
ProxySetting proxySetting = getProxySetting();
boolean isProxySSLEnabled = settingsDataStore.getIsProxyForSSLEnabled();
boolean useHTTPSProxy = ProxyUtil.useHTTPSProxy(isProxySSLEnabled, getManualProxySettings());
ProxyConfig proxyConfig = ProxyUtil.getProxy(proxySetting, getManualProxySettings());

return Observable.fromCallable(() -> {
OkHttpClient client = new OkHttpClient();
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.proxy(proxySetting == ProxySetting.NO_PROXY || !useHTTPSProxy ? Proxy.NO_PROXY : proxyConfig.proxy())
.proxyAuthenticator(proxySetting == ProxySetting.NO_PROXY || !useHTTPSProxy ? Authenticator.NONE : proxyConfig.authenticator())
.hostnameVerifier(OkHostnameVerifier.INSTANCE)
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.callTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
OkHttpClient client = builder.build();
Request request = new Request.Builder().url(tslUrl).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful() && response.body() != null) {
Expand All @@ -414,8 +453,10 @@ private Observable<Integer> getObservableTslVersion(String tslUrl) {
}

private String getRpUuidText() {
String rpUuid = ((Activity) this.getContext()).getSettingsDataStore().getUuid();
int uuid = rpUuid.isEmpty() ? R.string.main_diagnostics_rpuuid_default : R.string.main_diagnostics_rpuuid_custom;
String rpUuid = settingsDataStore.getUuid();
int uuid = rpUuid == null || rpUuid.isEmpty()
? R.string.main_diagnostics_rpuuid_default
: R.string.main_diagnostics_rpuuid_custom;
return getResources().getString(uuid);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
package ee.ria.DigiDoc.android.main.settings;

import static ee.ria.DigiDoc.common.ProxySetting.NO_PROXY;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import javax.inject.Inject;

import ee.ria.DigiDoc.R;
import ee.ria.DigiDoc.android.main.settings.access.siva.SivaSetting;
import ee.ria.DigiDoc.android.main.settings.signing.siva.SivaSetting;
import ee.ria.DigiDoc.android.utils.ToastUtil;
import ee.ria.DigiDoc.common.EncryptedPreferences;
import ee.ria.DigiDoc.common.ManualProxy;
import ee.ria.DigiDoc.common.ProxySetting;
import timber.log.Timber;

public final class SettingsDataStore {
Expand Down Expand Up @@ -322,4 +331,95 @@ public void setSivaCertName(String cert) {
public String getSivaCertName() {
return preferences.getString(resources.getString(R.string.main_settings_siva_cert_key), "");
}

public void setProxySetting(ProxySetting proxySetting) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(resources.getString(R.string.main_settings_proxy_setting_key), proxySetting.name());
editor.commit();
}

public ProxySetting getProxySetting() {
String settingKey = preferences.getString(resources.getString(R.string.main_settings_proxy_setting_key), NO_PROXY.name());
try {
return ProxySetting.valueOf(settingKey);
} catch (IllegalArgumentException iae) {
Timber.log(Log.ERROR, iae, "Unable to get proxy setting");
return NO_PROXY;
}
}

public void setIsProxyForSSLEnabled(boolean isEnabled) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(resources.getString(R.string.main_settings_proxy_ssl_enabled_key), isEnabled);
editor.commit();
}

public boolean getIsProxyForSSLEnabled() {
return preferences.getBoolean(resources.getString(R.string.main_settings_proxy_ssl_enabled_key), true);
}

public void setProxyHost(String host) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(resources.getString(R.string.main_settings_proxy_host_key), host);
editor.commit();
}

public String getProxyHost() {
return preferences.getString(resources.getString(R.string.main_settings_proxy_host_key), "");
}

public void setProxyPort(int port) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(resources.getString(R.string.main_settings_proxy_port_key), port);
editor.commit();
}

public int getProxyPort() {
return preferences.getInt(resources.getString(R.string.main_settings_proxy_port_key), 80);
}

public void setProxyUsername(String username) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(resources.getString(R.string.main_settings_proxy_username_key), username);
editor.commit();
}

public String getProxyUsername() {
return preferences.getString(resources.getString(R.string.main_settings_proxy_username_key), "");
}

public void setProxyPassword(Context context, String password) {
SharedPreferences encryptedPreferences = getEncryptedPreferences(context);
if (encryptedPreferences != null) {
SharedPreferences.Editor editor = encryptedPreferences.edit();
editor.putString(resources.getString(R.string.main_settings_proxy_password_key), password);
editor.commit();
}
Timber.log(Log.ERROR, "Unable to set proxy password");
}

public String getProxyPassword(Context context) {
SharedPreferences encryptedPreferences = getEncryptedPreferences(context);
if (encryptedPreferences != null) {
return encryptedPreferences.getString(resources.getString(R.string.main_settings_proxy_password_key), "");
}
Timber.log(Log.ERROR, "Unable to get proxy password");
return "";
}

public ManualProxy getManualProxySettings(Context context) {
return new ManualProxy(getProxyHost(), getProxyPort(),
getProxyUsername(), getProxyPassword(context));
}

@Nullable
private static SharedPreferences getEncryptedPreferences(Context context) {
try {
return EncryptedPreferences.getEncryptedPreferences(context);
} catch (GeneralSecurityException | IOException e) {
Timber.log(Log.ERROR, e, "Unable to get encrypted preferences");
ToastUtil.showError(context, R.string.signature_update_mobile_id_error_general_client);
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@

import ee.ria.DigiDoc.R;
import ee.ria.DigiDoc.android.ApplicationApp;
import ee.ria.DigiDoc.android.main.settings.access.SettingsAccessScreen;
import ee.ria.DigiDoc.android.main.settings.access.SettingsAccessView;
import ee.ria.DigiDoc.android.main.settings.role.SettingsRoleAndAddressScreen;
import ee.ria.DigiDoc.android.main.settings.role.SettingsRoleAndAddressView;
import ee.ria.DigiDoc.android.main.settings.proxy.SettingsProxyDialog;
import ee.ria.DigiDoc.android.main.settings.rights.SettingsRightsScreen;
import ee.ria.DigiDoc.android.main.settings.rights.SettingsRightsView;
import ee.ria.DigiDoc.android.main.settings.signing.SettingsSigningScreen;
import ee.ria.DigiDoc.android.main.settings.signing.SettingsSigningView;
import ee.ria.DigiDoc.android.utils.ViewDisposables;
import ee.ria.DigiDoc.android.utils.navigator.ContentView;
import ee.ria.DigiDoc.android.utils.navigator.Navigator;
Expand All @@ -40,10 +41,11 @@ public final class SettingsView extends CoordinatorLayout implements ContentView

private final ViewDisposables disposables;

private final Button accessCategory;
private final Button roleAndAddressCategory;
private final Button defaultSettingsButton;

private final Button accessCategory;
private final Button rightsCategory;

public SettingsView(Context context) {
this(context, null);
}
Expand All @@ -62,21 +64,22 @@ public SettingsView(Context context, AttributeSet attrs, int defStyleAttr) {
settingsDataStore = ApplicationApp.component(context).settingsDataStore();
disposables = new ViewDisposables();

accessCategory = findViewById(R.id.mainSettingsAccessCategory);
roleAndAddressCategory = findViewById(R.id.mainSettingsRoleAndAddressCategory);
defaultSettingsButton = findViewById(R.id.mainSettingsUseDefaultSettings);

defaultSettingsButton.setContentDescription(
defaultSettingsButton.getText().toString().toLowerCase());
accessCategory = findViewById(R.id.mainSettingsSigningCategory);
rightsCategory = findViewById(R.id.mainSettingsRightsCategory);

toolbarView.setTitle(R.string.main_settings_title);
toolbarView.setNavigationIcon(androidx.appcompat.R.drawable.abc_ic_ab_back_material);
toolbarView.setNavigationContentDescription(R.string.back);
}

private void resetToDefaultSettings(SettingsDataStore settingsDataStore) {
SettingsAccessView.resetSettings(getContext(), settingsDataStore);
SettingsRoleAndAddressView.resetSettings(settingsDataStore);
SettingsSigningView.resetSettings(getContext(), settingsDataStore);
SettingsRightsView.resetSettings(settingsDataStore);
SettingsProxyDialog.resetSettings(getContext(), settingsDataStore);
}

@Override
Expand All @@ -102,10 +105,10 @@ public void onAttachedToWindow() {
navigator.execute(Transaction.pop())));
disposables.add(clicks(accessCategory).subscribe(o ->
navigator.execute(
Transaction.push(SettingsAccessScreen.create()))));
disposables.add(clicks(roleAndAddressCategory).subscribe(o ->
Transaction.push(SettingsSigningScreen.create()))));
disposables.add(clicks(rightsCategory).subscribe(o ->
navigator.execute(
Transaction.push(SettingsRoleAndAddressScreen.create()))));
Transaction.push(SettingsRightsScreen.create()))));
disposables.add(clicks(defaultSettingsButton).subscribe(o ->
resetToDefaultSettings(settingsDataStore)
));
Expand All @@ -116,4 +119,4 @@ public void onDetachedFromWindow() {
disposables.detach();
super.onDetachedFromWindow();
}
}
}
Loading

0 comments on commit 7e11306

Please sign in to comment.