mirror of
https://github.com/Corewala/Buran
synced 2025-03-12 07:06:48 +00:00
Added dialog when client certificate is required
The biometric unlock feature is on the way, if you couldn't tell
This commit is contained in:
parent
b2ef138402
commit
d60c1a3b20
9 changed files with 38 additions and 38 deletions
|
@ -8,7 +8,6 @@ sealed class GemState {
|
|||
data class AppQuery(val uri: URI): GemState()
|
||||
data class Requesting(val uri: URI): GemState()
|
||||
data class NotGeminiRequest(val uri: URI) : GemState()
|
||||
|
||||
data class ResponseGemtext(val uri: URI, val header: GeminiResponse.Header, val lines: List<String>) : GemState()
|
||||
data class ResponseInput(val uri: URI, val header: GeminiResponse.Header) : GemState()
|
||||
data class ResponseText(val uri: URI, val header: GeminiResponse.Header, val content: String) : GemState()
|
||||
|
@ -17,8 +16,7 @@ sealed class GemState {
|
|||
data class ResponseUnknownMime(val uri: URI, val header: GeminiResponse.Header) : GemState()
|
||||
data class ResponseError(val header: GeminiResponse.Header): GemState()
|
||||
data class ResponseUnknownHost(val uri: URI): GemState()
|
||||
|
||||
data class ClientCertRequired(val uri: URI, val header: GeminiResponse.Header): GemState()
|
||||
data class ClientCertError(val header: GeminiResponse.Header): GemState()
|
||||
|
||||
object Blank: GemState()
|
||||
}
|
|
@ -6,8 +6,7 @@ import corewala.buran.io.database.history.BuranHistory
|
|||
import java.net.URI
|
||||
|
||||
interface Datasource {
|
||||
fun request(address: String, onUpdate: (state: GemState) -> Unit)
|
||||
fun request(address: String, forceDownload: Boolean, onUpdate: (state: GemState) -> Unit)
|
||||
fun request(address: String, forceDownload: Boolean, clientCertAllowed: Boolean, onUpdate: (state: GemState) -> Unit)
|
||||
fun canGoBack(): Boolean
|
||||
fun goBack(onUpdate: (state: GemState) -> Unit)
|
||||
|
||||
|
|
|
@ -32,12 +32,9 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
|||
|
||||
private var socketFactory: SSLSocketFactory? = null
|
||||
|
||||
override fun request(address: String, forceDownload: Boolean, onUpdate: (state: GemState) -> Unit) {
|
||||
override fun request(address: String, forceDownload: Boolean, clientCertAllowed: Boolean, onUpdate: (state: GemState) -> Unit) {
|
||||
this.forceDownload = forceDownload
|
||||
request(address, onUpdate)
|
||||
}
|
||||
|
||||
override fun request(address: String, onUpdate: (state: GemState) -> Unit) {
|
||||
this.onUpdate = onUpdate
|
||||
|
||||
val uri = URI.create(address)
|
||||
|
@ -45,29 +42,29 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
|||
onUpdate(GemState.Requesting(uri))
|
||||
|
||||
GlobalScope.launch {
|
||||
geminiRequest(uri, onUpdate)
|
||||
geminiRequest(uri, onUpdate, clientCertAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSSLFactory(protocol: String){
|
||||
private fun initSSLFactory(protocol: String, clientCertAllowed: Boolean){
|
||||
val sslContext = when (protocol) {
|
||||
"TLS_ALL" -> SSLContext.getInstance("TLS")
|
||||
else -> SSLContext.getInstance(protocol)
|
||||
}
|
||||
|
||||
sslContext.init(buranKeyManager.getFactory()?.keyManagers, DummyTrustManager.get(), null)
|
||||
sslContext.init(buranKeyManager.getFactory(clientCertAllowed)?.keyManagers, DummyTrustManager.get(), null)
|
||||
socketFactory = sslContext.socketFactory
|
||||
}
|
||||
|
||||
private fun geminiRequest(uri: URI, onUpdate: (state: GemState) -> Unit){
|
||||
private fun geminiRequest(uri: URI, onUpdate: (state: GemState) -> Unit, clientCertAllowed: Boolean){
|
||||
val protocol = "TLS"
|
||||
val useClientCert = prefs.getBoolean(Buran.PREF_KEY_CLIENT_CERT_ACTIVE, false)
|
||||
|
||||
//Update factory if operating mode has changed
|
||||
when {
|
||||
socketFactory == null -> initSSLFactory(protocol!!)
|
||||
useClientCert && !buranKeyManager.lastCallUsedKey -> initSSLFactory(protocol!!)
|
||||
!useClientCert && buranKeyManager.lastCallUsedKey -> initSSLFactory(protocol!!)
|
||||
socketFactory == null -> initSSLFactory(protocol!!, clientCertAllowed)
|
||||
useClientCert && !buranKeyManager.lastCallUsedKey -> initSSLFactory(protocol!!, clientCertAllowed)
|
||||
!useClientCert && buranKeyManager.lastCallUsedKey -> initSSLFactory(protocol!!, clientCertAllowed)
|
||||
}
|
||||
|
||||
val socket: SSLSocket?
|
||||
|
@ -124,7 +121,8 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
|||
|
||||
when {
|
||||
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
|
||||
header.code == GeminiResponse.REDIRECT -> request(URI.create(header.meta).toString(), onUpdate)
|
||||
header.code == GeminiResponse.REDIRECT -> request(URI.create(header.meta).toString(), false, false, onUpdate)
|
||||
header.code == GeminiResponse.CLIENT_CERTIFICATE_REQUIRED -> onUpdate(GemState.ClientCertRequired(uri, header))
|
||||
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
|
||||
header.meta.startsWith("text/gemini") -> getGemtext(bufferedReader, uri, header, onUpdate)
|
||||
header.meta.startsWith("text/") -> getString(socket, uri, header, onUpdate)
|
||||
|
@ -225,7 +223,7 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
|||
|
||||
override fun goBack(onUpdate: (state: GemState) -> Unit) {
|
||||
runtimeHistory.removeLast()
|
||||
request(runtimeHistory.last().toString(), onUpdate)
|
||||
request(runtimeHistory.last().toString(), false, false, onUpdate)
|
||||
}
|
||||
|
||||
//This just forces the factory to rebuild before the next request
|
||||
|
|
|
@ -19,10 +19,10 @@ class BuranKeyManager(val context: Context, val onKeyError: (error: String) -> U
|
|||
var lastCallUsedKey = false
|
||||
|
||||
//If the user has a key loaded load it here - or else return null
|
||||
fun getFactory(): KeyManagerFactory? {
|
||||
fun getFactory(clientCertAllowed: Boolean): KeyManagerFactory? {
|
||||
val isClientCertActive = prefs.getBoolean(Buran.PREF_KEY_CLIENT_CERT_ACTIVE, false)
|
||||
return when {
|
||||
isClientCertActive -> {
|
||||
isClientCertActive and clientCertAllowed -> {
|
||||
lastCallUsedKey = true
|
||||
val keyStore: KeyStore = KeyStore.getInstance("pkcs12")
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class GemActivity : AppCompatActivity() {
|
|||
|
||||
private val omniTerm = OmniTerm(object : OmniTerm.Listener {
|
||||
override fun request(address: String) {
|
||||
model.request(address)
|
||||
model.request(address, false)
|
||||
}
|
||||
|
||||
override fun openBrowser(address: String) = openWebLink(address)
|
||||
|
@ -393,7 +393,7 @@ class GemActivity : AppCompatActivity() {
|
|||
request("${state.uri}?${Uri.encode(editText.text.toString())}")
|
||||
editText.hideKeyboard()
|
||||
}
|
||||
setNegativeButton(R.string.cancel){ dialog, which ->
|
||||
setNegativeButton(getString(R.string.cancel)){ dialog, which ->
|
||||
editText.hideKeyboard()
|
||||
}
|
||||
setView(dialogLayout)
|
||||
|
@ -401,6 +401,18 @@ class GemActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
is GemState.ClientCertRequired -> runOnUiThread {
|
||||
loadingView(false)
|
||||
AlertDialog.Builder(this, R.style.AppDialogTheme)
|
||||
.setTitle(getString(R.string.client_certificate_required))
|
||||
.setMessage(state.header.meta)
|
||||
.setPositiveButton(getString(R.string.use_client_certificate)) { _, _ ->
|
||||
model.request(state.uri.toString(), true)
|
||||
}
|
||||
.setNegativeButton(getString(R.string.cancel)) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
is GemState.Requesting -> loadingView(true)
|
||||
is GemState.NotGeminiRequest -> externalProtocol(state)
|
||||
is GemState.ResponseError -> {
|
||||
|
@ -672,7 +684,7 @@ class GemActivity : AppCompatActivity() {
|
|||
if(getInternetStatus()){
|
||||
if(initialised){
|
||||
loadingView(true)
|
||||
return model.request(address)
|
||||
return model.request(address, false)
|
||||
}else{
|
||||
val intent = baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
|
||||
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
|
|
|
@ -19,24 +19,24 @@ class GemViewModel: ViewModel() {
|
|||
this.db = db
|
||||
this.onState = onState
|
||||
|
||||
request(home)
|
||||
request(home, false)
|
||||
}
|
||||
|
||||
fun request(address: String) {
|
||||
gemini.request(address){ state ->
|
||||
fun request(address: String, clientCertAllowed: Boolean) {
|
||||
gemini.request(address, false, clientCertAllowed){ state ->
|
||||
onState(state)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestBinaryDownload(uri: URI) {
|
||||
gemini.request(uri.toString(), true){ state ->
|
||||
gemini.request(uri.toString(), true, false){ state ->
|
||||
onState(state)
|
||||
}
|
||||
}
|
||||
|
||||
//todo - same action as above... refactor
|
||||
fun requestInlineImage(uri: URI, onImageReady: (cacheUri: Uri?) -> Unit){
|
||||
gemini.request(uri.toString()){ state ->
|
||||
gemini.request(uri.toString(), false, false){ state ->
|
||||
when (state) {
|
||||
is GemState.ResponseImage -> onImageReady(state.cacheUri)
|
||||
else -> onState(state)
|
||||
|
|
|
@ -294,15 +294,6 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
|
|||
}
|
||||
|
||||
certificateCategory.addPreference(clientCertPassword)
|
||||
|
||||
useClientCertPreference = SwitchPreferenceCompat(context)
|
||||
useClientCertPreference.key = Buran.PREF_KEY_CLIENT_CERT_ACTIVE
|
||||
useClientCertPreference.title = getString(R.string.use_client_certificate)
|
||||
certificateCategory.addPreference(useClientCertPreference)
|
||||
|
||||
if (!hasCert) {
|
||||
useClientCertPreference.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDots(value: String): String {
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
<string name="tap_to_select_client_certificate">Cliquez pour sélectionner un certificat client</string>
|
||||
<string name="client_certificate_password">Mot de passe du Certificat Client</string>
|
||||
<string name="no_password">Pas de mot de passe</string>
|
||||
<string name="use_client_certificate">Utiliser un Certificat Client</string>
|
||||
<string name="use_client_certificate">Utiliser Certificat Client</string>
|
||||
<string name="client_certificate_required">Certificat Client Requis</string>
|
||||
<string name="set_home_capsule">Choisir comme capsule d\'accueil</string>
|
||||
<string name="check_for_updates">Rechercher des nouvelles versions</string>
|
||||
<string name="new_version_available">Nouvelle version disponible</string>
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
<string name="client_certificate_password">Client Certificate Password</string>
|
||||
<string name="no_password">No Password</string>
|
||||
<string name="use_client_certificate">Use Client Certificate</string>
|
||||
<string name="client_certificate_required">Client Certificate Required</string>
|
||||
<string name="set_home_capsule">Set home capsule</string>
|
||||
<string name="check_for_updates">Check for updates</string>
|
||||
<string name="new_version_available">New version available</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue