Skip to content

Commit

Permalink
Fix OTP dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
J-Jamet committed Nov 12, 2019
1 parent 095e5e5 commit b9cfb32
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ class SetOTPDialogFragment : DialogFragment() {
private var otpAlgorithmAdapter: ArrayAdapter<TokenCalculator.HashAlgorithm>? = null

private var mManualEvent = false
private var touchListener = View.OnTouchListener { _, event ->
private var mOnFocusChangeListener = View.OnFocusChangeListener { _, isFocus ->
if (!isFocus)
mManualEvent = true
}
private var mOnTouchListener = View.OnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
mManualEvent = true
Expand Down Expand Up @@ -117,13 +121,17 @@ class SetOTPDialogFragment : DialogFragment() {
otpDigitsTextView = root?.findViewById(R.id.setup_otp_digits)

// To fix init element
otpTypeSpinner?.setOnTouchListener(touchListener)
otpTokenTypeSpinner?.setOnTouchListener(touchListener)
otpAlgorithmSpinner?.setOnTouchListener(touchListener)
otpSecretTextView?.setOnTouchListener(touchListener)
otpPeriodTextView?.setOnTouchListener(touchListener)
otpCounterTextView?.setOnTouchListener(touchListener)
otpDigitsTextView?.setOnTouchListener(touchListener)
// With tab keyboard selection
otpSecretTextView?.onFocusChangeListener = mOnFocusChangeListener
// With finger selection
otpTypeSpinner?.setOnTouchListener(mOnTouchListener)
otpTokenTypeSpinner?.setOnTouchListener(mOnTouchListener)
otpSecretTextView?.setOnTouchListener(mOnTouchListener)
otpAlgorithmSpinner?.setOnTouchListener(mOnTouchListener)
otpPeriodTextView?.setOnTouchListener(mOnTouchListener)
otpCounterTextView?.setOnTouchListener(mOnTouchListener)
otpDigitsTextView?.setOnTouchListener(mOnTouchListener)


// HOTP / TOTP Type selection
val otpTypeArray = OtpType.values()
Expand Down Expand Up @@ -178,8 +186,8 @@ class SetOTPDialogFragment : DialogFragment() {
return super.onCreateDialog(savedInstanceState)
}

override fun onStart() {
super.onStart()
override fun onResume() {
super.onResume()
(dialog as AlertDialog).getButton(Dialog.BUTTON_POSITIVE).setOnClickListener {
if (mSecretWellFormed
&& mCounterWellFormed
Expand Down Expand Up @@ -236,16 +244,14 @@ class SetOTPDialogFragment : DialogFragment() {
// Set secret in OtpElement
otpSecretTextView?.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(s: Editable?) {
if (mManualEvent) {
s?.toString()?.let { userString ->
try {
mOtpElement.setBase32Secret(userString)
otpSecretContainer?.error = null
} catch (exception: Exception) {
otpSecretContainer?.error = getString(R.string.error_otp_secret_key)
}
mSecretWellFormed = otpSecretContainer?.error == null
s?.toString()?.let { userString ->
try {
mOtpElement.setBase32Secret(userString)
otpSecretContainer?.error = null
} catch (exception: Exception) {
otpSecretContainer?.error = getString(R.string.error_otp_secret_key)
}
mSecretWellFormed = otpSecretContainer?.error == null
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
Expand Down Expand Up @@ -339,7 +345,11 @@ class SetOTPDialogFragment : DialogFragment() {
private fun upgradeParameters() {
otpAlgorithmSpinner?.setSelection(TokenCalculator.HashAlgorithm.values()
.indexOf(mOtpElement.algorithm))
otpSecretTextView?.setText(mOtpElement.getBase32Secret())
otpSecretTextView?.apply {
setText(mOtpElement.getBase32Secret())
// Cursor at end
setSelection(this.text.length)
}
otpCounterTextView?.setText(mOtpElement.counter.toString())
otpPeriodTextView?.setText(mOtpElement.period.toString())
otpDigitsTextView?.setText(mOtpElement.digits.toString())
Expand Down
18 changes: 12 additions & 6 deletions app/src/main/java/com/kunzisoft/keepass/otp/OtpElement.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.kunzisoft.keepass.otp

import com.kunzisoft.keepass.model.OtpModel
import org.apache.commons.codec.DecoderException
import org.apache.commons.codec.binary.Base32
import org.apache.commons.codec.binary.Base64
import org.apache.commons.codec.binary.Hex
Expand Down Expand Up @@ -68,15 +67,17 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {

var counter
get() = otpModel.counter
@Throws(NumberFormatException::class)
set(value) {
otpModel.counter = if (value < MIN_HOTP_COUNTER || value > MAX_HOTP_COUNTER) {
TokenCalculator.HOTP_INITIAL_COUNTER
throw NumberFormatException()
throw IllegalArgumentException()
} else value
}

var period
get() = otpModel.period
@Throws(NumberFormatException::class)
set(value) {
otpModel.period = if (value < MIN_TOTP_PERIOD || value > MAX_TOTP_PERIOD) {
TokenCalculator.TOTP_DEFAULT_PERIOD
Expand All @@ -86,6 +87,7 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {

var digits
get() = otpModel.digits
@Throws(NumberFormatException::class)
set(value) {
otpModel.digits = if (value < MIN_OTP_DIGITS|| value > MAX_OTP_DIGITS) {
TokenCalculator.OTP_DEFAULT_DIGITS
Expand All @@ -99,18 +101,20 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
otpModel.algorithm = value
}

@Throws(IllegalArgumentException::class)
fun setUTF8Secret(secret: String) {
if (secret.isNotEmpty())
otpModel.secret = secret.toByteArray(Charset.forName("UTF-8"))
else
throw DecoderException()
throw IllegalArgumentException()
}

@Throws(IllegalArgumentException::class)
fun setHexSecret(secret: String) {
if (secret.isNotEmpty())
otpModel.secret = Hex.decodeHex(secret)
else
throw DecoderException()
throw IllegalArgumentException()
}

fun getBase32Secret(): String {
Expand All @@ -119,18 +123,20 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
} ?: ""
}

@Throws(IllegalArgumentException::class)
fun setBase32Secret(secret: String) {
if (secret.isNotEmpty() && checkBase32Secret(secret))
otpModel.secret = Base32().decode(secret.toByteArray())
else
throw DecoderException()
throw IllegalArgumentException()
}

@Throws(IllegalArgumentException::class)
fun setBase64Secret(secret: String) {
if (secret.isNotEmpty() && checkBase64Secret(secret))
otpModel.secret = Base64().decode(secret.toByteArray())
else
throw DecoderException()
throw IllegalArgumentException()
}

val token: String
Expand Down
18 changes: 9 additions & 9 deletions app/src/main/java/com/kunzisoft/keepass/otp/OtpEntryFields.kt
Original file line number Diff line number Diff line change
Expand Up @@ -158,29 +158,29 @@ object OtpEntryFields {

val digitsParam = uri.getQueryParameter(DIGITS_URL_PARAM)
if (digitsParam != null && digitsParam.isNotEmpty())
otpElement.digits = try {
digitsParam.toIntOrNull() ?: OTP_DEFAULT_DIGITS
try {
otpElement.digits = digitsParam.toIntOrNull() ?: OTP_DEFAULT_DIGITS
} catch (exception: Exception) {
Log.e(TAG, "Unable to retrieve OTP digits.", exception)
OTP_DEFAULT_DIGITS
otpElement.digits = OTP_DEFAULT_DIGITS
}

val counterParam = uri.getQueryParameter(COUNTER_URL_PARAM)
if (counterParam != null && counterParam.isNotEmpty())
otpElement.counter = try {
counterParam.toLongOrNull() ?: HOTP_INITIAL_COUNTER
try {
otpElement.counter = counterParam.toLongOrNull() ?: HOTP_INITIAL_COUNTER
} catch (exception: Exception) {
Log.e(TAG, "Unable to retrieve HOTP counter.", exception)
HOTP_INITIAL_COUNTER
otpElement.counter = HOTP_INITIAL_COUNTER
}

val stepParam = uri.getQueryParameter(PERIOD_URL_PARAM)
if (stepParam != null && stepParam.isNotEmpty())
otpElement.period = try {
stepParam.toIntOrNull() ?: TOTP_DEFAULT_PERIOD
try {
otpElement.period = stepParam.toIntOrNull() ?: TOTP_DEFAULT_PERIOD
} catch (exception: Exception) {
Log.e(TAG, "Unable to retrieve TOTP period.", exception)
TOTP_DEFAULT_PERIOD
otpElement.period = TOTP_DEFAULT_PERIOD
}

val algorithmParam = uri.getQueryParameter(ALGORITHM_URL_PARAM)
Expand Down

0 comments on commit b9cfb32

Please sign in to comment.