mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
extract database module
This commit is contained in:
@@ -21,13 +21,6 @@ android {
|
||||
|
||||
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
|
||||
manifestPlaceholders = [ googleAndroidBackupAPIKey:"unused" ]
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("room.incremental", "true")
|
||||
arg("room.schemaLocation", "$projectDir/schemas".toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
@@ -78,7 +78,8 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() {
|
||||
private const val NEW_FILE_DATABASE_INFO = "NEW_FILE_DATABASE_INFO"
|
||||
|
||||
fun getInstance(oldSnapFileDatabaseInfo: SnapFileDatabaseInfo,
|
||||
newSnapFileDatabaseInfo: SnapFileDatabaseInfo)
|
||||
newSnapFileDatabaseInfo: SnapFileDatabaseInfo
|
||||
)
|
||||
: DatabaseChangedDialogFragment {
|
||||
val fragment = DatabaseChangedDialogFragment()
|
||||
fragment.arguments = Bundle().apply {
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.view.inputmethod.EditorInfo
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.OtpModel
|
||||
import com.kunzisoft.keepass.otp.OtpElement
|
||||
|
||||
@@ -1,51 +1,33 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.app.database
|
||||
|
||||
import android.content.*
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
|
||||
class CipherDatabaseAction(context: Context) {
|
||||
|
||||
private val applicationContext = context.applicationContext
|
||||
private val cipherDatabaseDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
AppDatabase.getDatabase(applicationContext)
|
||||
.cipherDatabaseDao()
|
||||
|
||||
// Temp DAO to easily remove content if object no longer in memory
|
||||
private var useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
|
||||
|
||||
private var mBinder: AdvancedUnlockNotificationService.AdvancedUnlockBinder? = null
|
||||
private var mBinder: com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.AdvancedUnlockBinder? = null
|
||||
private var mServiceConnection: ServiceConnection? = null
|
||||
|
||||
private var mDatabaseListeners = LinkedList<CipherDatabaseListener>()
|
||||
private var mAdvancedUnlockBroadcastReceiver = AdvancedUnlockNotificationService.AdvancedUnlockReceiver {
|
||||
private var mAdvancedUnlockBroadcastReceiver = com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.AdvancedUnlockReceiver {
|
||||
deleteAll()
|
||||
removeAllDataAndDetach()
|
||||
}
|
||||
@@ -67,12 +49,12 @@ class CipherDatabaseAction(context: Context) {
|
||||
@Synchronized
|
||||
private fun attachService(performedAction: () -> Unit) {
|
||||
applicationContext.registerReceiver(mAdvancedUnlockBroadcastReceiver, IntentFilter().apply {
|
||||
addAction(AdvancedUnlockNotificationService.REMOVE_ADVANCED_UNLOCK_KEY_ACTION)
|
||||
addAction(com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.REMOVE_ADVANCED_UNLOCK_KEY_ACTION)
|
||||
})
|
||||
|
||||
mServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
||||
mBinder = (serviceBinder as AdvancedUnlockNotificationService.AdvancedUnlockBinder)
|
||||
mBinder = (serviceBinder as com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.AdvancedUnlockBinder)
|
||||
performedAction.invoke()
|
||||
}
|
||||
|
||||
@@ -81,7 +63,7 @@ class CipherDatabaseAction(context: Context) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
AdvancedUnlockNotificationService.bindService(applicationContext,
|
||||
com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.bindService(applicationContext,
|
||||
mServiceConnection!!,
|
||||
Context.BIND_AUTO_CREATE)
|
||||
} catch (e: Exception) {
|
||||
@@ -97,7 +79,7 @@ class CipherDatabaseAction(context: Context) {
|
||||
} catch (e: Exception) {}
|
||||
|
||||
mServiceConnection?.let {
|
||||
AdvancedUnlockNotificationService.unbindService(applicationContext, it)
|
||||
com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.unbindService(applicationContext, it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +131,8 @@ class CipherDatabaseAction(context: Context) {
|
||||
} else {
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())?.let { cipherDatabaseEntity ->
|
||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
|
||||
?.let { cipherDatabaseEntity ->
|
||||
CipherEncryptDatabase().apply {
|
||||
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
|
||||
this.encryptedValue = Base64.decode(
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.app.database
|
||||
|
||||
import android.content.Context
|
||||
@@ -25,29 +6,31 @@ import android.util.Log
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtilDatabase
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
|
||||
class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
|
||||
private val databaseFileHistoryDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
AppDatabase.getDatabase(applicationContext)
|
||||
.fileDatabaseHistoryDao()
|
||||
|
||||
fun getDatabaseFile(databaseUri: Uri,
|
||||
databaseFileResult: (DatabaseFile?) -> Unit) {
|
||||
databaseFileResult: (com.kunzisoft.keepass.model.DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
val fileDatabaseHistoryEntity = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, databaseUri)
|
||||
val fileDatabaseHistoryEntity =
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseInfo = FileDatabaseInfo(
|
||||
applicationContext,
|
||||
databaseUri)
|
||||
DatabaseFile(
|
||||
databaseUri,
|
||||
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
||||
UriUtilDatabase.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias
|
||||
?: ""),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
@@ -68,29 +51,35 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
{
|
||||
it?.let { fileHistoryEntity ->
|
||||
fileHistoryEntity.keyFileUri?.let { keyFileUri ->
|
||||
keyFileUriResultListener.invoke(UriUtil.parse(keyFileUri))
|
||||
keyFileUriResultListener.invoke(UriUtilDatabase.parse(
|
||||
keyFileUri))
|
||||
}
|
||||
} ?: keyFileUriResultListener.invoke(null)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun getDatabaseFileList(databaseFileListResult: (List<DatabaseFile>) -> Unit) {
|
||||
fun getDatabaseFileList(databaseFileListResult: (List<com.kunzisoft.keepass.model.DatabaseFile>) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(applicationContext)
|
||||
val hideBrokenLocations =
|
||||
PreferencesUtil.hideBrokenLocations(
|
||||
applicationContext)
|
||||
// Show only uri accessible
|
||||
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
||||
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, fileDatabaseHistoryEntity.databaseUri)
|
||||
val fileDatabaseInfo = FileDatabaseInfo(
|
||||
applicationContext,
|
||||
fileDatabaseHistoryEntity.databaseUri)
|
||||
if (hideBrokenLocations && fileDatabaseInfo.exists
|
||||
|| !hideBrokenLocations) {
|
||||
|| !hideBrokenLocations
|
||||
) {
|
||||
databaseFileListLoaded.add(
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||
UriUtilDatabase.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
@@ -101,8 +90,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
}
|
||||
databaseFileListLoaded
|
||||
},
|
||||
{
|
||||
databaseFileList ->
|
||||
{ databaseFileList ->
|
||||
databaseFileList?.let {
|
||||
databaseFileListResult.invoke(it)
|
||||
}
|
||||
@@ -113,24 +101,26 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
fun addOrUpdateDatabaseUri(databaseUri: Uri,
|
||||
keyFileUri: Uri? = null,
|
||||
hardwareKey: HardwareKey? = null,
|
||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||
addOrUpdateDatabaseFile(DatabaseFile(
|
||||
databaseFileAddedOrUpdatedResult: ((com.kunzisoft.keepass.model.DatabaseFile?) -> Unit)? = null) {
|
||||
addOrUpdateDatabaseFile(com.kunzisoft.keepass.model.DatabaseFile(
|
||||
databaseUri,
|
||||
keyFileUri,
|
||||
hardwareKey
|
||||
), databaseFileAddedOrUpdatedResult)
|
||||
}
|
||||
|
||||
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: DatabaseFile,
|
||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: com.kunzisoft.keepass.model.DatabaseFile,
|
||||
databaseFileAddedOrUpdatedResult: ((com.kunzisoft.keepass.model.DatabaseFile?) -> Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
||||
// Try to get info in database first
|
||||
val fileDatabaseHistoryRetrieve = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseHistoryRetrieve =
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
|
||||
// Complete alias if not exists
|
||||
val fileDatabaseHistory = FileDatabaseHistoryEntity(
|
||||
val fileDatabaseHistory =
|
||||
FileDatabaseHistoryEntity(
|
||||
databaseUri.toString(),
|
||||
databaseFileToAddOrUpdate.databaseAlias
|
||||
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
||||
@@ -151,13 +141,14 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
Log.e(TAG, "Unable to add or update database history", e)
|
||||
}
|
||||
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
||||
val fileDatabaseInfo =
|
||||
FileDatabaseInfo(applicationContext,
|
||||
fileDatabaseHistory.databaseUri)
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistory.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
UriUtilDatabase.decode(fileDatabaseHistory.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
@@ -171,19 +162,20 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile,
|
||||
databaseFileDeletedResult: (DatabaseFile?) -> Unit) {
|
||||
fun deleteDatabaseFile(databaseFileToDelete: com.kunzisoft.keepass.model.DatabaseFile,
|
||||
databaseFileDeletedResult: (com.kunzisoft.keepass.model.DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())?.let { fileDatabaseHistory ->
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
?.let { fileDatabaseHistory ->
|
||||
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||
if (returnValue > 0) {
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtilDatabase.parse(fileDatabaseHistory.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
UriUtilDatabase.decode(fileDatabaseHistory.databaseUri),
|
||||
databaseFileToDelete.databaseAlias
|
||||
)
|
||||
} else {
|
||||
@@ -232,7 +224,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
).execute()
|
||||
}
|
||||
|
||||
companion object : SingletonHolderParameter<FileDatabaseHistoryAction, Context>(::FileDatabaseHistoryAction) {
|
||||
companion object : com.kunzisoft.keepass.utils.SingletonHolderParameter<FileDatabaseHistoryAction, Context>(::FileDatabaseHistoryAction) {
|
||||
private val TAG = FileDatabaseHistoryAction::class.java.name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.os.CancellationSignal
|
||||
import android.service.autofill.*
|
||||
import android.util.Log
|
||||
import android.view.autofill.AutofillId
|
||||
import android.view.inputmethod.InlineSuggestionsRequest
|
||||
import android.widget.RemoteViews
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.autofill.inline.UiVersions
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
@@ -54,7 +53,7 @@ open class AssignMainCredentialInDatabaseRunnable (
|
||||
super.onFinishRun()
|
||||
|
||||
// Erase the biometric
|
||||
CipherDatabaseAction.getInstance(context)
|
||||
com.kunzisoft.keepass.app.database.CipherDatabaseAction.getInstance(context)
|
||||
.deleteByDatabaseUri(mDatabaseUri)
|
||||
// Erase the register keyfile
|
||||
FileDatabaseHistoryAction.getInstance(context)
|
||||
|
||||
@@ -1,33 +1,18 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.Service
|
||||
import android.content.*
|
||||
import android.content.Context.*
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kunzisoft.keepass.R
|
||||
@@ -87,8 +72,9 @@ import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS
|
||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import com.kunzisoft.keepass.viewmodels.ChallengeResponseViewModel
|
||||
import java.util.ArrayList
|
||||
import java.util.UUID
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Utility class to connect an activity or a service to the DatabaseTaskNotificationService,
|
||||
@@ -103,7 +89,8 @@ class DatabaseTaskProvider {
|
||||
|
||||
var onActionFinish: ((database: Database,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result) -> Unit)? = null
|
||||
result: ActionRunnable.Result
|
||||
) -> Unit)? = null
|
||||
|
||||
private var intentDatabaseTask: Intent
|
||||
|
||||
@@ -177,7 +164,8 @@ class DatabaseTaskProvider {
|
||||
|
||||
private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener {
|
||||
override fun onStartAction(database: Database,
|
||||
progressMessage: ProgressMessage) {
|
||||
progressMessage: ProgressMessage
|
||||
) {
|
||||
startDialog(progressMessage)
|
||||
}
|
||||
|
||||
@@ -188,7 +176,8 @@ class DatabaseTaskProvider {
|
||||
|
||||
override fun onStopAction(database: Database,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result) {
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
onActionFinish?.invoke(database, actionTask, result)
|
||||
// Remove the progress task
|
||||
stopDialog()
|
||||
@@ -310,7 +299,7 @@ class DatabaseTaskProvider {
|
||||
private fun bindService() {
|
||||
initServiceConnection()
|
||||
serviceConnection?.let {
|
||||
context.bindService(intentDatabaseTask, it, BIND_AUTO_CREATE or BIND_IMPORTANT or BIND_ABOVE_CLIENT)
|
||||
context.bindService(intentDatabaseTask, it, Context.BIND_AUTO_CREATE or Context.BIND_IMPORTANT or Context.BIND_ABOVE_CLIENT)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,20 +21,19 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseInputException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
|
||||
class LoadDatabaseRunnable(private val context: Context,
|
||||
class LoadDatabaseRunnable(
|
||||
private val context: Context,
|
||||
private val mDatabase: Database,
|
||||
private val mDatabaseUri: Uri,
|
||||
private val mMainCredential: MainCredential,
|
||||
@@ -43,8 +42,8 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
private val mCipherEncryptDatabase: CipherEncryptDatabase?,
|
||||
private val mFixDuplicateUUID: Boolean,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: ActionRunnable() {
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?,
|
||||
) : ActionRunnable() {
|
||||
|
||||
override fun onStartRun() {
|
||||
// Clear before we load
|
||||
@@ -59,15 +58,14 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
mMainCredential,
|
||||
mChallengeResponseRetriever,
|
||||
mReadonly,
|
||||
UriUtil.getBinaryDir(context),
|
||||
com.kunzisoft.keepass.utils.UriUtilDatabase.getBinaryDir(context),
|
||||
{ memoryWanted ->
|
||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||
},
|
||||
mFixDuplicateUUID,
|
||||
progressTaskUpdater
|
||||
)
|
||||
}
|
||||
catch (e: DatabaseInputException) {
|
||||
} catch (e: DatabaseInputException) {
|
||||
setError(e)
|
||||
}
|
||||
|
||||
@@ -84,7 +82,7 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
|
||||
// Register the biometric
|
||||
mCipherEncryptDatabase?.let { cipherDatabase ->
|
||||
CipherDatabaseAction.getInstance(context)
|
||||
com.kunzisoft.keepass.app.database.CipherDatabaseAction.getInstance(context)
|
||||
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class HardwareKeyResponseHelper {
|
||||
@@ -134,7 +133,7 @@ class HardwareKeyResponseHelper {
|
||||
activity.getString(R.string.error_driver_required, hardwareKey.toString())
|
||||
)
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
UriUtil.openExternalApp(activity, activity.getString(R.string.key_driver_app_id))
|
||||
com.kunzisoft.keepass.utils.UriUtil.openExternalApp(activity, activity.getString(R.string.key_driver_app_id))
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
builder.create().show()
|
||||
|
||||
@@ -1,36 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.icons
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import java.util.*
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* Utility class to built and select an IconPack dynamically by libraries importation
|
||||
*
|
||||
* @author J-Jamet
|
||||
*/
|
||||
object IconPackChooser {
|
||||
object IconPackChooser : InterfaceIconPackChooser {
|
||||
|
||||
private val TAG = IconPackChooser::class.java.name
|
||||
|
||||
@@ -50,7 +31,7 @@ object IconPackChooser {
|
||||
* @param context Context to construct each pack with the resources
|
||||
* @return An unique instance of [IconPackChooser], recall [.build] provide the same instance
|
||||
*/
|
||||
fun build(context: Context) {
|
||||
override fun build(context: Context) {
|
||||
synchronized(IconPackChooser::class.java) {
|
||||
if (!isIconPackChooserBuilt) {
|
||||
isIconPackChooserBuilt = true
|
||||
@@ -69,7 +50,7 @@ object IconPackChooser {
|
||||
/**
|
||||
* Construct dynamically the icon pack provide by the default string resource "resource_id"
|
||||
*/
|
||||
private fun addDefaultIconPack(context: Context) {
|
||||
override fun addDefaultIconPack(context: Context) {
|
||||
val resourceId = context.resources.getIdentifier("resource_id", "string", context.packageName)
|
||||
iconPackList.add(IconPack(context.packageName, context.resources, resourceId))
|
||||
}
|
||||
@@ -77,9 +58,11 @@ object IconPackChooser {
|
||||
/**
|
||||
* Utility method to add new icon pack or catch exception if not retrieve
|
||||
*/
|
||||
private fun addOrCatchNewIconPack(context: Context, iconPackString: String) {
|
||||
override fun addOrCatchNewIconPack(context: Context, iconPackString: String) {
|
||||
try {
|
||||
iconPackList.add(IconPack(context.packageName, context.resources, context.resources.getIdentifier(
|
||||
iconPackList.add(IconPack(context.packageName,
|
||||
context.resources,
|
||||
context.resources.getIdentifier(
|
||||
iconPackString + "_resource_id",
|
||||
"string",
|
||||
context.packageName)))
|
||||
@@ -89,7 +72,7 @@ object IconPackChooser {
|
||||
|
||||
}
|
||||
|
||||
fun setSelectedIconPack(iconPackIdString: String?) {
|
||||
override fun setSelectedIconPack(iconPackIdString: String?) {
|
||||
for (iconPack in iconPackList) {
|
||||
if (iconPack.id == iconPackIdString) {
|
||||
iconPackSelected = iconPack
|
||||
@@ -104,10 +87,10 @@ object IconPackChooser {
|
||||
* @param context Context to build the icon pack if not already build
|
||||
* @return IconPack currently in usage
|
||||
*/
|
||||
fun getSelectedIconPack(context: Context): IconPack? {
|
||||
override fun getSelectedIconPack(context: Context): IconPack? {
|
||||
build(context)
|
||||
if (iconPackSelected == null) {
|
||||
setSelectedIconPack(PreferencesUtil.getIconPackSelectedId(context))
|
||||
setSelectedIconPack(DatabasePreferencesUtil.getIconPackSelectedId(context))
|
||||
}
|
||||
return iconPackSelected
|
||||
}
|
||||
@@ -118,7 +101,7 @@ object IconPackChooser {
|
||||
* @param context Context to build the icon pack if not already build
|
||||
* @return IconPack available
|
||||
*/
|
||||
fun getIconPackList(context: Context): List<IconPack> {
|
||||
override fun getIconPackList(context: Context): List<IconPack> {
|
||||
build(context)
|
||||
return iconPackList
|
||||
}
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/*
|
||||
* Copyright 2021 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.model
|
||||
|
||||
import android.content.Context
|
||||
@@ -24,9 +5,8 @@ import android.net.Uri
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.text.format.Formatter
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Utility data class to get FileDatabaseInfo at a `t` time
|
||||
@@ -90,7 +70,7 @@ data class SnapFileDatabaseInfo(var fileUri: Uri?,
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
|
||||
fun fromFileDatabaseInfo(fileDatabaseInfo: FileDatabaseInfo): SnapFileDatabaseInfo {
|
||||
fun fromFileDatabaseInfo(fileDatabaseInfo: com.kunzisoft.keepass.viewmodels.FileDatabaseInfo): SnapFileDatabaseInfo {
|
||||
return SnapFileDatabaseInfo(
|
||||
fileDatabaseInfo.fileUri,
|
||||
fileDatabaseInfo.exists,
|
||||
|
||||
@@ -2,15 +2,16 @@ package com.kunzisoft.keepass.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.*
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
|
||||
class AdvancedUnlockNotificationService : NotificationService() {
|
||||
|
||||
@@ -44,7 +45,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
||||
}
|
||||
|
||||
override fun retrieveChannelName(): String {
|
||||
return getString(R.string.advanced_unlock)
|
||||
return getString(com.kunzisoft.keepass.R.string.advanced_unlock)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
@@ -69,12 +70,12 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
||||
val biometricUnlockEnabled = PreferencesUtil.isBiometricUnlockEnable(this)
|
||||
val notificationBuilder = buildNewNotification().apply {
|
||||
setSmallIcon(if (biometricUnlockEnabled) {
|
||||
R.drawable.notification_ic_fingerprint_unlock_24dp
|
||||
com.kunzisoft.keepass.R.drawable.notification_ic_fingerprint_unlock_24dp
|
||||
} else {
|
||||
R.drawable.notification_ic_device_unlock_24dp
|
||||
com.kunzisoft.keepass.R.drawable.notification_ic_device_unlock_24dp
|
||||
})
|
||||
setContentTitle(getString(R.string.advanced_unlock))
|
||||
setContentText(getString(R.string.advanced_unlock_tap_delete))
|
||||
setContentTitle(getString(com.kunzisoft.keepass.R.string.advanced_unlock))
|
||||
setContentText(getString(com.kunzisoft.keepass.R.string.advanced_unlock_tap_delete))
|
||||
setContentIntent(pendingDeleteIntent)
|
||||
// Unfortunately swipe is disabled in lollipop+
|
||||
setDeleteIntent(pendingDeleteIntent)
|
||||
@@ -82,7 +83,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
||||
|
||||
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
||||
// Not necessarily a foreground service
|
||||
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
||||
if (mTimerJob == null && notificationTimeoutMilliSecs != com.kunzisoft.keepass.timeout.TimeoutHelper.NEVER) {
|
||||
defineTimerJob(notificationBuilder, notificationTimeoutMilliSecs) {
|
||||
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.model.ProgressMessage
|
||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||
@@ -55,9 +56,9 @@ import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.LOCK_ACTION
|
||||
import com.kunzisoft.keepass.utils.closeDatabase
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
import java.util.UUID
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import java.util.*
|
||||
|
||||
open class DatabaseTaskNotificationService : LockNotificationService(), ProgressTaskUpdater {
|
||||
|
||||
@@ -75,6 +76,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
private var mDatabaseInfoListeners = mutableListOf<DatabaseInfoListener>()
|
||||
private var mActionTaskBinder = ActionTaskBinder()
|
||||
private var mActionTaskListeners = mutableListOf<ActionTaskListener>()
|
||||
|
||||
// Channel to connect asynchronously a listener or a response
|
||||
private var mRequestChallengeListenerChannel: Channel<RequestChallengeListener>? = null
|
||||
private var mResponseChallengeChannel: Channel<ByteArray?>? = null
|
||||
@@ -154,18 +156,28 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
|
||||
interface DatabaseInfoListener {
|
||||
fun onDatabaseInfoChanged(previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||
newDatabaseInfo: SnapFileDatabaseInfo)
|
||||
fun onDatabaseInfoChanged(
|
||||
previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||
newDatabaseInfo: SnapFileDatabaseInfo,
|
||||
)
|
||||
}
|
||||
|
||||
interface ActionTaskListener {
|
||||
fun onStartAction(database: Database,
|
||||
progressMessage: ProgressMessage)
|
||||
fun onUpdateAction(database: Database,
|
||||
progressMessage: ProgressMessage)
|
||||
fun onStopAction(database: Database,
|
||||
fun onStartAction(
|
||||
database: Database,
|
||||
progressMessage: ProgressMessage,
|
||||
)
|
||||
|
||||
fun onUpdateAction(
|
||||
database: Database,
|
||||
progressMessage: ProgressMessage,
|
||||
)
|
||||
|
||||
fun onStopAction(
|
||||
database: Database,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result)
|
||||
result: ActionRunnable.Result,
|
||||
)
|
||||
}
|
||||
|
||||
interface RequestChallengeListener {
|
||||
@@ -208,7 +220,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
// Call listener to indicate a change in database info
|
||||
if (!mSaveState && previousDatabaseInfo != null) {
|
||||
mDatabaseInfoListeners.forEach { listener ->
|
||||
listener.onDatabaseInfoChanged(previousDatabaseInfo, lastFileDatabaseInfo)
|
||||
listener.onDatabaseInfoChanged(previousDatabaseInfo,
|
||||
lastFileDatabaseInfo)
|
||||
}
|
||||
}
|
||||
mSnapFileDatabaseInfo = lastFileDatabaseInfo
|
||||
@@ -294,7 +307,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
val database = Database.getInstance()
|
||||
val database = Database.getInstance(IconPackChooser)
|
||||
if (mDatabase != database) {
|
||||
mDatabase = database
|
||||
mDatabaseListeners.forEach { listener ->
|
||||
@@ -328,18 +341,31 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent, database)
|
||||
ACTION_DATABASE_MERGE_TASK -> buildDatabaseMergeActionTask(intent, database)
|
||||
ACTION_DATABASE_RELOAD_TASK -> buildDatabaseReloadActionTask(database)
|
||||
ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent, database)
|
||||
ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent, database)
|
||||
ACTION_DATABASE_UPDATE_GROUP_TASK -> buildDatabaseUpdateGroupActionTask(intent, database)
|
||||
ACTION_DATABASE_CREATE_ENTRY_TASK -> buildDatabaseCreateEntryActionTask(intent, database)
|
||||
ACTION_DATABASE_UPDATE_ENTRY_TASK -> buildDatabaseUpdateEntryActionTask(intent, database)
|
||||
ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_UPDATE_GROUP_TASK -> buildDatabaseUpdateGroupActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_CREATE_ENTRY_TASK -> buildDatabaseCreateEntryActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_UPDATE_ENTRY_TASK -> buildDatabaseUpdateEntryActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent, database)
|
||||
ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent, database)
|
||||
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent, database)
|
||||
ACTION_DATABASE_RESTORE_ENTRY_HISTORY -> buildDatabaseRestoreEntryHistoryActionTask(intent, database)
|
||||
ACTION_DATABASE_DELETE_ENTRY_HISTORY -> buildDatabaseDeleteEntryHistoryActionTask(intent, database)
|
||||
ACTION_DATABASE_UPDATE_COMPRESSION_TASK -> buildDatabaseUpdateCompressionActionTask(intent, database)
|
||||
ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK -> buildDatabaseRemoveUnlinkedDataActionTask(intent, database)
|
||||
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_RESTORE_ENTRY_HISTORY -> buildDatabaseRestoreEntryHistoryActionTask(
|
||||
intent,
|
||||
database)
|
||||
ACTION_DATABASE_DELETE_ENTRY_HISTORY -> buildDatabaseDeleteEntryHistoryActionTask(intent,
|
||||
database)
|
||||
ACTION_DATABASE_UPDATE_COMPRESSION_TASK -> buildDatabaseUpdateCompressionActionTask(
|
||||
intent,
|
||||
database)
|
||||
ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK -> buildDatabaseRemoveUnlinkedDataActionTask(
|
||||
intent,
|
||||
database)
|
||||
ACTION_DATABASE_UPDATE_NAME_TASK,
|
||||
ACTION_DATABASE_UPDATE_DESCRIPTION_TASK,
|
||||
ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK,
|
||||
@@ -352,7 +378,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK,
|
||||
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
||||
ACTION_DATABASE_UPDATE_PARALLELISM_TASK,
|
||||
ACTION_DATABASE_UPDATE_ITERATIONS_TASK -> buildDatabaseUpdateElementActionTask(intent, database)
|
||||
ACTION_DATABASE_UPDATE_ITERATIONS_TASK,
|
||||
-> buildDatabaseUpdateElementActionTask(intent, database)
|
||||
ACTION_DATABASE_SAVE -> buildDatabaseSave(intent, database)
|
||||
else -> null
|
||||
}
|
||||
@@ -393,7 +420,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
when (intentAction) {
|
||||
ACTION_DATABASE_LOAD_TASK,
|
||||
ACTION_DATABASE_MERGE_TASK,
|
||||
ACTION_DATABASE_RELOAD_TASK -> {
|
||||
ACTION_DATABASE_RELOAD_TASK,
|
||||
-> {
|
||||
saveDatabaseInfo()
|
||||
}
|
||||
}
|
||||
@@ -403,7 +431,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
// Save the database info after performing save action
|
||||
if (save) {
|
||||
database.fileUri?.let {
|
||||
val newSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
||||
val newSnapFileDatabaseInfo =
|
||||
SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
||||
FileDatabaseInfo(applicationContext, it))
|
||||
mLastLocalSaveTime = System.currentTimeMillis()
|
||||
mSnapFileDatabaseInfo = newSnapFileDatabaseInfo
|
||||
@@ -442,7 +471,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
ACTION_DATABASE_LOAD_TASK,
|
||||
ACTION_DATABASE_MERGE_TASK,
|
||||
ACTION_DATABASE_RELOAD_TASK,
|
||||
null -> {
|
||||
null,
|
||||
-> {
|
||||
START_STICKY
|
||||
}
|
||||
else -> {
|
||||
@@ -470,9 +500,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
||||
ACTION_DATABASE_LOAD_TASK,
|
||||
ACTION_DATABASE_MERGE_TASK,
|
||||
ACTION_DATABASE_RELOAD_TASK -> R.string.loading_database
|
||||
ACTION_DATABASE_RELOAD_TASK,
|
||||
-> R.string.loading_database
|
||||
ACTION_DATABASE_ASSIGN_PASSWORD_TASK,
|
||||
ACTION_DATABASE_SAVE -> R.string.saving_database
|
||||
ACTION_DATABASE_SAVE,
|
||||
-> R.string.saving_database
|
||||
else -> {
|
||||
if (mSaveState)
|
||||
R.string.saving_database
|
||||
@@ -583,10 +615,12 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
/**
|
||||
* Execute action with a coroutine
|
||||
*/
|
||||
private suspend fun executeAction(progressTaskUpdater: ProgressTaskUpdater,
|
||||
private suspend fun executeAction(
|
||||
progressTaskUpdater: ProgressTaskUpdater,
|
||||
onPreExecute: () -> Unit,
|
||||
onExecute: (ProgressTaskUpdater?) -> ActionRunnable?,
|
||||
onPostExecute: (result: ActionRunnable.Result) -> Unit) {
|
||||
onPostExecute: (result: ActionRunnable.Result) -> Unit,
|
||||
) {
|
||||
onPreExecute.invoke()
|
||||
withContext(Dispatchers.IO) {
|
||||
onExecute.invoke(progressTaskUpdater)?.apply {
|
||||
@@ -634,8 +668,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
super.onTaskRemoved(rootIntent)
|
||||
}
|
||||
|
||||
private fun retrieveResponseFromChallenge(hardwareKey: HardwareKey,
|
||||
seed: ByteArray?): ByteArray {
|
||||
private fun retrieveResponseFromChallenge(
|
||||
hardwareKey: HardwareKey,
|
||||
seed: ByteArray?,
|
||||
): ByteArray {
|
||||
// Request a challenge - response
|
||||
var response: ByteArray
|
||||
runBlocking {
|
||||
@@ -673,7 +709,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
||||
) {
|
||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
|
||||
val mainCredential: MainCredential = intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential()
|
||||
val mainCredential: MainCredential =
|
||||
intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential()
|
||||
|
||||
if (databaseUri == null)
|
||||
return null
|
||||
@@ -708,9 +745,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
|
||||
) {
|
||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
|
||||
val mainCredential: MainCredential = intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential()
|
||||
val mainCredential: MainCredential =
|
||||
intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential()
|
||||
val readOnly: Boolean = intent.getBooleanExtra(READ_ONLY_KEY, true)
|
||||
val cipherEncryptDatabase: CipherEncryptDatabase? = intent.getParcelableExtra(CIPHER_DATABASE_KEY)
|
||||
val cipherEncryptDatabase: CipherEncryptDatabase? =
|
||||
intent.getParcelableExtra(CIPHER_DATABASE_KEY)
|
||||
|
||||
if (databaseUri == null)
|
||||
return null
|
||||
@@ -777,7 +816,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseAssignPasswordActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseAssignPasswordActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(DATABASE_URI_KEY)
|
||||
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
||||
) {
|
||||
@@ -795,8 +837,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
|
||||
private inner class AfterActionNodesRunnable : AfterActionNodesFinish() {
|
||||
override fun onActionNodesFinish(result: ActionRunnable.Result,
|
||||
actionNodesValues: ActionNodesValues) {
|
||||
override fun onActionNodesFinish(
|
||||
result: ActionRunnable.Result,
|
||||
actionNodesValues: ActionNodesValues,
|
||||
) {
|
||||
val bundle = result.data ?: Bundle()
|
||||
bundle.putBundle(OLD_NODES_KEY, getBundleFromListNodes(actionNodesValues.oldNodes))
|
||||
bundle.putBundle(NEW_NODES_KEY, getBundleFromListNodes(actionNodesValues.newNodes))
|
||||
@@ -804,7 +848,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseCreateGroupActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseCreateGroupActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(GROUP_KEY)
|
||||
&& intent.hasExtra(PARENT_ID_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -813,7 +860,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
||||
|
||||
if (parentId == null
|
||||
|| newGroup == null)
|
||||
|| newGroup == null
|
||||
)
|
||||
return null
|
||||
|
||||
database.getGroupById(parentId)?.let { parent ->
|
||||
@@ -832,7 +880,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseUpdateGroupActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseUpdateGroupActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(GROUP_ID_KEY)
|
||||
&& intent.hasExtra(GROUP_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -841,7 +892,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
||||
|
||||
if (groupId == null
|
||||
|| newGroup == null)
|
||||
|| newGroup == null
|
||||
)
|
||||
return null
|
||||
|
||||
database.getGroupById(groupId)?.let { oldGroup ->
|
||||
@@ -860,7 +912,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseCreateEntryActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseCreateEntryActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(ENTRY_KEY)
|
||||
&& intent.hasExtra(PARENT_ID_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -869,7 +924,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
||||
|
||||
if (parentId == null
|
||||
|| newEntry == null)
|
||||
|| newEntry == null
|
||||
)
|
||||
return null
|
||||
|
||||
database.getGroupById(parentId)?.let { parent ->
|
||||
@@ -888,7 +944,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseUpdateEntryActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseUpdateEntryActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||
&& intent.hasExtra(ENTRY_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -897,7 +956,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
||||
|
||||
if (entryId == null
|
||||
|| newEntry == null)
|
||||
|| newEntry == null
|
||||
)
|
||||
return null
|
||||
|
||||
database.getEntryById(entryId)?.let { oldEntry ->
|
||||
@@ -916,7 +976,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseCopyNodesActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseCopyNodesActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||
&& intent.hasExtra(PARENT_ID_KEY)
|
||||
@@ -940,7 +1003,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseMoveNodesActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseMoveNodesActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||
&& intent.hasExtra(PARENT_ID_KEY)
|
||||
@@ -964,7 +1030,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseDeleteNodesActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseDeleteNodesActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -982,7 +1051,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseRestoreEntryHistoryActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseRestoreEntryHistoryActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -1004,7 +1076,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseDeleteEntryHistoryActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseDeleteEntryHistoryActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
@@ -1026,16 +1101,21 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseUpdateCompressionActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseUpdateCompressionActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(OLD_ELEMENT_KEY)
|
||||
&& intent.hasExtra(NEW_ELEMENT_KEY)
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||
) {
|
||||
|
||||
val oldElement: CompressionAlgorithm? = intent.getParcelableExtra(OLD_ELEMENT_KEY)
|
||||
val newElement: CompressionAlgorithm? = intent.getParcelableExtra(NEW_ELEMENT_KEY)
|
||||
|
||||
if (oldElement == null
|
||||
|| newElement == null)
|
||||
|| newElement == null
|
||||
)
|
||||
return null
|
||||
|
||||
return UpdateCompressionBinariesDatabaseRunnable(this,
|
||||
@@ -1055,7 +1135,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseRemoveUnlinkedDataActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseRemoveUnlinkedDataActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||
|
||||
return RemoveUnlinkedDataDatabaseRunnable(this,
|
||||
@@ -1073,7 +1156,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabaseUpdateElementActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||
private fun buildDatabaseUpdateElementActionTask(
|
||||
intent: Intent,
|
||||
database: Database,
|
||||
): ActionRunnable? {
|
||||
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||
return SaveDatabaseRunnable(this,
|
||||
database,
|
||||
@@ -1120,7 +1206,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
|
||||
private val TAG = DatabaseTaskNotificationService::class.java.name
|
||||
|
||||
private const val CHANNEL_DATABASE_ID = "com.kunzisoft.keepass.notification.channel.database"
|
||||
private const val CHANNEL_DATABASE_ID =
|
||||
"com.kunzisoft.keepass.notification.channel.database"
|
||||
|
||||
const val ACTION_DATABASE_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK"
|
||||
const val ACTION_DATABASE_LOAD_TASK = "ACTION_DATABASE_LOAD_TASK"
|
||||
@@ -1137,19 +1224,30 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
const val ACTION_DATABASE_RESTORE_ENTRY_HISTORY = "ACTION_DATABASE_RESTORE_ENTRY_HISTORY"
|
||||
const val ACTION_DATABASE_DELETE_ENTRY_HISTORY = "ACTION_DATABASE_DELETE_ENTRY_HISTORY"
|
||||
const val ACTION_DATABASE_UPDATE_NAME_TASK = "ACTION_DATABASE_UPDATE_NAME_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_DESCRIPTION_TASK = "ACTION_DATABASE_UPDATE_DESCRIPTION_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK = "ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_DESCRIPTION_TASK =
|
||||
"ACTION_DATABASE_UPDATE_DESCRIPTION_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK =
|
||||
"ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_COLOR_TASK = "ACTION_DATABASE_UPDATE_COLOR_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_COMPRESSION_TASK = "ACTION_DATABASE_UPDATE_COMPRESSION_TASK"
|
||||
const val ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK = "ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK = "ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK = "ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_COMPRESSION_TASK =
|
||||
"ACTION_DATABASE_UPDATE_COMPRESSION_TASK"
|
||||
const val ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK =
|
||||
"ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK =
|
||||
"ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK =
|
||||
"ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK =
|
||||
"ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK =
|
||||
"ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_ENCRYPTION_TASK = "ACTION_DATABASE_UPDATE_ENCRYPTION_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK = "ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK = "ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_PARALLELISM_TASK = "ACTION_DATABASE_UPDATE_PARALLELISM_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK =
|
||||
"ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK =
|
||||
"ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_PARALLELISM_TASK =
|
||||
"ACTION_DATABASE_UPDATE_PARALLELISM_TASK"
|
||||
const val ACTION_DATABASE_UPDATE_ITERATIONS_TASK = "ACTION_DATABASE_UPDATE_ITERATIONS_TASK"
|
||||
const val ACTION_DATABASE_SAVE = "ACTION_DATABASE_SAVE"
|
||||
|
||||
@@ -1173,8 +1271,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
const val SAVE_DATABASE_KEY = "SAVE_DATABASE_KEY"
|
||||
const val OLD_NODES_KEY = "OLD_NODES_KEY"
|
||||
const val NEW_NODES_KEY = "NEW_NODES_KEY"
|
||||
const val OLD_ELEMENT_KEY = "OLD_ELEMENT_KEY" // Warning type of this thing change every time
|
||||
const val NEW_ELEMENT_KEY = "NEW_ELEMENT_KEY" // Warning type of this thing change every time
|
||||
const val OLD_ELEMENT_KEY =
|
||||
"OLD_ELEMENT_KEY" // Warning type of this thing change every time
|
||||
const val NEW_ELEMENT_KEY =
|
||||
"NEW_ELEMENT_KEY" // Warning type of this thing change every time
|
||||
|
||||
fun getListNodesFromBundle(database: Database, bundle: Bundle): List<Node> {
|
||||
val nodesAction = ArrayList<Node>()
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.settings
|
||||
|
||||
import android.app.backup.BackupManager
|
||||
@@ -26,18 +7,18 @@ import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.stylish.Stylish
|
||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
|
||||
import com.kunzisoft.keepass.database.element.SortNodeEnum
|
||||
import com.kunzisoft.keepass.database.search.SearchParameters
|
||||
import com.kunzisoft.keepass.education.Education
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
import com.kunzisoft.keepass.password.PassphraseGenerator
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import java.util.*
|
||||
import java.util.HashSet
|
||||
import java.util.Properties
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.APP_TIMEOUT_KEY
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.HIDE_EXPIRED_ENTRIES_KEY
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.SETTING_ICON_PACK_CHOOSE_KEY
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.SUBDOMAIN_SEARCH_KEY
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.TIMEOUT_BACKUP_KEY
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.TIMEOUT_DEFAULT
|
||||
|
||||
object PreferencesUtil {
|
||||
|
||||
@@ -61,7 +42,8 @@ object PreferencesUtil {
|
||||
|
||||
fun saveNodeSort(context: Context,
|
||||
sortNodeEnum: SortNodeEnum,
|
||||
sortNodeParameters: SortNodeEnum.SortNodeParameters) {
|
||||
sortNodeParameters: SortNodeEnum.SortNodeParameters
|
||||
) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
prefs?.edit()?.apply {
|
||||
putString(context.getString(R.string.sort_node_key), sortNodeEnum.name)
|
||||
@@ -108,12 +90,6 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.auto_focus_search_default))
|
||||
}
|
||||
|
||||
fun searchSubdomains(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.subdomain_search_key),
|
||||
context.resources.getBoolean(R.bool.subdomain_search_default))
|
||||
}
|
||||
|
||||
fun showEntryColors(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.show_entry_colors_key),
|
||||
@@ -156,35 +132,35 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.show_uuid_default))
|
||||
}
|
||||
|
||||
fun showExpiredEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return ! prefs.getBoolean(context.getString(R.string.hide_expired_entries_key),
|
||||
context.resources.getBoolean(R.bool.hide_expired_entries_default))
|
||||
}
|
||||
|
||||
fun getStyle(context: Context): String {
|
||||
val defaultStyleString = Stylish.defaultStyle(context)
|
||||
val defaultStyleString =
|
||||
com.kunzisoft.keepass.activities.stylish.Stylish.defaultStyle(context)
|
||||
val styleString = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.setting_style_key), defaultStyleString)
|
||||
?: defaultStyleString
|
||||
// Return the system style
|
||||
return Stylish.retrieveEquivalentSystemStyle(context, styleString)
|
||||
return com.kunzisoft.keepass.activities.stylish.Stylish.retrieveEquivalentSystemStyle(
|
||||
context,
|
||||
styleString)
|
||||
}
|
||||
|
||||
fun setStyle(context: Context, styleString: String) {
|
||||
var tempThemeString = styleString
|
||||
if (!UriUtil.contributingUser(context)) {
|
||||
if (tempThemeString in BuildConfig.STYLES_DISABLED) {
|
||||
tempThemeString = Stylish.defaultStyle(context)
|
||||
if (!com.kunzisoft.keepass.utils.UriUtil.contributingUser(context)) {
|
||||
if (tempThemeString in com.kunzisoft.keepass.BuildConfig.STYLES_DISABLED) {
|
||||
tempThemeString =
|
||||
com.kunzisoft.keepass.activities.stylish.Stylish.defaultStyle(context)
|
||||
}
|
||||
}
|
||||
// Store light style to show selection in array list
|
||||
tempThemeString = Stylish.retrieveEquivalentLightStyle(context, tempThemeString)
|
||||
tempThemeString =
|
||||
com.kunzisoft.keepass.activities.stylish.Stylish.retrieveEquivalentLightStyle(context,
|
||||
tempThemeString)
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.putString(context.getString(R.string.setting_style_key), tempThemeString)
|
||||
.apply()
|
||||
Stylish.load(context)
|
||||
com.kunzisoft.keepass.activities.stylish.Stylish.load(context)
|
||||
}
|
||||
|
||||
fun getStyleBrightness(context: Context): String? {
|
||||
@@ -292,16 +268,16 @@ object PreferencesUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun getDefaultPassphraseWordCase(context: Context): PassphraseGenerator.WordCase {
|
||||
fun getDefaultPassphraseWordCase(context: Context): com.kunzisoft.keepass.password.PassphraseGenerator.WordCase {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return PassphraseGenerator.WordCase
|
||||
.getByOrdinal(prefs.getInt(context
|
||||
return com.kunzisoft.keepass.password.PassphraseGenerator.WordCase.Companion.getByOrdinal(
|
||||
prefs.getInt(context
|
||||
.getString(R.string.passphrase_generator_word_case_key),
|
||||
0)
|
||||
)
|
||||
}
|
||||
|
||||
fun setDefaultPassphraseWordCase(context: Context, wordCase: PassphraseGenerator.WordCase) {
|
||||
fun setDefaultPassphraseWordCase(context: Context, wordCase: com.kunzisoft.keepass.password.PassphraseGenerator.WordCase) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
||||
putInt(
|
||||
context.getString(R.string.passphrase_generator_word_case_key),
|
||||
@@ -414,45 +390,23 @@ object PreferencesUtil {
|
||||
*/
|
||||
fun saveCurrentTime(context: Context) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
||||
putLong(context.getString(R.string.timeout_backup_key), System.currentTimeMillis())
|
||||
putLong(TIMEOUT_BACKUP_KEY, System.currentTimeMillis())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time previously saved in milliseconds (commonly used to compare with current time and check timeout)
|
||||
*/
|
||||
fun getTimeSaved(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getLong(context.getString(R.string.timeout_backup_key),
|
||||
TimeoutHelper.NEVER)
|
||||
}
|
||||
|
||||
/**
|
||||
* App timeout selected in milliseconds
|
||||
*/
|
||||
fun getAppTimeout(context: Context): Long {
|
||||
return try {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
(prefs.getString(context.getString(R.string.app_timeout_key),
|
||||
context.getString(R.string.timeout_default)) ?: "300000").toLong()
|
||||
} catch (e: NumberFormatException) {
|
||||
TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
}
|
||||
|
||||
fun getClipboardTimeout(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(context.getString(R.string.clipboard_timeout_key),
|
||||
context.getString(R.string.clipboard_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
TIMEOUT_DEFAULT)?.toLong()
|
||||
?: com.kunzisoft.keepass.timeout.TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
|
||||
fun getAdvancedUnlockTimeout(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(context.getString(R.string.temp_advanced_unlock_timeout_key),
|
||||
context.getString(R.string.temp_advanced_unlock_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
?: com.kunzisoft.keepass.timeout.TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
|
||||
fun isLockDatabaseWhenScreenShutOffEnable(context: Context): Boolean {
|
||||
@@ -500,7 +454,8 @@ object PreferencesUtil {
|
||||
return prefs.getBoolean(context.getString(R.string.biometric_unlock_enable_key),
|
||||
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
|
||||
&& (if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
AdvancedUnlockManager.biometricUnlockSupported(context)
|
||||
com.kunzisoft.keepass.biometric.AdvancedUnlockManager.Companion.biometricUnlockSupported(
|
||||
context)
|
||||
} else {
|
||||
false
|
||||
})
|
||||
@@ -593,13 +548,6 @@ object PreferencesUtil {
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun getIconPackSelectedId(context: Context): String? {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(
|
||||
context.getString(R.string.setting_icon_pack_choose_key),
|
||||
context.getString(R.string.setting_icon_pack_choose_default))
|
||||
}
|
||||
|
||||
fun emptyPasswordAllowed(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.allow_no_password_key),
|
||||
@@ -631,7 +579,9 @@ object PreferencesUtil {
|
||||
}
|
||||
|
||||
fun isKeyboardSaveSearchInfoEnable(context: Context): Boolean {
|
||||
if (!MagikeyboardService.activatedInSettings(context))
|
||||
if (!com.kunzisoft.keepass.magikeyboard.MagikeyboardService.Companion.activatedInSettings(
|
||||
context)
|
||||
)
|
||||
return false
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_save_search_info_key),
|
||||
@@ -716,7 +666,7 @@ object PreferencesUtil {
|
||||
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
|
||||
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
|
||||
?.toMutableSet()?.apply {
|
||||
add(BuildConfig.APPLICATION_ID)
|
||||
add(com.kunzisoft.keepass.BuildConfig.APPLICATION_ID)
|
||||
} ?: emptySet()
|
||||
}
|
||||
|
||||
@@ -754,10 +704,12 @@ object PreferencesUtil {
|
||||
|
||||
fun getAppProperties(context: Context): Properties {
|
||||
val properties = Properties()
|
||||
for ((name, value) in PreferenceManager.getDefaultSharedPreferences(context).all) {
|
||||
for ((name, value) in PreferenceManager.getDefaultSharedPreferences(
|
||||
context).all) {
|
||||
properties[name] = value.toString()
|
||||
}
|
||||
for ((name, value) in Education.getEducationSharedPreferences(context).all) {
|
||||
for ((name, value) in com.kunzisoft.keepass.education.Education.Companion.getEducationSharedPreferences(
|
||||
context).all) {
|
||||
properties[name] = value.toString()
|
||||
}
|
||||
return properties
|
||||
@@ -780,7 +732,9 @@ object PreferencesUtil {
|
||||
try {
|
||||
putProperty(this, name as String, value as String)
|
||||
} catch (e:Exception) {
|
||||
Log.e("PreferencesUtil", "Error when trying to parse app property $name=$value", e)
|
||||
Log.e("PreferencesUtil",
|
||||
"Error when trying to parse app property $name=$value",
|
||||
e)
|
||||
}
|
||||
}
|
||||
}.apply()
|
||||
@@ -796,8 +750,8 @@ object PreferencesUtil {
|
||||
context.getString(R.string.enable_auto_save_database_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.enable_keep_screen_on_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.auto_focus_search_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.subdomain_search_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.app_timeout_key) -> editor.putString(name, value.toLong().toString())
|
||||
SUBDOMAIN_SEARCH_KEY -> editor.putBoolean(name, value.toBoolean())
|
||||
APP_TIMEOUT_KEY -> editor.putString(name, value.toLong().toString())
|
||||
context.getString(R.string.lock_database_screen_off_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.lock_database_back_root_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.lock_database_show_button_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
@@ -839,7 +793,7 @@ object PreferencesUtil {
|
||||
|
||||
context.getString(R.string.setting_style_key) -> setStyle(context, value)
|
||||
context.getString(R.string.setting_style_brightness_key) -> editor.putString(name, value)
|
||||
context.getString(R.string.setting_icon_pack_choose_key) -> editor.putString(name, value)
|
||||
SETTING_ICON_PACK_CHOOSE_KEY -> editor.putString(name, value)
|
||||
context.getString(R.string.show_entry_colors_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.hide_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.colorize_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
@@ -849,7 +803,7 @@ object PreferencesUtil {
|
||||
context.getString(R.string.show_uuid_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.list_size_key) -> editor.putString(name, value)
|
||||
context.getString(R.string.monospace_font_fields_enable_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.hide_expired_entries_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
HIDE_EXPIRED_ENTRIES_KEY -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.enable_education_screens_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
|
||||
context.getString(R.string.password_generator_length_key) -> editor.putInt(name, value.toInt())
|
||||
@@ -869,8 +823,13 @@ object PreferencesUtil {
|
||||
}
|
||||
|
||||
putPropertiesInPreferences(properties,
|
||||
Education.getEducationSharedPreferences(context)) { editor, name, value ->
|
||||
Education.putPropertiesInEducationPreferences(context, editor, name, value)
|
||||
Education.getEducationSharedPreferences(
|
||||
context)) { editor, name, value ->
|
||||
Education.putPropertiesInEducationPreferences(
|
||||
context,
|
||||
editor,
|
||||
name,
|
||||
value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION"
|
||||
const val DATABASE_STOP_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_STOP_TASK_ACTION"
|
||||
|
||||
const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK"
|
||||
const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD"
|
||||
const val BACK_PREVIOUS_KEYBOARD_ACTION = "com.kunzisoft.keepass.BACK_PREVIOUS_KEYBOARD"
|
||||
|
||||
|
||||
@@ -18,12 +18,9 @@
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
open class SingletonHolderParameter<out T, in A>(private val constructor: (A) -> T) {
|
||||
|
||||
@Volatile
|
||||
private var instance: T? = null
|
||||
|
||||
fun getInstance(arg: A): T {
|
||||
return when {
|
||||
instance != null -> instance!!
|
||||
@@ -35,18 +32,3 @@ open class SingletonHolderParameter<out T, in A>(private val constructor: (A) ->
|
||||
}
|
||||
}
|
||||
|
||||
open class SingletonHolder<out T>(private val constructor: () -> T) {
|
||||
|
||||
@Volatile
|
||||
private var instance: T? = null
|
||||
|
||||
fun getInstance(): T {
|
||||
return when {
|
||||
instance != null -> instance!!
|
||||
else -> synchronized(this) {
|
||||
if (instance == null) instance = constructor()
|
||||
instance!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,16 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.viewmodels
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.text.format.Formatter
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import java.io.Serializable
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
class FileDatabaseInfo : Serializable {
|
||||
|
||||
private var context: Context
|
||||
private var documentFile: DocumentFile? = null
|
||||
private var documentFile: androidx.documentfile.provider.DocumentFile? = null
|
||||
var fileUri: Uri?
|
||||
private set
|
||||
|
||||
@@ -43,16 +22,16 @@ class FileDatabaseInfo : Serializable {
|
||||
|
||||
constructor(context: Context, filePath: String) {
|
||||
this.context = context
|
||||
this.fileUri = UriUtil.parse(filePath)
|
||||
this.fileUri = com.kunzisoft.keepass.utils.UriUtil.parse(filePath)
|
||||
init()
|
||||
}
|
||||
|
||||
fun init() {
|
||||
// Check permission
|
||||
fileUri?.let { uri ->
|
||||
UriUtil.takeUriPermission(context.contentResolver, uri)
|
||||
com.kunzisoft.keepass.utils.UriUtil.takeUriPermission(context.contentResolver, uri)
|
||||
}
|
||||
documentFile = UriUtil.getFileData(context, fileUri)
|
||||
documentFile = com.kunzisoft.keepass.utils.UriUtil.getFileData(context, fileUri)
|
||||
}
|
||||
|
||||
var exists: Boolean = false
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
<dimen name="card_view_margin_vertical">5dp</dimen>
|
||||
<dimen name="card_view_padding">14dp</dimen>
|
||||
<dimen name="item_file_info_height">148dp</dimen>
|
||||
<dimen name="icon_size">32dp</dimen>
|
||||
<dimen name="lock_button_size">48dp</dimen>
|
||||
<dimen name="hidden_lock_button_size">0dp</dimen>
|
||||
<dimen name="content_percent">1</dimen>
|
||||
|
||||
@@ -78,12 +78,10 @@
|
||||
<string name="content_description_remove_from_list">Remove</string>
|
||||
<string name="content_description_keyboard_close_fields">Close fields</string>
|
||||
<string name="select_to_copy">Select to copy %1$s to clipboard</string>
|
||||
<string name="retrieving_db_key">Retrieving database key…</string>
|
||||
<string name="waiting_challenge_request">Waiting for the challenge request…</string>
|
||||
<string name="waiting_challenge_response">Waiting for the challenge response…</string>
|
||||
<string name="database">Database</string>
|
||||
<string name="template_group_name">Templates</string>
|
||||
<string name="decrypting_db">Decrypting database content…</string>
|
||||
<string name="default_checkbox">Use as default database</string>
|
||||
<string name="digits">Digits</string>
|
||||
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is <strong>open source</strong> and <strong>without advertising</strong>.
|
||||
@@ -92,10 +90,8 @@
|
||||
<string name="html_about_contribution">In order to <strong>keep our freedom</strong>, <strong>fix bugs</strong>, <strong>add features</strong> and <strong>to be always active</strong>, we count on your <strong>contribution</strong>.</string>
|
||||
<string name="entry_accessed">Accessed</string>
|
||||
<string name="entry_cancel">Cancel</string>
|
||||
<string name="entry_notes">Notes</string>
|
||||
<string name="entry_confpassword">Confirm password</string>
|
||||
<string name="entry_created">Created</string>
|
||||
<string name="entry_expires">Expires</string>
|
||||
<string name="expired">Expired</string>
|
||||
<string name="entry_UUID">UUID</string>
|
||||
<string name="entry_history">History</string>
|
||||
@@ -108,11 +104,9 @@
|
||||
<string name="auto_type">Auto-Type</string>
|
||||
<string name="auto_type_sequence">Auto-Type sequence</string>
|
||||
<string name="entry_not_found">Could not find entry data.</string>
|
||||
<string name="entry_password">Password</string>
|
||||
<string name="tags">Tags</string>
|
||||
<string name="custom_data">Custom data</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="entry_title">Title</string>
|
||||
<string name="entry_setup_otp">Set up one-time password</string>
|
||||
<string name="otp_type">OTP type</string>
|
||||
<string name="otp_secret">Secret</string>
|
||||
@@ -124,38 +118,8 @@
|
||||
<string name="current_group">Current group</string>
|
||||
<string name="case_sensitive">Case sensitive</string>
|
||||
<string name="regex">Regular expression</string>
|
||||
<string name="debit_credit_card">Debit / Credit Card</string>
|
||||
<string name="holder">Holder</string>
|
||||
<string name="number">Number</string>
|
||||
<string name="card_verification_value">CVV</string>
|
||||
<string name="personal_identification_number">PIN</string>
|
||||
<string name="id_card">ID Card</string>
|
||||
<string name="name">Name</string>
|
||||
<string name="place_of_issue">Place of issue</string>
|
||||
<string name="date_of_issue">Date of issue</string>
|
||||
<string name="email">Email</string>
|
||||
<string name="email_address">Email address</string>
|
||||
<string name="wireless">Wi-Fi</string>
|
||||
<string name="ssid">SSID</string>
|
||||
<string name="type">Type</string>
|
||||
<string name="cryptocurrency">Cryptocurrency wallet</string>
|
||||
<string name="token">Token</string>
|
||||
<string name="public_key">Public key</string>
|
||||
<string name="private_key">Private key</string>
|
||||
<string name="seed">Seed</string>
|
||||
<string name="account">Account</string>
|
||||
<string name="bank">Bank</string>
|
||||
<string name="bank_name">Bank name</string>
|
||||
<string name="bank_identifier_code">SWIFT / BIC</string>
|
||||
<string name="international_bank_account_number">IBAN</string>
|
||||
<string name="secure_note">Secure Note</string>
|
||||
<string name="membership">Membership</string>
|
||||
<string name="standard">Standard</string>
|
||||
<string name="template">Template</string>
|
||||
<string name="version">Version</string>
|
||||
<string name="entry_otp">OTP</string>
|
||||
<string name="entry_url">URL</string>
|
||||
<string name="entry_user_name">Username</string>
|
||||
<string name="error_arc4">The Arcfour stream cipher is not supported.</string>
|
||||
<string name="error_can_not_handle_uri">Could not handle this URI in KeePassDX.</string>
|
||||
<string name="error_file_not_create">Could not create file</string>
|
||||
@@ -166,10 +130,6 @@
|
||||
<string name="error_word_reserved">This word is reserved and cannot be used.</string>
|
||||
<string name="error_nokeyfile">Select a keyfile.</string>
|
||||
<string name="error_no_hardware_key">Select a hardware key.</string>
|
||||
<string name="error_out_of_memory">No memory to load your entire database.</string>
|
||||
<string name="error_XML_malformed">XML malformed.</string>
|
||||
<string name="error_load_database">Could not load the database.</string>
|
||||
<string name="error_load_database_KDF_memory">Could not load the key. Try to lower the KDF \"Memory Usage\".</string>
|
||||
<string name="error_pass_gen_type">At least one password generation type must be selected.</string>
|
||||
<string name="error_disallow_no_credentials">At least one credential must be set.</string>
|
||||
<string name="error_pass_match">The passwords do not match.</string>
|
||||
@@ -178,13 +138,8 @@
|
||||
<string name="error_label_exists">This label already exists.</string>
|
||||
<string name="error_wrong_length">Enter a positive integer number in the \"Length\" field.</string>
|
||||
<string name="error_autofill_enable_service">Could not enable autofill service.</string>
|
||||
<string name="error_move_group_here">You cannot move a group here.</string>
|
||||
<string name="error_move_entry_here">You cannot move an entry here.</string>
|
||||
<string name="error_copy_entry_here">You cannot copy an entry here.</string>
|
||||
<string name="error_copy_group_here">You cannot copy a group here.</string>
|
||||
<string name="error_create_database">Unable to create database file.</string>
|
||||
<string name="error_create_database_file">Unable to create database with this password and keyfile.</string>
|
||||
<string name="error_save_database">Could not save the database.</string>
|
||||
<string name="error_otp_secret_key">Secret key must be in Base32 format.</string>
|
||||
<string name="error_otp_counter">Counter must be between %1$d and %2$d.</string>
|
||||
<string name="error_otp_period">Period must be between %1$d and %2$d seconds.</string>
|
||||
@@ -205,14 +160,8 @@
|
||||
<string name="error_no_response_from_challenge">Unable to get the response from the challenge.</string>
|
||||
<string name="error_cancel_by_user">Cancelled by user.</string>
|
||||
<string name="error_driver_required">Driver for %1$s is required.</string>
|
||||
<string name="error_unable_merge_database_kdb">Unable to merge from a database V1.</string>
|
||||
<string name="error_location_unknown">Database location is unknown, database action cannot be performed.</string>
|
||||
<string name="error_hardware_key_unsupported">Hardware key is not supported.</string>
|
||||
<string name="error_empty_key">"Key cannot be empty."</string>
|
||||
<string name="field_name">Field name</string>
|
||||
<string name="field_value">Field value</string>
|
||||
<string name="file_not_found_content">Could not find file. Try reopening it from your file browser.</string>
|
||||
<string name="corrupted_file">Corrupted file.</string>
|
||||
<string name="file_browser">File manager</string>
|
||||
<string name="generate_password">Generate password</string>
|
||||
<string name="hint_conf_pass">Confirm password</string>
|
||||
@@ -224,10 +173,6 @@
|
||||
<string name="hint_pass">Password</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="passphrase">Passphrase</string>
|
||||
<string name="invalid_credentials">Could not read credentials.</string>
|
||||
<string name="invalid_algorithm">Wrong algorithm.</string>
|
||||
<string name="invalid_db_same_uuid">%1$s with the same UUID %2$s already exists.</string>
|
||||
<string name="invalid_db_sig">Could not recognize the database format.</string>
|
||||
<string name="keyfile_is_empty">The keyfile is empty.</string>
|
||||
<string name="length">Length</string>
|
||||
<string name="hide_password_title">Hide passwords</string>
|
||||
@@ -349,7 +294,6 @@
|
||||
<string name="special">Special</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="underline">Underline</string>
|
||||
<string name="unsupported_db_version">Unsupported database version.</string>
|
||||
<string name="uppercase">Upper-case</string>
|
||||
<string name="warning">Warning</string>
|
||||
<string name="warning_password_encoding">Avoid password characters outside of text encoding format in database file (unrecognized chars are converted to the same letter).</string>
|
||||
@@ -487,10 +431,6 @@
|
||||
<string name="application_appearance">Interface</string>
|
||||
<string name="other">Other</string>
|
||||
<string name="compression">Compression</string>
|
||||
<string name="compression_none">None</string>
|
||||
<string name="compression_gzip">Gzip</string>
|
||||
<string name="recycle_bin">Recycle bin</string>
|
||||
<string name="templates">Templates</string>
|
||||
<string name="keyboard">Keyboard</string>
|
||||
<string name="magic_keyboard_title">Magikeyboard</string>
|
||||
<string name="magic_keyboard_explanation_summary">Activate a custom keyboard populating your passwords and all identity fields</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
@@ -16,6 +16,13 @@ android {
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
||||
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("room.incremental", "true")
|
||||
arg("room.schemaLocation", "$projectDir/schemas".toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -33,6 +40,8 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
def room_version = "2.4.3"
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.core:core-ktx:$android_core_version"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||
@@ -47,6 +56,10 @@ dependencies {
|
||||
implementation project(path: ':icon-pack-classic')
|
||||
implementation project(path: ':icon-pack-material')
|
||||
|
||||
// Database
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
||||
implementation project(path: ':crypto')
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
|
||||
@@ -61,7 +61,7 @@ class MergeDatabaseRunnable(private val context: Context,
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
DatabasePreferencesUtil.saveCurrentTime(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,20 +23,22 @@ import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtilDatabase
|
||||
|
||||
class ReloadDatabaseRunnable(private val context: Context,
|
||||
class ReloadDatabaseRunnable(
|
||||
private val context: Context,
|
||||
private val mDatabase: Database,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: ActionRunnable() {
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?,
|
||||
) : ActionRunnable() {
|
||||
|
||||
override fun onStartRun() {
|
||||
// Clear before we load
|
||||
mDatabase.clearIndexesAndBinaries(UriUtil.getBinaryDir(context))
|
||||
mDatabase.clearIndexesAndBinaries(UriUtilDatabase.getBinaryDir(
|
||||
context))
|
||||
mDatabase.wasReloaded = true
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@ class ReloadDatabaseRunnable(private val context: Context,
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
DatabasePreferencesUtil.saveCurrentTime(context)
|
||||
} else {
|
||||
mDatabase.clearAndClose(context)
|
||||
}
|
||||
@@ -56,13 +56,14 @@ import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.search.SearchParameters
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.icons.InterfaceIconPackChooser
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.*
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
|
||||
class Database {
|
||||
class Database(private val iconPackChooser: InterfaceIconPackChooser) {
|
||||
|
||||
// To keep a reference for specific methods provided by version
|
||||
private var mDatabaseKDB: DatabaseKDB? = null
|
||||
@@ -76,8 +77,9 @@ class Database {
|
||||
var isReadOnly = false
|
||||
|
||||
val iconDrawableFactory = IconDrawableFactory(
|
||||
{ binaryCache },
|
||||
{ iconId -> iconsManager.getBinaryForCustomIcon(iconId) }
|
||||
iconPackChooser = iconPackChooser,
|
||||
retrieveBinaryCache = { binaryCache },
|
||||
retrieveCustomIconBinary = { iconId -> iconsManager.getBinaryForCustomIcon(iconId) }
|
||||
)
|
||||
|
||||
var loaded = false
|
||||
@@ -646,7 +648,7 @@ class Database {
|
||||
}
|
||||
|
||||
// New database instance to get new changes
|
||||
val databaseToMerge = Database()
|
||||
val databaseToMerge = Database(iconPackChooser)
|
||||
databaseToMerge.fileUri = databaseToMergeUri ?: this.fileUri
|
||||
|
||||
try {
|
||||
@@ -785,7 +787,7 @@ class Database {
|
||||
openDatabaseKDBX: (InputStream) -> Unit) {
|
||||
try {
|
||||
// Load Data, pass Uris as InputStreams
|
||||
val databaseStream = UriUtil.getUriInputStream(contentResolver, databaseUri)
|
||||
val databaseStream = UriUtilDatabase.getUriInputStream(contentResolver, databaseUri)
|
||||
?: throw UnknownDatabaseLocationException()
|
||||
|
||||
BufferedInputStream(databaseStream).use { databaseInputStream ->
|
||||
@@ -866,7 +868,7 @@ class Database {
|
||||
}
|
||||
}
|
||||
// Copy from the cache to the final stream
|
||||
UriUtil.getUriOutputStream(contentResolver, saveUri)?.use { outputStream ->
|
||||
UriUtilDatabase.getUriOutputStream(contentResolver, saveUri)?.use { outputStream ->
|
||||
cacheFile.inputStream().use { inputStream ->
|
||||
inputStream.readAllBytes { buffer ->
|
||||
outputStream.write(buffer)
|
||||
@@ -1005,7 +1007,7 @@ class Database {
|
||||
}
|
||||
|
||||
fun clearAndClose(context: Context? = null) {
|
||||
clearIndexesAndBinaries(context?.let { UriUtil.getBinaryDir(context) })
|
||||
clearIndexesAndBinaries(context?.let { com.kunzisoft.keepass.utils.UriUtilDatabase.getBinaryDir(context) })
|
||||
this.mDatabaseKDB = null
|
||||
this.mDatabaseKDBX = null
|
||||
this.fileUri = null
|
||||
@@ -30,7 +30,7 @@ import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.node.*
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.GroupInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@@ -87,7 +87,7 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
|
||||
|
||||
companion object {
|
||||
fun getDefaults(context: Context): Array<ChildFilter> {
|
||||
return if (PreferencesUtil.showExpiredEntries(context)) {
|
||||
return if (DatabasePreferencesUtil.showExpiredEntries(context)) {
|
||||
arrayOf(META_STREAM)
|
||||
} else {
|
||||
arrayOf(META_STREAM, EXPIRED)
|
||||
@@ -29,7 +29,7 @@ import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.utils.StringUtil.removeSpaceChars
|
||||
import com.kunzisoft.keepass.utils.StringUtil.toHexString
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtilDatabase
|
||||
import com.kunzisoft.keepass.utils.readEnum
|
||||
import com.kunzisoft.keepass.utils.writeEnum
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
@@ -148,7 +148,7 @@ data class MainCredential(var password: String? = null,
|
||||
@Throws(Exception::class)
|
||||
private fun getKeyFileData(contentResolver: ContentResolver,
|
||||
keyFileUri: Uri): ByteArray? {
|
||||
UriUtil.getUriInputStream(contentResolver, keyFileUri)?.use { keyFileInputStream ->
|
||||
UriUtilDatabase.getUriInputStream(contentResolver, keyFileUri)?.use { keyFileInputStream ->
|
||||
return keyFileInputStream.readBytes()
|
||||
}
|
||||
return null
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.database.element.database
|
||||
import android.content.res.Resources
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.R
|
||||
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||
import com.kunzisoft.keepass.utils.readEnum
|
||||
import com.kunzisoft.keepass.utils.writeEnum
|
||||
@@ -24,7 +24,7 @@ import android.content.res.Resources
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import com.kunzisoft.encrypt.HashManager
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.R
|
||||
import com.kunzisoft.keepass.database.action.node.NodeHandler
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.crypto.VariantDictionary
|
||||
@@ -32,7 +32,12 @@ import com.kunzisoft.keepass.database.crypto.kdf.AesKdf
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfFactory
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfParameters
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.element.CompositeKey
|
||||
import com.kunzisoft.keepass.database.element.CustomData
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.DeletedObject
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.Tags
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.element.database.DatabaseKDB.Companion.BACKUP_FOLDER_TITLE
|
||||
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
|
||||
@@ -58,7 +63,8 @@ import java.io.IOException
|
||||
import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.*
|
||||
import java.util.Arrays
|
||||
import java.util.UUID
|
||||
import javax.crypto.Mac
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -141,6 +147,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
|
||||
var maintenanceHistoryDays = UnsignedInt(365)
|
||||
var color = ""
|
||||
|
||||
/**
|
||||
* Determine if RecycleBin is enable or not
|
||||
* @return true if RecycleBin enable, false if is not available or not enable
|
||||
@@ -168,9 +175,11 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
/**
|
||||
* Create a new database with a root group
|
||||
*/
|
||||
constructor(databaseName: String,
|
||||
constructor(
|
||||
databaseName: String,
|
||||
rootName: String,
|
||||
templatesGroupName: String? = null) {
|
||||
templatesGroupName: String? = null,
|
||||
) {
|
||||
name = databaseName
|
||||
kdbxVersion = FILE_VERSION_31
|
||||
val group = createGroup().apply {
|
||||
@@ -231,7 +240,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
fun deriveMasterKey(
|
||||
contentResolver: ContentResolver,
|
||||
mainCredential: MainCredential,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
) {
|
||||
// Retrieve each plain credential
|
||||
val password = mainCredential.password
|
||||
@@ -263,7 +272,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
|
||||
@Throws(DatabaseOutputException::class)
|
||||
fun deriveCompositeKey(
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
) {
|
||||
val passwordBytes = mCompositeKey.passwordData
|
||||
val keyFileBytes = mCompositeKey.keyFileData
|
||||
@@ -286,9 +295,11 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun composedKeyToMasterKey(passwordData: ByteArray?,
|
||||
private fun composedKeyToMasterKey(
|
||||
passwordData: ByteArray?,
|
||||
keyFileData: ByteArray?,
|
||||
hardwareKeyData: ByteArray? = null): ByteArray {
|
||||
hardwareKeyData: ByteArray? = null,
|
||||
): ByteArray {
|
||||
return HashManager.hashSha256(
|
||||
passwordData,
|
||||
keyFileData,
|
||||
@@ -308,26 +319,33 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
|
||||
// https://keepass.info/help/kb/kdbx_4.1.html
|
||||
val containsGroupWithTag = groupHandler.containsTags
|
||||
val containsEntryWithPasswordQualityEstimationDisabled = entryHandler.passwordQualityEstimationDisabled
|
||||
val containsCustomIconWithNameOrLastModificationTime = iconsManager.containsCustomIconWithNameOrLastModificationTime()
|
||||
val containsHeaderCustomDataWithLastModificationTime = customData.containsItemWithLastModificationTime()
|
||||
val containsEntryWithPasswordQualityEstimationDisabled =
|
||||
entryHandler.passwordQualityEstimationDisabled
|
||||
val containsCustomIconWithNameOrLastModificationTime =
|
||||
iconsManager.containsCustomIconWithNameOrLastModificationTime()
|
||||
val containsHeaderCustomDataWithLastModificationTime =
|
||||
customData.containsItemWithLastModificationTime()
|
||||
|
||||
// https://keepass.info/help/kb/kdbx_4.html
|
||||
// If AES is not use, it's at least 4.0
|
||||
val keyDerivationFunction = kdfEngine
|
||||
val kdfIsNotAes = keyDerivationFunction != null && keyDerivationFunction.uuid != AesKdf.CIPHER_UUID
|
||||
val kdfIsNotAes =
|
||||
keyDerivationFunction != null && keyDerivationFunction.uuid != AesKdf.CIPHER_UUID
|
||||
val containsHeaderCustomData = customData.isNotEmpty()
|
||||
val containsNodeCustomData = entryHandler.containsCustomData || groupHandler.containsCustomData
|
||||
val containsNodeCustomData =
|
||||
entryHandler.containsCustomData || groupHandler.containsCustomData
|
||||
|
||||
// Check each condition to determine version
|
||||
return if (containsGroupWithTag
|
||||
|| containsEntryWithPasswordQualityEstimationDisabled
|
||||
|| containsCustomIconWithNameOrLastModificationTime
|
||||
|| containsHeaderCustomDataWithLastModificationTime) {
|
||||
|| containsHeaderCustomDataWithLastModificationTime
|
||||
) {
|
||||
FILE_VERSION_41
|
||||
} else if (kdfIsNotAes
|
||||
|| containsHeaderCustomData
|
||||
|| containsNodeCustomData) {
|
||||
|| containsNodeCustomData
|
||||
) {
|
||||
FILE_VERSION_40
|
||||
} else {
|
||||
FILE_VERSION_31
|
||||
@@ -339,8 +357,10 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
CompressionAlgorithm.GZip
|
||||
)
|
||||
|
||||
fun changeBinaryCompression(oldCompression: CompressionAlgorithm,
|
||||
newCompression: CompressionAlgorithm) {
|
||||
fun changeBinaryCompression(
|
||||
oldCompression: CompressionAlgorithm,
|
||||
newCompression: CompressionAlgorithm,
|
||||
) {
|
||||
when (oldCompression) {
|
||||
CompressionAlgorithm.None -> {
|
||||
when (newCompression) {
|
||||
@@ -455,17 +475,21 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
return this.iconsManager.getIcon(iconId)
|
||||
}
|
||||
|
||||
fun buildNewCustomIcon(customIconId: UUID? = null,
|
||||
result: (IconImageCustom, BinaryData?) -> Unit) {
|
||||
fun buildNewCustomIcon(
|
||||
customIconId: UUID? = null,
|
||||
result: (IconImageCustom, BinaryData?) -> Unit,
|
||||
) {
|
||||
// Create a binary file for a brand new custom icon
|
||||
addCustomIcon(customIconId, "", null, false, result)
|
||||
}
|
||||
|
||||
fun addCustomIcon(customIconId: UUID? = null,
|
||||
fun addCustomIcon(
|
||||
customIconId: UUID? = null,
|
||||
name: String,
|
||||
lastModificationTime: DateInstant?,
|
||||
smallSize: Boolean,
|
||||
result: (IconImageCustom, BinaryData?) -> Unit) {
|
||||
result: (IconImageCustom, BinaryData?) -> Unit,
|
||||
) {
|
||||
iconsManager.addCustomIcon(customIconId, name, lastModificationTime, { uniqueBinaryId ->
|
||||
// Create a byte array for better performance with small data
|
||||
binaryCache.getBinaryData(uniqueBinaryId, smallSize)
|
||||
@@ -525,7 +549,10 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
return mTemplateEngine.getTemplate(entry)
|
||||
}
|
||||
|
||||
fun decodeEntryWithTemplateConfiguration(entryKDBX: EntryKDBX, entryIsTemplate: Boolean): EntryKDBX {
|
||||
fun decodeEntryWithTemplateConfiguration(
|
||||
entryKDBX: EntryKDBX,
|
||||
entryIsTemplate: Boolean,
|
||||
): EntryKDBX {
|
||||
return if (entryIsTemplate) {
|
||||
mTemplateEngine.decodeTemplateEntry(entryKDBX)
|
||||
} else {
|
||||
@@ -533,7 +560,11 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
}
|
||||
}
|
||||
|
||||
fun encodeEntryWithTemplateConfiguration(entryKDBX: EntryKDBX, entryIsTemplate: Boolean, template: Template): EntryKDBX {
|
||||
fun encodeEntryWithTemplateConfiguration(
|
||||
entryKDBX: EntryKDBX,
|
||||
entryIsTemplate: Boolean,
|
||||
template: Template,
|
||||
): EntryKDBX {
|
||||
return if (entryIsTemplate) {
|
||||
mTemplateEngine.encodeTemplateEntry(entryKDBX)
|
||||
} else {
|
||||
@@ -603,7 +634,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
val kdfEngine = getKdfEngineFromParameters(keyDerivationFunctionParameters)
|
||||
?: throw IOException("Unknown key derivation function")
|
||||
|
||||
var transformedMasterKey = kdfEngine.transform(masterKey, keyDerivationFunctionParameters)
|
||||
var transformedMasterKey =
|
||||
kdfEngine.transform(masterKey, keyDerivationFunctionParameters)
|
||||
if (transformedMasterKey.size != 32) {
|
||||
transformedMasterKey = HashManager.hashSha256(transformedMasterKey)
|
||||
}
|
||||
@@ -702,7 +734,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
var currentGroup: GroupKDBX? = group
|
||||
while (currentGroup != null) {
|
||||
if (currentGroup.parent == rootGroup
|
||||
&& currentGroup.title.equals(BACKUP_FOLDER_TITLE, ignoreCase = true)) {
|
||||
&& currentGroup.title.equals(BACKUP_FOLDER_TITLE, ignoreCase = true)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
currentGroup = currentGroup.parent
|
||||
@@ -761,7 +794,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
if (recycleBin == null)
|
||||
return false
|
||||
if (node is GroupKDBX
|
||||
&& recycleBin!!.isContainedIn(node))
|
||||
&& recycleBin!!.isContainedIn(node)
|
||||
)
|
||||
return false
|
||||
if (!node.isContainedIn(recycleBin!!))
|
||||
return true
|
||||
@@ -798,10 +832,12 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
mFieldReferenceEngine.clear()
|
||||
}
|
||||
|
||||
fun buildNewBinaryAttachment(smallSize: Boolean,
|
||||
fun buildNewBinaryAttachment(
|
||||
smallSize: Boolean,
|
||||
compression: Boolean,
|
||||
protection: Boolean,
|
||||
binaryPoolId: Int? = null): BinaryData {
|
||||
binaryPoolId: Int? = null,
|
||||
): BinaryData {
|
||||
return attachmentPool.put(binaryPoolId) { uniqueBinaryId ->
|
||||
binaryCache.getBinaryData(uniqueBinaryId, smallSize, compression, protection)
|
||||
}.binary
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user