From 47d5c3881c23548ea96482fa1d8286c30a9988e6 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 16 Nov 2024 18:34:45 -0500 Subject: [PATCH 1/4] ui: Add skeleton of an experimental new download flow This doesn't work yet at all, and is hidden behind an experimental settings switch. --- app-common/src/main/AndroidManifest.xml | 4 ++ .../openeuicc/ui/EuiccManagementFragment.kt | 12 ++++- .../im/angry/openeuicc/ui/SettingsFragment.kt | 6 +-- .../ui/wizard/DownloadWizardActivity.kt | 43 ++++++++++++++++++ .../angry/openeuicc/util/PreferenceUtils.kt | 4 ++ .../src/main/res/drawable/ic_chevron_left.xml | 5 +++ .../main/res/drawable/ic_chevron_right.xml | 5 +++ .../res/layout/activity_download_wizard.xml | 44 +++++++++++++++++++ app-common/src/main/res/values/strings.xml | 6 +++ app-common/src/main/res/xml/pref_settings.xml | 6 +++ 10 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt create mode 100644 app-common/src/main/res/drawable/ic_chevron_left.xml create mode 100644 app-common/src/main/res/drawable/ic_chevron_right.xml create mode 100644 app-common/src/main/res/layout/activity_download_wizard.xml diff --git a/app-common/src/main/AndroidManifest.xml b/app-common/src/main/AndroidManifest.xml index 11f16a6..a33838f 100644 --- a/app-common/src/main/AndroidManifest.xml +++ b/app-common/src/main/AndroidManifest.xml @@ -32,6 +32,10 @@ android:name="im.angry.openeuicc.ui.LogsActivity" android:label="@string/pref_advanced_logs" /> + + ("pref_advanced_verbose_logging") ?.bindBooleanFlow(preferenceRepository.verboseLoggingFlow, PreferenceKeys.VERBOSE_LOGGING) + + findPreference("pref_advanced_experimental_download_wizard") + ?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD) } override fun onStart() { diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt new file mode 100644 index 0000000..4db4b38 --- /dev/null +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt @@ -0,0 +1,43 @@ +package im.angry.openeuicc.ui.wizard + +import android.os.Bundle +import android.view.View +import androidx.activity.OnBackPressedCallback +import androidx.activity.enableEdgeToEdge +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding +import im.angry.openeuicc.common.R +import im.angry.openeuicc.ui.BaseEuiccAccessActivity + +class DownloadWizardActivity: BaseEuiccAccessActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_download_wizard) + onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // TODO: Actually implement this + } + }) + + val navigation = requireViewById(R.id.download_wizard_navigation) + val origHeight = navigation.layoutParams.height + + ViewCompat.setOnApplyWindowInsetsListener(navigation) { v, insets -> + val bars = insets.getInsets( + WindowInsetsCompat.Type.systemBars() + or WindowInsetsCompat.Type.displayCutout() + ) + v.updatePadding(bars.left, 0, bars.right, bars.bottom) + val newParams = navigation.layoutParams + newParams.height = origHeight + bars.bottom + navigation.layoutParams = newParams + WindowInsetsCompat.CONSUMED + } + } + + override fun onInit() { + + } +} \ No newline at end of file diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt index 262482a..ebc32d9 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt @@ -25,6 +25,7 @@ object PreferenceKeys { val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch") val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim") val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging") + val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard") } class PreferenceRepository(context: Context) { @@ -48,6 +49,9 @@ class PreferenceRepository(context: Context) { val verboseLoggingFlow: Flow = dataStore.data.map { it[PreferenceKeys.VERBOSE_LOGGING] ?: false } + val experimentalDownloadWizardFlow: Flow = + dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false } + suspend fun updatePreference(key: Preferences.Key, value: T) { dataStore.edit { it[key] = value diff --git a/app-common/src/main/res/drawable/ic_chevron_left.xml b/app-common/src/main/res/drawable/ic_chevron_left.xml new file mode 100644 index 0000000..1152da9 --- /dev/null +++ b/app-common/src/main/res/drawable/ic_chevron_left.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app-common/src/main/res/drawable/ic_chevron_right.xml b/app-common/src/main/res/drawable/ic_chevron_right.xml new file mode 100644 index 0000000..1db5e68 --- /dev/null +++ b/app-common/src/main/res/drawable/ic_chevron_right.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app-common/src/main/res/layout/activity_download_wizard.xml b/app-common/src/main/res/layout/activity_download_wizard.xml new file mode 100644 index 0000000..7f5637c --- /dev/null +++ b/app-common/src/main/res/layout/activity_download_wizard.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 05ea4c5..47dd897 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -58,6 +58,10 @@ This download may fail This download may fail due to low remaining capacity. + Download Wizard + Back + Next + New nickname Are you sure you want to delete the profile %s? This operation is irreversible. @@ -113,6 +117,8 @@ Enable verbose logs, which may contain sensitive information. Only share your logs with someone you trust after turning this on. Logs View recent debug logs of the application + Experimental Download Wizard + Enable the experimental new download wizard. Note that it is not fully working yet. Info App Version Source Code diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 53395ed..9630612 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -41,6 +41,12 @@ app:iconSpaceReserved="false" app:title="@string/pref_advanced_logs" app:summary="@string/pref_advanced_logs_desc" /> + + Date: Sat, 16 Nov 2024 20:37:43 -0500 Subject: [PATCH 2/4] ui: Set up progress bar for the new wizard --- .../ui/wizard/DownloadWizardActivity.kt | 7 ++++++- .../res/layout/activity_download_wizard.xml | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt index 4db4b38..edd9f2e 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt @@ -2,6 +2,7 @@ package im.angry.openeuicc.ui.wizard import android.os.Bundle import android.view.View +import android.widget.ProgressBar import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.core.view.ViewCompat @@ -11,6 +12,8 @@ import im.angry.openeuicc.common.R import im.angry.openeuicc.ui.BaseEuiccAccessActivity class DownloadWizardActivity: BaseEuiccAccessActivity() { + private lateinit var progressBar: ProgressBar + override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) @@ -21,6 +24,8 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() { } }) + progressBar = requireViewById(R.id.progress) + val navigation = requireViewById(R.id.download_wizard_navigation) val origHeight = navigation.layoutParams.height @@ -38,6 +43,6 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() { } override fun onInit() { - + progressBar.visibility = View.GONE } } \ No newline at end of file diff --git a/app-common/src/main/res/layout/activity_download_wizard.xml b/app-common/src/main/res/layout/activity_download_wizard.xml index 7f5637c..605eca2 100644 --- a/app-common/src/main/res/layout/activity_download_wizard.xml +++ b/app-common/src/main/res/layout/activity_download_wizard.xml @@ -4,6 +4,27 @@ android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> + + + + Date: Sat, 16 Nov 2024 20:59:36 -0500 Subject: [PATCH 3/4] ui: Hide developer settings behind 7 clicks --- .../im/angry/openeuicc/ui/SettingsFragment.kt | 67 ++++++++++++++++++- .../angry/openeuicc/util/PreferenceUtils.kt | 5 ++ app-common/src/main/res/values/strings.xml | 8 ++- app-common/src/main/res/xml/pref_settings.xml | 14 +++- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt index 1981db5..f368732 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt @@ -3,23 +3,48 @@ package im.angry.openeuicc.ui import android.content.Intent import android.net.Uri import android.os.Bundle +import android.widget.Toast import androidx.datastore.preferences.core.Preferences import androidx.lifecycle.lifecycleScope import androidx.preference.CheckBoxPreference import androidx.preference.Preference +import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import im.angry.openeuicc.common.R import im.angry.openeuicc.util.* import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking class SettingsFragment: PreferenceFragmentCompat() { + private lateinit var developerPref: PreferenceCategory + + // Hidden developer options switch + private var numClicks = 0 + private var lastClickTimestamp = -1L + private var lastToast: Toast? = null + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_settings, rootKey) + developerPref = findPreference("pref_developer")!! + + // Show / hide developer preference based on whether it is enabled + lifecycleScope.launch { + preferenceRepository.developerOptionsEnabledFlow.onEach { + developerPref.isVisible = it + }.collect() + } + findPreference("pref_info_app_version") - ?.summary = requireContext().selfAppVersion + ?.apply { + summary = requireContext().selfAppVersion + + // Enable developer options when this is clicked for 7 times + setOnPreferenceClickListener(this@SettingsFragment::onAppVersionClicked) + } findPreference("pref_info_source_code") ?.setOnPreferenceClickListener { @@ -48,7 +73,7 @@ class SettingsFragment: PreferenceFragmentCompat() { findPreference("pref_advanced_verbose_logging") ?.bindBooleanFlow(preferenceRepository.verboseLoggingFlow, PreferenceKeys.VERBOSE_LOGGING) - findPreference("pref_advanced_experimental_download_wizard") + findPreference("pref_developer_experimental_download_wizard") ?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD) } @@ -57,6 +82,44 @@ class SettingsFragment: PreferenceFragmentCompat() { setupRootViewInsets(requireView().requireViewById(androidx.preference.R.id.recycler_view)) } + @Suppress("UNUSED_PARAMETER") + private fun onAppVersionClicked(pref: Preference): Boolean { + if (developerPref.isVisible) return false + val now = System.currentTimeMillis() + if (now - lastClickTimestamp >= 1000) { + numClicks = 1 + } else { + numClicks++ + } + lastClickTimestamp = now + + if (numClicks == 7) { + lifecycleScope.launch { + preferenceRepository.updatePreference( + PreferenceKeys.DEVELOPER_OPTIONS_ENABLED, + true + ) + + lastToast?.cancel() + Toast.makeText( + requireContext(), + R.string.developer_options_enabled, + Toast.LENGTH_SHORT + ).show() + } + } else if (numClicks > 1) { + lastToast?.cancel() + lastToast = Toast.makeText( + requireContext(), + getString(R.string.developer_options_steps, 7 - numClicks), + Toast.LENGTH_SHORT + ) + lastToast!!.show() + } + + return true + } + private fun CheckBoxPreference.bindBooleanFlow(flow: Flow, key: Preferences.Key) { lifecycleScope.launch { flow.collect { isChecked = it } diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt index ebc32d9..700c4cd 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt @@ -25,6 +25,7 @@ object PreferenceKeys { val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch") val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim") val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging") + val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled") val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard") } @@ -49,6 +50,10 @@ class PreferenceRepository(context: Context) { val verboseLoggingFlow: Flow = dataStore.data.map { it[PreferenceKeys.VERBOSE_LOGGING] ?: false } + // ---- Developer Options ---- + val developerOptionsEnabledFlow: Flow = + dataStore.data.map { it[PreferenceKeys.DEVELOPER_OPTIONS_ENABLED] ?: false } + val experimentalDownloadWizardFlow: Flow = dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false } diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 47dd897..062a5c0 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -101,6 +101,9 @@ Save Logs at %s + You are %d steps away from being a developer. + You are now a developer! + Settings Notifications eSIM profile operations send notifications to the carrier. Fine-tune this behavior as needed here. @@ -117,8 +120,9 @@ Enable verbose logs, which may contain sensitive information. Only share your logs with someone you trust after turning this on. Logs View recent debug logs of the application - Experimental Download Wizard - Enable the experimental new download wizard. Note that it is not fully working yet. + Developer Options + Experimental Download Wizard + Enable the experimental new download wizard. Note that it is not fully working yet. Info App Version Source Code diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 9630612..150aca5 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -42,11 +42,19 @@ app:title="@string/pref_advanced_logs" app:summary="@string/pref_advanced_logs_desc" /> + + + + + app:title="@string/pref_developer_experimental_download_wizard" + app:summary="@string/pref_developer_experimental_download_wizard_desc" /> + Date: Sun, 17 Nov 2024 10:27:44 +0800 Subject: [PATCH 4/4] feat: ignore tls certificate --- .../core/DefaultEuiccChannelFactory.kt | 6 +++-- .../angry/openeuicc/core/EuiccChannelImpl.kt | 5 ++-- .../im/angry/openeuicc/ui/SettingsFragment.kt | 3 +++ .../angry/openeuicc/util/PreferenceUtils.kt | 9 ++++++++ app-common/src/main/res/values/strings.xml | 2 ++ app-common/src/main/res/xml/pref_settings.xml | 6 +++++ .../core/PrivilegedEuiccChannelFactory.kt | 3 ++- .../lpac_jni/impl/HttpInterfaceImpl.kt | 23 +++++++++++++++---- .../lpac_jni/impl/IgnoreTLSCertificate.kt | 22 ++++++++++++++++++ 9 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt diff --git a/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt b/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt index 410cccc..eea45e0 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt @@ -42,7 +42,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha port, context.preferenceRepository.verboseLoggingFlow ), - context.preferenceRepository.verboseLoggingFlow + context.preferenceRepository.verboseLoggingFlow, + context.preferenceRepository.ignoreTLSCertificate, ).also { Log.i(DefaultEuiccChannelManager.TAG, "Is OMAPI channel, setting MSS to 60") it.lpa.setEs10xMss(60) @@ -72,7 +73,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha bulkOut, context.preferenceRepository.verboseLoggingFlow ), - context.preferenceRepository.verboseLoggingFlow + context.preferenceRepository.verboseLoggingFlow, + context.preferenceRepository.ignoreTLSCertificate, ) } diff --git a/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt b/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt index 9bccbff..f305a1b 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt @@ -11,14 +11,15 @@ class EuiccChannelImpl( override val type: String, override val port: UiccPortInfoCompat, apduInterface: ApduInterface, - verboseLoggingFlow: Flow + verboseLoggingFlow: Flow, + ignoreTLSCertificate: Flow ) : EuiccChannel { override val slotId = port.card.physicalSlotIndex override val logicalSlotId = port.logicalSlotIndex override val portId = port.portIndex override val lpa: LocalProfileAssistant = - LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow)) + LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow, ignoreTLSCertificate)) override val valid: Boolean get() = lpa.valid diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt index f368732..83be1ea 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt @@ -75,6 +75,9 @@ class SettingsFragment: PreferenceFragmentCompat() { findPreference("pref_developer_experimental_download_wizard") ?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD) + + findPreference("pref_ignore_tls_certificate") + ?.bindBooleanFlow(preferenceRepository.ignoreTLSCertificate, PreferenceKeys.IGNORE_TLS_CERTIFICATE) } override fun onStart() { diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt index 700c4cd..133204c 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt @@ -20,13 +20,19 @@ val Fragment.preferenceRepository: PreferenceRepository get() = requireContext().preferenceRepository object PreferenceKeys { + // ---- Profile Notifications ---- val NOTIFICATION_DOWNLOAD = booleanPreferencesKey("notification_download") val NOTIFICATION_DELETE = booleanPreferencesKey("notification_delete") val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch") + + // ---- Advanced ---- val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim") val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging") + + // ---- Developer Options ---- val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled") val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard") + val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate") } class PreferenceRepository(context: Context) { @@ -57,6 +63,9 @@ class PreferenceRepository(context: Context) { val experimentalDownloadWizardFlow: Flow = dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false } + val ignoreTLSCertificate: Flow = + dataStore.data.map { it[PreferenceKeys.IGNORE_TLS_CERTIFICATE] ?: false } + suspend fun updatePreference(key: Preferences.Key, value: T) { dataStore.edit { it[key] = value diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 062a5c0..a2373a3 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -123,6 +123,8 @@ Developer Options Experimental Download Wizard Enable the experimental new download wizard. Note that it is not fully working yet. + Do not check SM-DP+ TLS certificate + Do not check SM-DP+ TLS certificate, allow any RSP Info App Version Source Code diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 150aca5..d43c84b 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -55,6 +55,12 @@ app:title="@string/pref_developer_experimental_download_wizard" app:summary="@string/pref_developer_experimental_download_wizard_desc" /> + + ) : HttpInterface { +class HttpInterfaceImpl( + private val verboseLoggingFlow: Flow, + private val ignoreTLSCertificate: Flow +) : HttpInterface { companion object { private const val TAG = "HttpInterfaceImpl" } @@ -36,9 +40,6 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : HttpInt } try { - val sslContext = SSLContext.getInstance("TLS") - sslContext.init(null, trustManagers, SecureRandom()) - val conn = parsedUrl.openConnection() as HttpsURLConnection conn.connectTimeout = 2000 @@ -47,7 +48,7 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : HttpInt conn.readTimeout = 1000 } - conn.sslSocketFactory = sslContext.socketFactory + conn.sslSocketFactory = getSocketFactory() conn.requestMethod = "POST" conn.doInput = true conn.doOutput = true @@ -79,6 +80,18 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : HttpInt } } + private fun getSocketFactory(): SSLSocketFactory { + val trustManagers = + if (runBlocking { ignoreTLSCertificate.first() }) { + arrayOf(IgnoreTLSCertificate()) + } else { + this.trustManagers + } + val sslContext = SSLContext.getInstance("TLS") + sslContext.init(null, trustManagers, SecureRandom()) + return sslContext.socketFactory + } + override fun usePublicKeyIds(pkids: Array) { val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply { init(keyIdToKeystore(pkids)) diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt new file mode 100644 index 0000000..7b13282 --- /dev/null +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt @@ -0,0 +1,22 @@ +package net.typeblog.lpac_jni.impl + +import android.annotation.SuppressLint +import java.security.cert.X509Certificate +import javax.net.ssl.X509TrustManager + +@SuppressLint("CustomX509TrustManager") +class IgnoreTLSCertificate : X509TrustManager { + @SuppressLint("TrustAllX509TrustManager") + override fun checkClientTrusted(p0: Array?, p1: String?) { + return + } + + @SuppressLint("TrustAllX509TrustManager") + override fun checkServerTrusted(p0: Array?, p1: String?) { + return + } + + override fun getAcceptedIssuers(): Array { + return emptyArray() + } +} \ No newline at end of file