mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge tag '2.5.0.0beta24' into develop
2.5.0.0beta24
This commit is contained in:
@@ -55,7 +55,7 @@ You can contribute in different ways to help us on our work.
|
||||
|
||||
## F.A.Q.
|
||||
|
||||
Other questions? You can read the [F.A.Q.](https://www.keepassdx.com/FAQ)
|
||||
Other questions? You can read the [F.A.Q.](https://github.com/Kunzisoft/KeePassDX/wiki/F.A.Q.)
|
||||
|
||||
## Other devices
|
||||
|
||||
|
||||
1
_config.yml
Normal file
1
_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-cayman
|
||||
@@ -163,7 +163,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
}
|
||||
|
||||
// Attach the dialog thread to this activity
|
||||
progressDialogThread = ProgressDialogThread(this) { actionTask, result ->
|
||||
progressDialogThread = ProgressDialogThread(this) { actionTask, _ ->
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_CREATE_TASK -> {
|
||||
// TODO Check
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -236,7 +244,6 @@ 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)
|
||||
@@ -247,7 +254,6 @@ class SetOTPDialogFragment : DialogFragment() {
|
||||
mSecretWellFormed = otpSecretContainer?.error == null
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
})
|
||||
@@ -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())
|
||||
|
||||
@@ -75,9 +75,10 @@ class OpenFileHelper {
|
||||
val intentOpenDocument = Intent(APP_ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
}
|
||||
if (fragment != null)
|
||||
fragment?.startActivityForResult(intentOpenDocument, OPEN_DOC)
|
||||
@@ -85,10 +86,15 @@ class OpenFileHelper {
|
||||
activity?.startActivityForResult(intentOpenDocument, OPEN_DOC)
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private fun openActivityWithActionGetContent() {
|
||||
val intentGetContent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
}
|
||||
if (fragment != null)
|
||||
fragment?.startActivityForResult(intentGetContent, GET_CONTENT)
|
||||
|
||||
@@ -62,16 +62,10 @@ class LoadDatabaseInvalidAlgorithmException : LoadDatabaseException {
|
||||
|
||||
class LoadDatabaseDuplicateUuidException: LoadDatabaseException {
|
||||
@StringRes
|
||||
override var errorId: Int = R.string.invalid_algorithm
|
||||
override var errorId: Int = R.string.invalid_db_same_uuid
|
||||
|
||||
constructor(type: Type, uuid: PwNodeId<*>) : super() {
|
||||
parameters = Array(2) {
|
||||
when(it) {
|
||||
1 -> type.name
|
||||
2 -> uuid.toString()
|
||||
else -> {""}
|
||||
}
|
||||
}
|
||||
parameters = arrayOf(type.name, uuid.toString())
|
||||
}
|
||||
constructor(exception: Throwable) : super(exception)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
Translations from BoDEAN
|
||||
Translations from Matthias Dill
|
||||
Translations from David Ramiro
|
||||
--><resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
<string name="about_feedback">Rückmeldung</string>
|
||||
<string name="about_homepage">Webseite</string>
|
||||
<string name="about_description">Android-Implementierung des Passwortmanagers KeePass</string>
|
||||
@@ -398,8 +399,6 @@
|
||||
<string name="disable">Deaktivieren</string>
|
||||
<string name="biometric_prompt_store_credential_message">Datenbank-Anmeldeinformationen biometrisch speichern</string>
|
||||
<string name="biometric_prompt_extract_credential_message">Datenbank-Anmeldeinformationen mit biometrischen Daten extrahieren</string>
|
||||
<string name="fingerprint_open_biometric_prompt">Die Eingabeaufforderung für biometrische Daten mittels Klick auf den biometrischen Button öffnen</string>
|
||||
<string name="biometric_auto_open_prompt_title">Biometrische Eingabeaufforderung automatisch öffnen</string>
|
||||
<string name="fingerprint_auto_open_biometric_prompt">Sie können die Einstellung ändern, um die biometrische Eingabeaufforderung schnell zu öffnen und Schritt 1 nicht wiederholen zu müssen.</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Biometrische Eingabeaufforderung automatisch öffnen, wenn ein biometrischer Schlüssel für eine Datenbank definiert ist</string>
|
||||
</resources>
|
||||
@@ -10,7 +10,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user