Skip to content

Commit

Permalink
Merge branch 'release/2.9.12'
Browse files Browse the repository at this point in the history
  • Loading branch information
J-Jamet committed Jan 23, 2021
2 parents 2928b7d + 3fd0689 commit e6b33d6
Show file tree
Hide file tree
Showing 62 changed files with 561 additions and 162 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
KeePassDX(2.9.12)
* Fix OTP token type #863
* Fix auto open biometric prompt #862
* Fix back appearance setting #865
* Fix orientation change in settings #872
* Change memory unit to MiB #851
* Small changes #642

KeePassDX(2.9.11)
* Add Keyfile XML version 2 (fix hex) #844
* Fix hex Keyfile #861
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId "com.kunzisoft.keepass"
minSdkVersion 14
targetSdkVersion 30
versionCode = 55
versionName = "2.9.11"
versionCode = 56
versionName = "2.9.12"
multiDexEnabled true

testApplicationId = "com.kunzisoft.keepass.tests"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.EditText
import android.widget.Spinner
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.google.android.material.textfield.TextInputLayout
Expand All @@ -57,6 +54,7 @@ class SetOTPDialogFragment : DialogFragment() {

private var mOtpElement: OtpElement = OtpElement()

private var otpTypeMessage: TextView? = null
private var otpTypeSpinner: Spinner? = null
private var otpTokenTypeSpinner: Spinner? = null
private var otpSecretContainer: TextInputLayout? = null
Expand All @@ -74,6 +72,8 @@ class SetOTPDialogFragment : DialogFragment() {
private var totpTokenTypeAdapter: ArrayAdapter<OtpTokenType>? = null
private var hotpTokenTypeAdapter: ArrayAdapter<OtpTokenType>? = null
private var otpAlgorithmAdapter: ArrayAdapter<TokenCalculator.HashAlgorithm>? = null
private var mHotpTokenTypeArray: Array<OtpTokenType>? = null
private var mTotpTokenTypeArray: Array<OtpTokenType>? = null

private var mManualEvent = false
private var mOnFocusChangeListener = View.OnFocusChangeListener { _, isFocus ->
Expand Down Expand Up @@ -134,6 +134,7 @@ class SetOTPDialogFragment : DialogFragment() {

activity?.let { activity ->
val root = activity.layoutInflater.inflate(R.layout.fragment_set_otp, null) as ViewGroup?
otpTypeMessage = root?.findViewById(R.id.setup_otp_type_message)
otpTypeSpinner = root?.findViewById(R.id.setup_otp_type)
otpTokenTypeSpinner = root?.findViewById(R.id.setup_otp_token_type)
otpSecretContainer = root?.findViewById(R.id.setup_otp_secret_label)
Expand Down Expand Up @@ -183,31 +184,31 @@ class SetOTPDialogFragment : DialogFragment() {

// HOTP / TOTP Type selection
val otpTypeArray = OtpType.values()
otpTypeAdapter = ArrayAdapter<OtpType>(activity,
otpTypeAdapter = ArrayAdapter(activity,
android.R.layout.simple_spinner_item, otpTypeArray).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
otpTypeSpinner?.adapter = otpTypeAdapter

// Otp Token type selection
val hotpTokenTypeArray = OtpTokenType.getHotpTokenTypeValues()
mHotpTokenTypeArray = OtpTokenType.getHotpTokenTypeValues()
hotpTokenTypeAdapter = ArrayAdapter(activity,
android.R.layout.simple_spinner_item, hotpTokenTypeArray).apply {
android.R.layout.simple_spinner_item, mHotpTokenTypeArray!!).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
// Proprietary only on closed and full version
val totpTokenTypeArray = OtpTokenType.getTotpTokenTypeValues(
mTotpTokenTypeArray = OtpTokenType.getTotpTokenTypeValues(
BuildConfig.CLOSED_STORE && BuildConfig.FULL_VERSION)
totpTokenTypeAdapter = ArrayAdapter(activity,
android.R.layout.simple_spinner_item, totpTokenTypeArray).apply {
android.R.layout.simple_spinner_item, mTotpTokenTypeArray!!).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
otpTokenTypeAdapter = hotpTokenTypeAdapter
otpTokenTypeSpinner?.adapter = otpTokenTypeAdapter

// OTP Algorithm
val otpAlgorithmArray = TokenCalculator.HashAlgorithm.values()
otpAlgorithmAdapter = ArrayAdapter<TokenCalculator.HashAlgorithm>(activity,
otpAlgorithmAdapter = ArrayAdapter(activity,
android.R.layout.simple_spinner_item, otpAlgorithmArray).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
Expand Down Expand Up @@ -372,24 +373,40 @@ class SetOTPDialogFragment : DialogFragment() {
}

private fun upgradeTokenType() {
val tokenType = mOtpElement.tokenType
when (mOtpElement.type) {
OtpType.HOTP -> {
otpPeriodContainer?.visibility = View.GONE
otpCounterContainer?.visibility = View.VISIBLE
otpTokenTypeSpinner?.adapter = hotpTokenTypeAdapter
otpTokenTypeSpinner?.setSelection(OtpTokenType
.getHotpTokenTypeValues().indexOf(mOtpElement.tokenType))
mHotpTokenTypeArray?.let { otpTokenTypeArray ->
defineOtpTokenTypeSpinner(otpTokenTypeArray, tokenType, OtpTokenType.RFC4226)
}
}
OtpType.TOTP -> {
otpPeriodContainer?.visibility = View.VISIBLE
otpCounterContainer?.visibility = View.GONE
otpTokenTypeSpinner?.adapter = totpTokenTypeAdapter
otpTokenTypeSpinner?.setSelection(OtpTokenType
.getTotpTokenTypeValues().indexOf(mOtpElement.tokenType))
mTotpTokenTypeArray?.let { otpTokenTypeArray ->
defineOtpTokenTypeSpinner(otpTokenTypeArray, tokenType, OtpTokenType.RFC6238)
}
}
}
}

private fun defineOtpTokenTypeSpinner(otpTokenTypeArray: Array<OtpTokenType>,
tokenType: OtpTokenType,
defaultTokenType: OtpTokenType) {
val formTokenType = if (otpTokenTypeArray.contains(tokenType)) {
otpTypeMessage?.visibility = View.GONE
tokenType
} else {
otpTypeMessage?.visibility = View.VISIBLE
defaultTokenType
}
otpTokenTypeSpinner?.setSelection(otpTokenTypeArray.indexOf(formTokenType))
}

private fun upgradeParameters() {
otpAlgorithmSpinner?.setSelection(TokenCalculator.HashAlgorithm.values()
.indexOf(mOtpElement.algorithm))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ abstract class LockingActivity : SpecialModeActivity() {
private set

override fun onCreate(savedInstanceState: Bundle?) {

mProgressDatabaseTaskProvider = ProgressDatabaseTaskProvider(this)

super.onCreate(savedInstanceState)

if (savedInstanceState != null
Expand All @@ -84,8 +87,6 @@ abstract class LockingActivity : SpecialModeActivity() {
}

mExitLock = false

mProgressDatabaseTaskProvider = ProgressDatabaseTaskProvider(this)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ class IOActionTask<T>(
mainScope.launch {
withContext(Dispatchers.IO) {
val asyncResult: Deferred<T?> = async {
action.invoke()
try {
action.invoke()
} catch (e: Exception) {
e.printStackTrace()
null
}
}
withContext(Dispatchers.Main) {
afterActionDatabaseListener?.invoke(asyncResult.await())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU
disconnect()
}
} ?: run {
connect(databaseUri)
this.mAutoOpenPrompt = autoOpenPrompt
connect(databaseUri)
}
} else {
disconnect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
return if (hashString != null
&& checkKeyFileHash(dataString, hashString)) {
Log.i(TAG, "Successful key file hash check.")
Hex.decodeHex(dataString)
Hex.decodeHex(dataString.toCharArray())
} else {
Log.e(TAG, "Unable to check the hash of the key file.")
null
Expand All @@ -477,7 +477,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
digest = MessageDigest.getInstance("SHA-256")
digest?.reset()
// hexadecimal encoding of the first 4 bytes of the SHA-256 hash of the key.
val dataDigest = digest.digest(Hex.decodeHex(data))
val dataDigest = digest.digest(Hex.decodeHex(data.toCharArray()))
.copyOfRange(0, 4)
.toHexString()
success = dataDigest == hash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ abstract class DatabaseVersioned<
when (keyData.size) {
32 -> return keyData
64 -> try {
return Hex.decodeHex(String(keyData))
return Hex.decodeHex(String(keyData).toCharArray())
} catch (ignoredException: Exception) {
// Key is not base 64, treat it as binary data
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,41 +129,49 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
}

fun checkDatabaseInfo() {
mDatabase.fileUri?.let {
val previousDatabaseInfo = mSnapFileDatabaseInfo
val lastFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it))

val oldDatabaseModification = previousDatabaseInfo?.lastModification
val newDatabaseModification = lastFileDatabaseInfo.lastModification

val conditionExists = previousDatabaseInfo != null
&& previousDatabaseInfo.exists != lastFileDatabaseInfo.exists
// To prevent dialog opening too often
val conditionLastModification = (oldDatabaseModification != null && newDatabaseModification != null
&& oldDatabaseModification < newDatabaseModification
&& mLastLocalSaveTime + 5000 < newDatabaseModification)

if (conditionExists || conditionLastModification) {
// Show the dialog only if it's real new info and not a delay after a save
Log.i(TAG, "Database file modified " +
"$previousDatabaseInfo != $lastFileDatabaseInfo ")
// Call listener to indicate a change in database info
if (previousDatabaseInfo != null) {
mDatabaseInfoListeners.forEach { listener ->
listener.onDatabaseInfoChanged(previousDatabaseInfo, lastFileDatabaseInfo)
try {
mDatabase.fileUri?.let {
val previousDatabaseInfo = mSnapFileDatabaseInfo
val lastFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it))

val oldDatabaseModification = previousDatabaseInfo?.lastModification
val newDatabaseModification = lastFileDatabaseInfo.lastModification

val conditionExists = previousDatabaseInfo != null
&& previousDatabaseInfo.exists != lastFileDatabaseInfo.exists
// To prevent dialog opening too often
val conditionLastModification = (oldDatabaseModification != null && newDatabaseModification != null
&& oldDatabaseModification < newDatabaseModification
&& mLastLocalSaveTime + 5000 < newDatabaseModification)

if (conditionExists || conditionLastModification) {
// Show the dialog only if it's real new info and not a delay after a save
Log.i(TAG, "Database file modified " +
"$previousDatabaseInfo != $lastFileDatabaseInfo ")
// Call listener to indicate a change in database info
if (previousDatabaseInfo != null) {
mDatabaseInfoListeners.forEach { listener ->
listener.onDatabaseInfoChanged(previousDatabaseInfo, lastFileDatabaseInfo)
}
}
mSnapFileDatabaseInfo = lastFileDatabaseInfo
}
mSnapFileDatabaseInfo = lastFileDatabaseInfo
}
} catch (e: Exception) {
Log.e(TAG, "Unable to check database info", e)
}
}

fun saveDatabaseInfo() {
mDatabase.fileUri?.let {
mSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it))
Log.i(TAG, "Database file saved $mSnapFileDatabaseInfo")
try {
mDatabase.fileUri?.let {
mSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it))
Log.i(TAG, "Database file saved $mSnapFileDatabaseInfo")
}
} catch (e: Exception) {
Log.e(TAG, "Unable to check database info", e)
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/kunzisoft/keepass/otp/OtpElement.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
@Throws(IllegalArgumentException::class)
fun setHexSecret(secret: String) {
if (secret.isNotEmpty())
otpModel.secret = Hex.decodeHex(secret)
otpModel.secret = Hex.decodeHex(secret.toCharArray())
else
throw IllegalArgumentException()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,13 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
if (styleEnabled) {
Stylish.assignStyle(styleIdString)
activity.recreate()
// Relaunch the current activity to redraw theme
(activity as? SettingsActivity?)?.apply {
keepCurrentScreen()
startActivity(intent)
finish()
activity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
}
}
styleEnabled
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
private var mEncryptionAlgorithmPref: DialogListExplanationPreference? = null
private var mKeyDerivationPref: DialogListExplanationPreference? = null
private var mRoundPref: InputKdfNumberPreference? = null
private var mMemoryPref: InputKdfNumberPreference? = null
private var mMemoryPref: InputKdfSizePreference? = null
private var mParallelismPref: InputKdfNumberPreference? = null

override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
Expand Down Expand Up @@ -231,7 +231,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
}

// Memory Usage
mMemoryPref = findPreference<InputKdfNumberPreference>(getString(R.string.memory_usage_key))?.apply {
mMemoryPref = findPreference<InputKdfSizePreference>(getString(R.string.memory_usage_key))?.apply {
summary = mDatabase.memoryUsage.toString()
}

Expand Down Expand Up @@ -553,7 +553,10 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
true
}
R.id.menu_reload_database -> {
settingActivity?.mProgressDatabaseTaskProvider?.startDatabaseReload(false)
settingActivity?.apply {
keepCurrentScreen()
mProgressDatabaseTaskProvider?.startDatabaseReload(false)
}
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
APPLICATION, FORM_FILLING, ADVANCED_UNLOCK, APPEARANCE, DATABASE, DATABASE_SECURITY, DATABASE_MASTER_KEY
}

fun getScreen(): Screen {
return Screen.values()[requireArguments().getInt(TAG_KEY)]
}

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
onCreateScreenPreference(
Screen.values()[requireArguments().getInt(TAG_KEY)],
getScreen(),
savedInstanceState,
rootKey)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ open class SettingsActivity
intent.extras?.getString(FRAGMENT_ARG)?.let { fragmentScreenName ->
onNestedPreferenceSelected(NestedSettingsFragment.Screen.valueOf(fragmentScreenName), true)
}
// Eat state
intent.removeExtra(FRAGMENT_ARG)
}
}

Expand Down Expand Up @@ -224,11 +226,19 @@ open class SettingsActivity
}

toolbar?.title = NestedSettingsFragment.retrieveTitle(resources, key)
// To reload the current screen
intent.putExtra(FRAGMENT_ARG, key.name)
hideOrShowLockButton(key)
}

/**
* To keep the current screen when activity is reloaded
*/
fun keepCurrentScreen() {
(supportFragmentManager.findFragmentByTag(TAG_NESTED) as? NestedSettingsFragment?)
?.getScreen()?.let { fragmentKey ->
intent.putExtra(FRAGMENT_ARG, fragmentKey.name)
}
}

override fun onNestedPreferenceSelected(key: NestedSettingsFragment.Screen, reload: Boolean) {
if (mTimeoutEnable)
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import androidx.preference.DialogPreference
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine

class InputKdfNumberPreference @JvmOverloads constructor(context: Context,
open class InputKdfNumberPreference @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.dialogPreferenceStyle,
defStyleRes: Int = defStyleAttr)
Expand Down
Loading

0 comments on commit e6b33d6

Please sign in to comment.