mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Setting to remember hardware key
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 2,
|
||||||
|
"identityHash": "f8fb4aed546de19ae7ca0797f49b26a4",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "file_database_history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `database_alias` TEXT NOT NULL, `keyfile_uri` TEXT, `hardware_key` TEXT, `updated` INTEGER NOT NULL, PRIMARY KEY(`database_uri`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "databaseUri",
|
||||||
|
"columnName": "database_uri",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "databaseAlias",
|
||||||
|
"columnName": "database_alias",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "keyFileUri",
|
||||||
|
"columnName": "keyfile_uri",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hardwareKey",
|
||||||
|
"columnName": "hardware_key",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "updated",
|
||||||
|
"columnName": "updated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"database_uri"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "cipher_database",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `encrypted_value` TEXT NOT NULL, `specs_parameters` TEXT NOT NULL, PRIMARY KEY(`database_uri`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "databaseUri",
|
||||||
|
"columnName": "database_uri",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "encryptedValue",
|
||||||
|
"columnName": "encrypted_value",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "specParameters",
|
||||||
|
"columnName": "specs_parameters",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"database_uri"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f8fb4aed546de19ae7ca0797f49b26a4')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,7 @@ import com.kunzisoft.keepass.autofill.AutofillHelper
|
|||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
|
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
|
||||||
import com.kunzisoft.keepass.database.element.MainCredential
|
import com.kunzisoft.keepass.database.element.MainCredential
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.RegisterInfo
|
import com.kunzisoft.keepass.model.RegisterInfo
|
||||||
import com.kunzisoft.keepass.model.SearchInfo
|
import com.kunzisoft.keepass.model.SearchInfo
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||||
@@ -155,8 +156,9 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryOpenListener { fileDatabaseHistoryEntityToOpen ->
|
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryOpenListener { fileDatabaseHistoryEntityToOpen ->
|
||||||
fileDatabaseHistoryEntityToOpen.databaseUri?.let { databaseFileUri ->
|
fileDatabaseHistoryEntityToOpen.databaseUri?.let { databaseFileUri ->
|
||||||
launchPasswordActivity(
|
launchPasswordActivity(
|
||||||
databaseFileUri,
|
databaseFileUri,
|
||||||
fileDatabaseHistoryEntityToOpen.keyFileUri
|
fileDatabaseHistoryEntityToOpen.keyFileUri,
|
||||||
|
fileDatabaseHistoryEntityToOpen.hardwareKey
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +252,8 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
?: MainCredential()
|
?: MainCredential()
|
||||||
databaseFilesViewModel.addDatabaseFile(
|
databaseFilesViewModel.addDatabaseFile(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
mainCredential.keyFileUri
|
mainCredential.keyFileUri,
|
||||||
|
mainCredential.hardwareKey
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,10 +300,11 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_LONG).asError().show()
|
Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_LONG).asError().show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchPasswordActivity(databaseUri: Uri, keyFile: Uri?) {
|
private fun launchPasswordActivity(databaseUri: Uri, keyFile: Uri?, hardwareKey: HardwareKey?) {
|
||||||
MainCredentialActivity.launch(this,
|
MainCredentialActivity.launch(this,
|
||||||
databaseUri,
|
databaseUri,
|
||||||
keyFile,
|
keyFile,
|
||||||
|
hardwareKey,
|
||||||
{ exception ->
|
{ exception ->
|
||||||
fileNoFoundAction(exception)
|
fileNoFoundAction(exception)
|
||||||
},
|
},
|
||||||
@@ -321,7 +325,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun launchPasswordActivityWithPath(databaseUri: Uri) {
|
private fun launchPasswordActivityWithPath(databaseUri: Uri) {
|
||||||
launchPasswordActivity(databaseUri, null)
|
launchPasswordActivity(databaseUri, null, null)
|
||||||
// Delete flickering for kitkat <=
|
// Delete flickering for kitkat <=
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||||
overridePendingTransition(0, 0)
|
overridePendingTransition(0, 0)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ import com.kunzisoft.keepass.database.element.MainCredential
|
|||||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||||
import com.kunzisoft.keepass.database.exception.FileNotFoundDatabaseException
|
import com.kunzisoft.keepass.database.exception.FileNotFoundDatabaseException
|
||||||
import com.kunzisoft.keepass.education.PasswordActivityEducation
|
import com.kunzisoft.keepass.education.PasswordActivityEducation
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.*
|
import com.kunzisoft.keepass.model.*
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.CIPHER_DATABASE_KEY
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.CIPHER_DATABASE_KEY
|
||||||
@@ -102,6 +103,8 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
private var mRememberKeyFile: Boolean = false
|
private var mRememberKeyFile: Boolean = false
|
||||||
private var mExternalFileHelper: ExternalFileHelper? = null
|
private var mExternalFileHelper: ExternalFileHelper? = null
|
||||||
|
|
||||||
|
private var mRememberHardwareKey: Boolean = false
|
||||||
|
|
||||||
private var mReadOnly: Boolean = false
|
private var mReadOnly: Boolean = false
|
||||||
private var mForceReadOnly: Boolean = false
|
private var mForceReadOnly: Boolean = false
|
||||||
|
|
||||||
@@ -134,6 +137,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
PreferencesUtil.enableReadOnlyDatabase(this)
|
PreferencesUtil.enableReadOnlyDatabase(this)
|
||||||
}
|
}
|
||||||
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
|
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
|
||||||
|
mRememberHardwareKey = PreferencesUtil.rememberHardwareKey(this)
|
||||||
|
|
||||||
// Build elements to manage keyfile selection
|
// Build elements to manage keyfile selection
|
||||||
mExternalFileHelper = ExternalFileHelper(this)
|
mExternalFileHelper = ExternalFileHelper(this)
|
||||||
@@ -216,10 +220,19 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
databaseKeyFileUri
|
databaseKeyFileUri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val databaseHardwareKey = mainCredentialView?.getMainCredential()?.hardwareKey
|
||||||
|
val hardwareKey =
|
||||||
|
if (mRememberHardwareKey
|
||||||
|
&& databaseHardwareKey == null) {
|
||||||
|
databaseFile?.hardwareKey
|
||||||
|
} else {
|
||||||
|
databaseHardwareKey
|
||||||
|
}
|
||||||
|
|
||||||
// Define title
|
// Define title
|
||||||
filenameView?.text = databaseFile?.databaseAlias ?: ""
|
filenameView?.text = databaseFile?.databaseAlias ?: ""
|
||||||
|
|
||||||
onDatabaseFileLoaded(databaseFile?.databaseUri, keyFileUri)
|
onDatabaseFileLoaded(databaseFile?.databaseUri, keyFileUri, hardwareKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +240,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this@MainCredentialActivity)
|
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this@MainCredentialActivity)
|
||||||
|
mRememberHardwareKey = PreferencesUtil.rememberHardwareKey(this@MainCredentialActivity)
|
||||||
|
|
||||||
// Back to previous keyboard is setting activated
|
// Back to previous keyboard is setting activated
|
||||||
if (PreferencesUtil.isKeyboardPreviousDatabaseCredentialsEnable(this@MainCredentialActivity)) {
|
if (PreferencesUtil.isKeyboardPreviousDatabaseCredentialsEnable(this@MainCredentialActivity)) {
|
||||||
@@ -344,24 +358,36 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
private fun getUriFromIntent(intent: Intent?) {
|
private fun getUriFromIntent(intent: Intent?) {
|
||||||
// If is a view intent
|
// If is a view intent
|
||||||
val action = intent?.action
|
val action = intent?.action
|
||||||
if (action != null
|
if (action == VIEW_INTENT) {
|
||||||
&& action == VIEW_INTENT) {
|
fillCredentials(
|
||||||
mDatabaseFileUri = intent.data
|
intent.data,
|
||||||
mainCredentialView?.populateKeyFileView(UriUtil.getUriFromIntent(intent, KEY_KEYFILE))
|
UriUtil.getUriFromIntent(intent, KEY_KEYFILE),
|
||||||
|
HardwareKey.getHardwareKeyFromString(intent.getStringExtra(KEY_HARDWARE_KEY))
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
mDatabaseFileUri = intent?.getParcelableExtra(KEY_FILENAME)
|
fillCredentials(
|
||||||
intent?.getParcelableExtra<Uri?>(KEY_KEYFILE)?.let {
|
intent?.getParcelableExtra(KEY_FILENAME),
|
||||||
mainCredentialView?.populateKeyFileView(it)
|
intent?.getParcelableExtra(KEY_KEYFILE),
|
||||||
}
|
HardwareKey.getHardwareKeyFromString(intent?.getStringExtra(KEY_HARDWARE_KEY))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
intent?.removeExtra(KEY_KEYFILE)
|
intent?.removeExtra(KEY_KEYFILE)
|
||||||
|
intent?.removeExtra(KEY_HARDWARE_KEY)
|
||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
mDatabaseFileUri?.let {
|
mDatabaseFileUri?.let {
|
||||||
mDatabaseFileViewModel.checkIfIsDefaultDatabase(it)
|
mDatabaseFileViewModel.checkIfIsDefaultDatabase(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fillCredentials(databaseUri: Uri?,
|
||||||
|
keyFileUri: Uri?,
|
||||||
|
hardwareKey: HardwareKey?) {
|
||||||
|
mDatabaseFileUri = databaseUri
|
||||||
|
mainCredentialView?.populateKeyFileView(keyFileUri)
|
||||||
|
mainCredentialView?.populateHardwareKeyView(hardwareKey)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
getUriFromIntent(intent)
|
getUriFromIntent(intent)
|
||||||
@@ -370,7 +396,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
private fun launchGroupActivityIfLoaded(database: Database) {
|
private fun launchGroupActivityIfLoaded(database: Database) {
|
||||||
// Check if database really loaded
|
// Check if database really loaded
|
||||||
if (database.loaded) {
|
if (database.loaded) {
|
||||||
clearCredentialsViews(true)
|
clearCredentialsViews(clearKeyFile = true, clearHardwareKey = true)
|
||||||
GroupActivity.launch(this,
|
GroupActivity.launch(this,
|
||||||
database,
|
database,
|
||||||
{ onValidateSpecialMode() },
|
{ onValidateSpecialMode() },
|
||||||
@@ -435,12 +461,19 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDatabaseFileLoaded(databaseFileUri: Uri?, keyFileUri: Uri?) {
|
private fun onDatabaseFileLoaded(databaseFileUri: Uri?,
|
||||||
|
keyFileUri: Uri?,
|
||||||
|
hardwareKey: HardwareKey?) {
|
||||||
// Define Key File text
|
// Define Key File text
|
||||||
if (mRememberKeyFile) {
|
if (mRememberKeyFile) {
|
||||||
mainCredentialView?.populateKeyFileView(keyFileUri)
|
mainCredentialView?.populateKeyFileView(keyFileUri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define hardware key
|
||||||
|
if (mRememberHardwareKey) {
|
||||||
|
mainCredentialView?.populateHardwareKeyView(hardwareKey)
|
||||||
|
}
|
||||||
|
|
||||||
// Define listener for validate button
|
// Define listener for validate button
|
||||||
confirmButtonView?.setOnClickListener {
|
confirmButtonView?.setOnClickListener {
|
||||||
mainCredentialView?.validateCredential()
|
mainCredentialView?.validateCredential()
|
||||||
@@ -476,11 +509,15 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearCredentialsViews(clearKeyFile: Boolean = !mRememberKeyFile) {
|
private fun clearCredentialsViews(clearKeyFile: Boolean = !mRememberKeyFile,
|
||||||
|
clearHardwareKey: Boolean = !mRememberHardwareKey) {
|
||||||
mainCredentialView?.populatePasswordTextView(null)
|
mainCredentialView?.populatePasswordTextView(null)
|
||||||
if (clearKeyFile) {
|
if (clearKeyFile) {
|
||||||
mainCredentialView?.populateKeyFileView(null)
|
mainCredentialView?.populateKeyFileView(null)
|
||||||
}
|
}
|
||||||
|
if (clearHardwareKey) {
|
||||||
|
mainCredentialView?.populateHardwareKeyView(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@@ -670,18 +707,24 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
|
|
||||||
private const val KEY_FILENAME = "fileName"
|
private const val KEY_FILENAME = "fileName"
|
||||||
private const val KEY_KEYFILE = "keyFile"
|
private const val KEY_KEYFILE = "keyFile"
|
||||||
|
private const val KEY_HARDWARE_KEY = "hardwareKey"
|
||||||
private const val VIEW_INTENT = "android.intent.action.VIEW"
|
private const val VIEW_INTENT = "android.intent.action.VIEW"
|
||||||
|
|
||||||
private const val KEY_READ_ONLY = "KEY_READ_ONLY"
|
private const val KEY_READ_ONLY = "KEY_READ_ONLY"
|
||||||
private const val KEY_PASSWORD = "password"
|
private const val KEY_PASSWORD = "password"
|
||||||
private const val KEY_LAUNCH_IMMEDIATELY = "launchImmediately"
|
private const val KEY_LAUNCH_IMMEDIATELY = "launchImmediately"
|
||||||
|
|
||||||
private fun buildAndLaunchIntent(activity: Activity, databaseFile: Uri, keyFile: Uri?,
|
private fun buildAndLaunchIntent(activity: Activity,
|
||||||
|
databaseFile: Uri,
|
||||||
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
intentBuildLauncher: (Intent) -> Unit) {
|
intentBuildLauncher: (Intent) -> Unit) {
|
||||||
val intent = Intent(activity, MainCredentialActivity::class.java)
|
val intent = Intent(activity, MainCredentialActivity::class.java)
|
||||||
intent.putExtra(KEY_FILENAME, databaseFile)
|
intent.putExtra(KEY_FILENAME, databaseFile)
|
||||||
if (keyFile != null)
|
if (keyFile != null)
|
||||||
intent.putExtra(KEY_KEYFILE, keyFile)
|
intent.putExtra(KEY_KEYFILE, keyFile)
|
||||||
|
if (hardwareKey != null)
|
||||||
|
intent.putExtra(KEY_HARDWARE_KEY, hardwareKey.toString())
|
||||||
intentBuildLauncher.invoke(intent)
|
intentBuildLauncher.invoke(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,8 +737,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
@Throws(FileNotFoundException::class)
|
@Throws(FileNotFoundException::class)
|
||||||
fun launch(activity: Activity,
|
fun launch(activity: Activity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?) {
|
keyFile: Uri?,
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
hardwareKey: HardwareKey?) {
|
||||||
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -710,8 +754,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launchForSearchResult(activity: Activity,
|
fun launchForSearchResult(activity: Activity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
searchInfo: SearchInfo) {
|
searchInfo: SearchInfo) {
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
EntrySelectionHelper.startActivityForSearchModeResult(
|
EntrySelectionHelper.startActivityForSearchModeResult(
|
||||||
activity,
|
activity,
|
||||||
intent,
|
intent,
|
||||||
@@ -729,8 +774,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launchForSaveResult(activity: Activity,
|
fun launchForSaveResult(activity: Activity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
searchInfo: SearchInfo) {
|
searchInfo: SearchInfo) {
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
EntrySelectionHelper.startActivityForSaveModeResult(
|
EntrySelectionHelper.startActivityForSaveModeResult(
|
||||||
activity,
|
activity,
|
||||||
intent,
|
intent,
|
||||||
@@ -748,8 +794,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launchForKeyboardResult(activity: Activity,
|
fun launchForKeyboardResult(activity: Activity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
searchInfo: SearchInfo?) {
|
searchInfo: SearchInfo?) {
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
EntrySelectionHelper.startActivityForKeyboardSelectionModeResult(
|
EntrySelectionHelper.startActivityForKeyboardSelectionModeResult(
|
||||||
activity,
|
activity,
|
||||||
intent,
|
intent,
|
||||||
@@ -768,10 +815,11 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launchForAutofillResult(activity: AppCompatActivity,
|
fun launchForAutofillResult(activity: AppCompatActivity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
activityResultLauncher: ActivityResultLauncher<Intent>?,
|
activityResultLauncher: ActivityResultLauncher<Intent>?,
|
||||||
autofillComponent: AutofillComponent,
|
autofillComponent: AutofillComponent,
|
||||||
searchInfo: SearchInfo?) {
|
searchInfo: SearchInfo?) {
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
AutofillHelper.startActivityForAutofillResult(
|
AutofillHelper.startActivityForAutofillResult(
|
||||||
activity,
|
activity,
|
||||||
intent,
|
intent,
|
||||||
@@ -789,8 +837,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launchForRegistration(activity: Activity,
|
fun launchForRegistration(activity: Activity,
|
||||||
databaseFile: Uri,
|
databaseFile: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
registerInfo: RegisterInfo?) {
|
registerInfo: RegisterInfo?) {
|
||||||
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
|
buildAndLaunchIntent(activity, databaseFile, keyFile, hardwareKey) { intent ->
|
||||||
EntrySelectionHelper.startActivityForRegistrationModeResult(
|
EntrySelectionHelper.startActivityForRegistrationModeResult(
|
||||||
activity,
|
activity,
|
||||||
intent,
|
intent,
|
||||||
@@ -806,6 +855,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
fun launch(activity: AppCompatActivity,
|
fun launch(activity: AppCompatActivity,
|
||||||
databaseUri: Uri,
|
databaseUri: Uri,
|
||||||
keyFile: Uri?,
|
keyFile: Uri?,
|
||||||
|
hardwareKey: HardwareKey?,
|
||||||
fileNoFoundAction: (exception: FileNotFoundException) -> Unit,
|
fileNoFoundAction: (exception: FileNotFoundException) -> Unit,
|
||||||
onCancelSpecialMode: () -> Unit,
|
onCancelSpecialMode: () -> Unit,
|
||||||
onLaunchActivitySpecialMode: () -> Unit,
|
onLaunchActivitySpecialMode: () -> Unit,
|
||||||
@@ -814,43 +864,67 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
|||||||
try {
|
try {
|
||||||
EntrySelectionHelper.doSpecialAction(activity.intent,
|
EntrySelectionHelper.doSpecialAction(activity.intent,
|
||||||
{
|
{
|
||||||
MainCredentialActivity.launch(activity,
|
launch(
|
||||||
databaseUri, keyFile)
|
activity,
|
||||||
|
databaseUri,
|
||||||
|
keyFile,
|
||||||
|
hardwareKey
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{ searchInfo -> // Search Action
|
{ searchInfo -> // Search Action
|
||||||
MainCredentialActivity.launchForSearchResult(activity,
|
launchForSearchResult(
|
||||||
databaseUri, keyFile,
|
activity,
|
||||||
searchInfo)
|
databaseUri,
|
||||||
|
keyFile,
|
||||||
|
hardwareKey,
|
||||||
|
searchInfo
|
||||||
|
)
|
||||||
onLaunchActivitySpecialMode()
|
onLaunchActivitySpecialMode()
|
||||||
},
|
},
|
||||||
{ searchInfo -> // Save Action
|
{ searchInfo -> // Save Action
|
||||||
MainCredentialActivity.launchForSaveResult(activity,
|
launchForSaveResult(
|
||||||
databaseUri, keyFile,
|
activity,
|
||||||
searchInfo)
|
databaseUri,
|
||||||
|
keyFile,
|
||||||
|
hardwareKey,
|
||||||
|
searchInfo
|
||||||
|
)
|
||||||
onLaunchActivitySpecialMode()
|
onLaunchActivitySpecialMode()
|
||||||
},
|
},
|
||||||
{ searchInfo -> // Keyboard Selection Action
|
{ searchInfo -> // Keyboard Selection Action
|
||||||
MainCredentialActivity.launchForKeyboardResult(activity,
|
launchForKeyboardResult(
|
||||||
databaseUri, keyFile,
|
activity,
|
||||||
searchInfo)
|
databaseUri,
|
||||||
|
keyFile,
|
||||||
|
hardwareKey,
|
||||||
|
searchInfo
|
||||||
|
)
|
||||||
onLaunchActivitySpecialMode()
|
onLaunchActivitySpecialMode()
|
||||||
},
|
},
|
||||||
{ searchInfo, autofillComponent -> // Autofill Selection Action
|
{ searchInfo, autofillComponent -> // Autofill Selection Action
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
MainCredentialActivity.launchForAutofillResult(activity,
|
launchForAutofillResult(
|
||||||
databaseUri, keyFile,
|
activity,
|
||||||
autofillActivityResultLauncher,
|
databaseUri,
|
||||||
autofillComponent,
|
keyFile,
|
||||||
searchInfo)
|
hardwareKey,
|
||||||
|
autofillActivityResultLauncher,
|
||||||
|
autofillComponent,
|
||||||
|
searchInfo
|
||||||
|
)
|
||||||
onLaunchActivitySpecialMode()
|
onLaunchActivitySpecialMode()
|
||||||
} else {
|
} else {
|
||||||
onCancelSpecialMode()
|
onCancelSpecialMode()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ registerInfo -> // Registration Action
|
{ registerInfo -> // Registration Action
|
||||||
MainCredentialActivity.launchForRegistration(activity,
|
launchForRegistration(
|
||||||
databaseUri, keyFile,
|
activity,
|
||||||
registerInfo)
|
databaseUri,
|
||||||
|
keyFile,
|
||||||
|
hardwareKey,
|
||||||
|
registerInfo
|
||||||
|
)
|
||||||
onLaunchActivitySpecialMode()
|
onLaunchActivitySpecialMode()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,8 +23,15 @@ import androidx.room.Database
|
|||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.room.AutoMigration
|
||||||
|
|
||||||
@Database(version = 1, entities = [FileDatabaseHistoryEntity::class, CipherDatabaseEntity::class])
|
@Database(
|
||||||
|
version = 2,
|
||||||
|
entities = [FileDatabaseHistoryEntity::class, CipherDatabaseEntity::class],
|
||||||
|
autoMigrations = [
|
||||||
|
AutoMigration (from = 1, to = 2)
|
||||||
|
]
|
||||||
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun fileDatabaseHistoryDao(): FileDatabaseHistoryDao
|
abstract fun fileDatabaseHistoryDao(): FileDatabaseHistoryDao
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.app.database
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.DatabaseFile
|
import com.kunzisoft.keepass.model.DatabaseFile
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||||
@@ -44,6 +45,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
DatabaseFile(
|
DatabaseFile(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||||
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
||||||
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
||||||
fileDatabaseInfo.exists,
|
fileDatabaseInfo.exists,
|
||||||
@@ -85,13 +87,14 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
|| !hideBrokenLocations) {
|
|| !hideBrokenLocations) {
|
||||||
databaseFileListLoaded.add(
|
databaseFileListLoaded.add(
|
||||||
DatabaseFile(
|
DatabaseFile(
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||||
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||||
fileDatabaseInfo.exists,
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||||
fileDatabaseInfo.getLastModificationString(),
|
fileDatabaseInfo.exists,
|
||||||
fileDatabaseInfo.getSizeString()
|
fileDatabaseInfo.getLastModificationString(),
|
||||||
|
fileDatabaseInfo.getSizeString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -107,11 +110,14 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addOrUpdateDatabaseUri(databaseUri: Uri, keyFileUri: Uri? = null,
|
fun addOrUpdateDatabaseUri(databaseUri: Uri,
|
||||||
|
keyFileUri: Uri? = null,
|
||||||
|
hardwareKey: HardwareKey? = null,
|
||||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||||
addOrUpdateDatabaseFile(DatabaseFile(
|
addOrUpdateDatabaseFile(DatabaseFile(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
keyFileUri
|
keyFileUri,
|
||||||
|
hardwareKey
|
||||||
), databaseFileAddedOrUpdatedResult)
|
), databaseFileAddedOrUpdatedResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +136,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
||||||
?: "",
|
?: "",
|
||||||
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
||||||
|
databaseFileToAddOrUpdate.hardwareKey?.value,
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -147,13 +154,14 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
||||||
fileDatabaseHistory.databaseUri)
|
fileDatabaseHistory.databaseUri)
|
||||||
DatabaseFile(
|
DatabaseFile(
|
||||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||||
fileDatabaseInfo.exists,
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||||
fileDatabaseInfo.getLastModificationString(),
|
fileDatabaseInfo.exists,
|
||||||
fileDatabaseInfo.getSizeString()
|
fileDatabaseInfo.getLastModificationString(),
|
||||||
|
fileDatabaseInfo.getSizeString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -172,10 +180,11 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
|||||||
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||||
if (returnValue > 0) {
|
if (returnValue > 0) {
|
||||||
DatabaseFile(
|
DatabaseFile(
|
||||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||||
databaseFileToDelete.databaseAlias
|
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||||
|
databaseFileToDelete.databaseAlias
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ data class FileDatabaseHistoryEntity(
|
|||||||
@ColumnInfo(name = "keyfile_uri")
|
@ColumnInfo(name = "keyfile_uri")
|
||||||
var keyFileUri: String?,
|
var keyFileUri: String?,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "hardware_key")
|
||||||
|
var hardwareKey: String?,
|
||||||
|
|
||||||
@ColumnInfo(name = "updated")
|
@ColumnInfo(name = "updated")
|
||||||
val updated: Long
|
val updated: Long
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -60,8 +60,11 @@ class CreateDatabaseRunnable(context: Context,
|
|||||||
// Add database to recent files
|
// Add database to recent files
|
||||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||||
FileDatabaseHistoryAction.getInstance(context.applicationContext)
|
FileDatabaseHistoryAction.getInstance(context.applicationContext)
|
||||||
.addOrUpdateDatabaseUri(mDatabaseUri,
|
.addOrUpdateDatabaseUri(
|
||||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mainCredential.keyFileUri else null)
|
mDatabaseUri,
|
||||||
|
if (PreferencesUtil.rememberKeyFileLocations(context)) mainCredential.keyFileUri else null,
|
||||||
|
if (PreferencesUtil.rememberHardwareKey(context)) mainCredential.hardwareKey else null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the current time to init the lock timer
|
// Register the current time to init the lock timer
|
||||||
|
|||||||
@@ -75,8 +75,11 @@ class LoadDatabaseRunnable(private val context: Context,
|
|||||||
// Save keyFile in app database
|
// Save keyFile in app database
|
||||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||||
FileDatabaseHistoryAction.getInstance(context)
|
FileDatabaseHistoryAction.getInstance(context)
|
||||||
.addOrUpdateDatabaseUri(mDatabaseUri,
|
.addOrUpdateDatabaseUri(
|
||||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null)
|
mDatabaseUri,
|
||||||
|
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null,
|
||||||
|
if (PreferencesUtil.rememberHardwareKey(context)) mMainCredential.hardwareKey else null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the biometric
|
// Register the biometric
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ enum class HardwareKey(val value: String) {
|
|||||||
FIDO2_SECRET("FIDO2 secret"),
|
FIDO2_SECRET("FIDO2 secret"),
|
||||||
CHALLENGE_RESPONSE_YUBIKEY("Yubikey challenge-response");
|
CHALLENGE_RESPONSE_YUBIKEY("Yubikey challenge-response");
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT = FIDO2_SECRET
|
val DEFAULT = FIDO2_SECRET
|
||||||
|
|
||||||
@@ -19,7 +23,9 @@ enum class HardwareKey(val value: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getHardwareKeyFromString(text: String): HardwareKey {
|
fun getHardwareKeyFromString(text: String?): HardwareKey? {
|
||||||
|
if (text == null)
|
||||||
|
return null
|
||||||
values().find { it.value == text }?.let {
|
values().find { it.value == text }?.let {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.kunzisoft.keepass.model
|
package com.kunzisoft.keepass.model
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
|
|
||||||
data class DatabaseFile(var databaseUri: Uri? = null,
|
data class DatabaseFile(var databaseUri: Uri? = null,
|
||||||
var keyFileUri: Uri? = null,
|
var keyFileUri: Uri? = null,
|
||||||
|
var hardwareKey: HardwareKey? = null,
|
||||||
var databaseDecodedPath: String? = null,
|
var databaseDecodedPath: String? = null,
|
||||||
var databaseAlias: String? = null,
|
var databaseAlias: String? = null,
|
||||||
var databaseFileExists: Boolean = false,
|
var databaseFileExists: Boolean = false,
|
||||||
|
|||||||
@@ -96,6 +96,12 @@ object PreferencesUtil {
|
|||||||
context.resources.getBoolean(R.bool.remember_keyfile_locations_default))
|
context.resources.getBoolean(R.bool.remember_keyfile_locations_default))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun rememberHardwareKey(context: Context): Boolean {
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
return prefs.getBoolean(context.getString(R.string.remember_hardware_key_key),
|
||||||
|
context.resources.getBoolean(R.bool.remember_hardware_key_default))
|
||||||
|
}
|
||||||
|
|
||||||
fun automaticallyFocusSearch(context: Context): Boolean {
|
fun automaticallyFocusSearch(context: Context): Boolean {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.auto_focus_search_key),
|
return prefs.getBoolean(context.getString(R.string.auto_focus_search_key),
|
||||||
|
|||||||
@@ -226,10 +226,10 @@ object UriUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUriFromIntent(intent: Intent, key: String): Uri? {
|
fun getUriFromIntent(intent: Intent?, key: String): Uri? {
|
||||||
try {
|
try {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
val clipData = intent.clipData
|
val clipData = intent?.clipData
|
||||||
if (clipData != null) {
|
if (clipData != null) {
|
||||||
if (clipData.description.label == key) {
|
if (clipData.description.label == key) {
|
||||||
if (clipData.itemCount == 1) {
|
if (clipData.itemCount == 1) {
|
||||||
@@ -242,7 +242,7 @@ object UriUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return intent.getParcelableExtra(key)
|
return intent?.getParcelableExtra(key)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ class HardwareKeySelectionView @JvmOverloads constructor(context: Context,
|
|||||||
hardwareKeyLayout = findViewById(R.id.input_entry_hardware_key_layout)
|
hardwareKeyLayout = findViewById(R.id.input_entry_hardware_key_layout)
|
||||||
hardwareKeyCompletion = findViewById(R.id.input_entry_hardware_key_completion)
|
hardwareKeyCompletion = findViewById(R.id.input_entry_hardware_key_completion)
|
||||||
|
|
||||||
|
hardwareKeyCompletion.isFocusable = false
|
||||||
|
hardwareKeyCompletion.isFocusableInTouchMode = false
|
||||||
|
//hardwareKeyCompletion.isEnabled = false
|
||||||
|
hardwareKeyCompletion.isCursorVisible = false
|
||||||
|
hardwareKeyCompletion.setTextIsSelectable(false)
|
||||||
hardwareKeyCompletion.inputType = InputType.TYPE_NULL
|
hardwareKeyCompletion.inputType = InputType.TYPE_NULL
|
||||||
hardwareKeyCompletion.setAdapter(mHardwareKeyAdapter)
|
hardwareKeyCompletion.setAdapter(mHardwareKeyAdapter)
|
||||||
|
|
||||||
@@ -89,8 +94,7 @@ class HardwareKeySelectionView @JvmOverloads constructor(context: Context,
|
|||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
mHardwareKey = value
|
mHardwareKey = value
|
||||||
if (value != null)
|
hardwareKeyCompletion.setText(value?.toString() ?: "")
|
||||||
hardwareKeyCompletion.setSelection(value.ordinal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var error: CharSequence?
|
var error: CharSequence?
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
|||||||
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
|
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
|
||||||
import com.kunzisoft.keepass.model.CredentialStorage
|
import com.kunzisoft.keepass.model.CredentialStorage
|
||||||
import com.kunzisoft.keepass.database.element.MainCredential
|
import com.kunzisoft.keepass.database.element.MainCredential
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
|
|
||||||
class MainCredentialView @JvmOverloads constructor(context: Context,
|
class MainCredentialView @JvmOverloads constructor(context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
@@ -156,6 +157,18 @@ class MainCredentialView @JvmOverloads constructor(context: Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun populateHardwareKeyView(hardwareKey: HardwareKey?) {
|
||||||
|
if (hardwareKey == null) {
|
||||||
|
hardwareKeySelectionView.hardwareKey = null
|
||||||
|
if (checkboxHardwareView.isChecked)
|
||||||
|
checkboxHardwareView.isChecked = false
|
||||||
|
} else {
|
||||||
|
hardwareKeySelectionView.hardwareKey = hardwareKey
|
||||||
|
if (!checkboxHardwareView.isChecked)
|
||||||
|
checkboxHardwareView.isChecked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setOpenKeyfileClickListener(externalFileHelper: ExternalFileHelper?) {
|
fun setOpenKeyfileClickListener(externalFileHelper: ExternalFileHelper?) {
|
||||||
keyFileSelectionView.setOpenDocumentClickListener(externalFileHelper)
|
keyFileSelectionView.setOpenDocumentClickListener(externalFileHelper)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.kunzisoft.keepass.app.App
|
import com.kunzisoft.keepass.app.App
|
||||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||||
import com.kunzisoft.keepass.app.database.IOActionTask
|
import com.kunzisoft.keepass.app.database.IOActionTask
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.DatabaseFile
|
import com.kunzisoft.keepass.model.DatabaseFile
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
import com.kunzisoft.keepass.utils.UriUtil
|
||||||
@@ -72,8 +73,12 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addDatabaseFile(databaseUri: Uri, keyFileUri: Uri?) {
|
fun addDatabaseFile(databaseUri: Uri, keyFileUri: Uri?, hardwareKey: HardwareKey?) {
|
||||||
mFileDatabaseHistoryAction?.addOrUpdateDatabaseUri(databaseUri, keyFileUri) { databaseFileAdded ->
|
mFileDatabaseHistoryAction?.addOrUpdateDatabaseUri(
|
||||||
|
databaseUri,
|
||||||
|
keyFileUri,
|
||||||
|
hardwareKey
|
||||||
|
) { databaseFileAdded ->
|
||||||
databaseFileAdded?.let { _ ->
|
databaseFileAdded?.let { _ ->
|
||||||
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
|
databaseFilesLoaded.value = getDatabaseFilesLoadedValue().apply {
|
||||||
this.databaseFileAction = DatabaseFileAction.ADD
|
this.databaseFileAction = DatabaseFileAction.ADD
|
||||||
@@ -96,6 +101,7 @@ class DatabaseFilesViewModel(application: Application) : AndroidViewModel(applic
|
|||||||
.find { it.databaseUri == databaseFileUpdated.databaseUri }
|
.find { it.databaseUri == databaseFileUpdated.databaseUri }
|
||||||
?.apply {
|
?.apply {
|
||||||
keyFileUri = databaseFileUpdated.keyFileUri
|
keyFileUri = databaseFileUpdated.keyFileUri
|
||||||
|
hardwareKey = databaseFileUpdated.hardwareKey
|
||||||
databaseAlias = databaseFileUpdated.databaseAlias
|
databaseAlias = databaseFileUpdated.databaseAlias
|
||||||
databaseFileExists = databaseFileUpdated.databaseFileExists
|
databaseFileExists = databaseFileUpdated.databaseFileExists
|
||||||
databaseLastModified = databaseFileUpdated.databaseLastModified
|
databaseLastModified = databaseFileUpdated.databaseLastModified
|
||||||
|
|||||||
@@ -91,6 +91,8 @@
|
|||||||
<bool name="hide_broken_locations_default" translatable="false">true</bool>
|
<bool name="hide_broken_locations_default" translatable="false">true</bool>
|
||||||
<string name="remember_keyfile_locations_key" translatable="false">remember_keyfile_locations_key</string>
|
<string name="remember_keyfile_locations_key" translatable="false">remember_keyfile_locations_key</string>
|
||||||
<bool name="remember_keyfile_locations_default" translatable="false">true</bool>
|
<bool name="remember_keyfile_locations_default" translatable="false">true</bool>
|
||||||
|
<string name="remember_hardware_key_key" translatable="false">remember_hardware_key_key</string>
|
||||||
|
<bool name="remember_hardware_key_default" translatable="false">true</bool>
|
||||||
<string name="advanced_unlock_explanation_key" translatable="false">advanced_unlock_explanation_key</string>
|
<string name="advanced_unlock_explanation_key" translatable="false">advanced_unlock_explanation_key</string>
|
||||||
<string name="biometric_unlock_enable_key" translatable="false">biometric_unlock_enable_key</string>
|
<string name="biometric_unlock_enable_key" translatable="false">biometric_unlock_enable_key</string>
|
||||||
<bool name="biometric_unlock_enable_default" translatable="false">false</bool>
|
<bool name="biometric_unlock_enable_default" translatable="false">false</bool>
|
||||||
|
|||||||
@@ -292,6 +292,8 @@
|
|||||||
<string name="remember_database_locations_summary">Keeps track of where databases are stored</string>
|
<string name="remember_database_locations_summary">Keeps track of where databases are stored</string>
|
||||||
<string name="remember_keyfile_locations_title">Remember keyfile locations</string>
|
<string name="remember_keyfile_locations_title">Remember keyfile locations</string>
|
||||||
<string name="remember_keyfile_locations_summary">Keeps track of where keyfiles are stored</string>
|
<string name="remember_keyfile_locations_summary">Keeps track of where keyfiles are stored</string>
|
||||||
|
<string name="remember_hardware_key_title">Remember hardware keys</string>
|
||||||
|
<string name="remember_hardware_key_summary">Keeps track of the hardware keys used</string>
|
||||||
<string name="show_recent_files_title">Show recent files</string>
|
<string name="show_recent_files_title">Show recent files</string>
|
||||||
<string name="show_recent_files_summary">Show locations of recent databases</string>
|
<string name="show_recent_files_summary">Show locations of recent databases</string>
|
||||||
<string name="hide_broken_locations_title">Hide broken database links</string>
|
<string name="hide_broken_locations_title">Hide broken database links</string>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/general">
|
android:title="@string/general">
|
||||||
@@ -107,6 +106,12 @@
|
|||||||
android:summary="@string/remember_keyfile_locations_summary"
|
android:summary="@string/remember_keyfile_locations_summary"
|
||||||
android:dependency="@string/remember_database_locations_key"
|
android:dependency="@string/remember_database_locations_key"
|
||||||
android:defaultValue="@bool/remember_keyfile_locations_default"/>
|
android:defaultValue="@bool/remember_keyfile_locations_default"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="@string/remember_hardware_key_key"
|
||||||
|
android:title="@string/remember_hardware_key_title"
|
||||||
|
android:summary="@string/remember_hardware_key_summary"
|
||||||
|
android:dependency="@string/remember_database_locations_key"
|
||||||
|
android:defaultValue="@bool/remember_hardware_key_default"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="@string/show_recent_files_key"
|
android:key="@string/show_recent_files_key"
|
||||||
android:title="@string/show_recent_files_title"
|
android:title="@string/show_recent_files_title"
|
||||||
|
|||||||
Reference in New Issue
Block a user