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\"}"
|
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
|
||||||
manifestPlaceholders = [ googleAndroidBackupAPIKey:"unused" ]
|
manifestPlaceholders = [ googleAndroidBackupAPIKey:"unused" ]
|
||||||
|
|
||||||
kapt {
|
|
||||||
arguments {
|
|
||||||
arg("room.incremental", "true")
|
|
||||||
arg("room.schemaLocation", "$projectDir/schemas".toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() {
|
|||||||
private const val NEW_FILE_DATABASE_INFO = "NEW_FILE_DATABASE_INFO"
|
private const val NEW_FILE_DATABASE_INFO = "NEW_FILE_DATABASE_INFO"
|
||||||
|
|
||||||
fun getInstance(oldSnapFileDatabaseInfo: SnapFileDatabaseInfo,
|
fun getInstance(oldSnapFileDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
newSnapFileDatabaseInfo: SnapFileDatabaseInfo)
|
newSnapFileDatabaseInfo: SnapFileDatabaseInfo
|
||||||
|
)
|
||||||
: DatabaseChangedDialogFragment {
|
: DatabaseChangedDialogFragment {
|
||||||
val fragment = DatabaseChangedDialogFragment()
|
val fragment = DatabaseChangedDialogFragment()
|
||||||
fragment.arguments = Bundle().apply {
|
fragment.arguments = Bundle().apply {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.view.inputmethod.EditorInfo
|
|||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.kunzisoft.keepass.BuildConfig
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.model.OtpModel
|
import com.kunzisoft.keepass.model.OtpModel
|
||||||
import com.kunzisoft.keepass.otp.OtpElement
|
import com.kunzisoft.keepass.otp.OtpElement
|
||||||
@@ -470,4 +469,4 @@ class SetOTPDialogFragment : DatabaseDialogFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
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.net.Uri
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
|
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||||
import java.util.*
|
import java.util.LinkedList
|
||||||
|
|
||||||
class CipherDatabaseAction(context: Context) {
|
class CipherDatabaseAction(context: Context) {
|
||||||
|
|
||||||
private val applicationContext = context.applicationContext
|
private val applicationContext = context.applicationContext
|
||||||
private val cipherDatabaseDao =
|
private val cipherDatabaseDao =
|
||||||
AppDatabase
|
AppDatabase.getDatabase(applicationContext)
|
||||||
.getDatabase(applicationContext)
|
|
||||||
.cipherDatabaseDao()
|
.cipherDatabaseDao()
|
||||||
|
|
||||||
// Temp DAO to easily remove content if object no longer in memory
|
// Temp DAO to easily remove content if object no longer in memory
|
||||||
private var useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
|
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 mServiceConnection: ServiceConnection? = null
|
||||||
|
|
||||||
private var mDatabaseListeners = LinkedList<CipherDatabaseListener>()
|
private var mDatabaseListeners = LinkedList<CipherDatabaseListener>()
|
||||||
private var mAdvancedUnlockBroadcastReceiver = AdvancedUnlockNotificationService.AdvancedUnlockReceiver {
|
private var mAdvancedUnlockBroadcastReceiver = com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.AdvancedUnlockReceiver {
|
||||||
deleteAll()
|
deleteAll()
|
||||||
removeAllDataAndDetach()
|
removeAllDataAndDetach()
|
||||||
}
|
}
|
||||||
@@ -67,12 +49,12 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
private fun attachService(performedAction: () -> Unit) {
|
private fun attachService(performedAction: () -> Unit) {
|
||||||
applicationContext.registerReceiver(mAdvancedUnlockBroadcastReceiver, IntentFilter().apply {
|
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 {
|
mServiceConnection = object : ServiceConnection {
|
||||||
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
||||||
mBinder = (serviceBinder as AdvancedUnlockNotificationService.AdvancedUnlockBinder)
|
mBinder = (serviceBinder as com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.AdvancedUnlockBinder)
|
||||||
performedAction.invoke()
|
performedAction.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,9 +63,9 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
AdvancedUnlockNotificationService.bindService(applicationContext,
|
com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.bindService(applicationContext,
|
||||||
mServiceConnection!!,
|
mServiceConnection!!,
|
||||||
Context.BIND_AUTO_CREATE)
|
Context.BIND_AUTO_CREATE)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Unable to start cipher action", e)
|
Log.e(TAG, "Unable to start cipher action", e)
|
||||||
performedAction.invoke()
|
performedAction.invoke()
|
||||||
@@ -97,7 +79,7 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
|
|
||||||
mServiceConnection?.let {
|
mServiceConnection?.let {
|
||||||
AdvancedUnlockNotificationService.unbindService(applicationContext, it)
|
com.kunzisoft.keepass.services.AdvancedUnlockNotificationService.unbindService(applicationContext, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +130,9 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())?.let { cipherDatabaseEntity ->
|
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
|
||||||
|
?.let { cipherDatabaseEntity ->
|
||||||
CipherEncryptDatabase().apply {
|
CipherEncryptDatabase().apply {
|
||||||
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
|
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
|
||||||
this.encryptedValue = Base64.decode(
|
this.encryptedValue = Base64.decode(
|
||||||
@@ -162,10 +145,10 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cipherDatabaseResultListener.invoke(it)
|
cipherDatabaseResultListener.invoke(it)
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,12 +205,12 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
|
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cipherDatabaseResultListener?.invoke()
|
cipherDatabaseResultListener?.invoke()
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,9 +223,9 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
}
|
}
|
||||||
// To erase the residues
|
// To erase the residues
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
cipherDatabaseDao.deleteAll()
|
cipherDatabaseDao.deleteAll()
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
// Unbind
|
// Unbind
|
||||||
removeAllDataAndDetach()
|
removeAllDataAndDetach()
|
||||||
@@ -251,4 +234,4 @@ class CipherDatabaseAction(context: Context) {
|
|||||||
companion object : SingletonHolderParameter<CipherDatabaseAction, Context>(::CipherDatabaseAction) {
|
companion object : SingletonHolderParameter<CipherDatabaseAction, Context>(::CipherDatabaseAction) {
|
||||||
private val TAG = CipherDatabaseAction::class.java.name
|
private val TAG = CipherDatabaseAction::class.java.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
package com.kunzisoft.keepass.app.database
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -25,214 +6,225 @@ import android.util.Log
|
|||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.DatabaseFile
|
import com.kunzisoft.keepass.model.DatabaseFile
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
import com.kunzisoft.keepass.utils.UriUtilDatabase
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
|
||||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||||
|
|
||||||
class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||||
|
|
||||||
private val databaseFileHistoryDao =
|
private val databaseFileHistoryDao =
|
||||||
AppDatabase
|
AppDatabase.getDatabase(applicationContext)
|
||||||
.getDatabase(applicationContext)
|
|
||||||
.fileDatabaseHistoryDao()
|
.fileDatabaseHistoryDao()
|
||||||
|
|
||||||
fun getDatabaseFile(databaseUri: Uri,
|
fun getDatabaseFile(databaseUri: Uri,
|
||||||
databaseFileResult: (DatabaseFile?) -> Unit) {
|
databaseFileResult: (com.kunzisoft.keepass.model.DatabaseFile?) -> Unit) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
val fileDatabaseHistoryEntity = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
val fileDatabaseHistoryEntity =
|
||||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, databaseUri)
|
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||||
DatabaseFile(
|
val fileDatabaseInfo = FileDatabaseInfo(
|
||||||
databaseUri,
|
applicationContext,
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
databaseUri)
|
||||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
DatabaseFile(
|
||||||
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
databaseUri,
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
UriUtilDatabase.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||||
fileDatabaseInfo.exists,
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
||||||
fileDatabaseInfo.getLastModificationString(),
|
UriUtilDatabase.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||||
fileDatabaseInfo.getSizeString()
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias
|
||||||
)
|
?: ""),
|
||||||
},
|
fileDatabaseInfo.exists,
|
||||||
{
|
fileDatabaseInfo.getLastModificationString(),
|
||||||
databaseFileResult.invoke(it)
|
fileDatabaseInfo.getSizeString()
|
||||||
}
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
databaseFileResult.invoke(it)
|
||||||
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getKeyFileUriByDatabaseUri(databaseUri: Uri,
|
fun getKeyFileUriByDatabaseUri(databaseUri: Uri,
|
||||||
keyFileUriResultListener: (Uri?) -> Unit) {
|
keyFileUriResultListener: (Uri?) -> Unit) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
it?.let { fileHistoryEntity ->
|
it?.let { fileHistoryEntity ->
|
||||||
fileHistoryEntity.keyFileUri?.let { keyFileUri ->
|
fileHistoryEntity.keyFileUri?.let { keyFileUri ->
|
||||||
keyFileUriResultListener.invoke(UriUtil.parse(keyFileUri))
|
keyFileUriResultListener.invoke(UriUtilDatabase.parse(
|
||||||
}
|
keyFileUri))
|
||||||
} ?: keyFileUriResultListener.invoke(null)
|
}
|
||||||
}
|
} ?: keyFileUriResultListener.invoke(null)
|
||||||
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDatabaseFileList(databaseFileListResult: (List<DatabaseFile>) -> Unit) {
|
fun getDatabaseFileList(databaseFileListResult: (List<com.kunzisoft.keepass.model.DatabaseFile>) -> Unit) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(applicationContext)
|
val hideBrokenLocations =
|
||||||
// Show only uri accessible
|
PreferencesUtil.hideBrokenLocations(
|
||||||
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
applicationContext)
|
||||||
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
// Show only uri accessible
|
||||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, fileDatabaseHistoryEntity.databaseUri)
|
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
||||||
if (hideBrokenLocations && fileDatabaseInfo.exists
|
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
||||||
|| !hideBrokenLocations) {
|
val fileDatabaseInfo = FileDatabaseInfo(
|
||||||
databaseFileListLoaded.add(
|
applicationContext,
|
||||||
DatabaseFile(
|
fileDatabaseHistoryEntity.databaseUri)
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
if (hideBrokenLocations && fileDatabaseInfo.exists
|
||||||
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
|| !hideBrokenLocations
|
||||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
) {
|
||||||
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
databaseFileListLoaded.add(
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
DatabaseFile(
|
||||||
fileDatabaseInfo.exists,
|
UriUtilDatabase.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||||
fileDatabaseInfo.getLastModificationString(),
|
UriUtilDatabase.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||||
fileDatabaseInfo.getSizeString()
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
||||||
)
|
UriUtilDatabase.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||||
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||||
|
fileDatabaseInfo.exists,
|
||||||
|
fileDatabaseInfo.getLastModificationString(),
|
||||||
|
fileDatabaseInfo.getSizeString()
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
|
||||||
databaseFileListLoaded
|
|
||||||
},
|
|
||||||
{
|
|
||||||
databaseFileList ->
|
|
||||||
databaseFileList?.let {
|
|
||||||
databaseFileListResult.invoke(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
databaseFileListLoaded
|
||||||
|
},
|
||||||
|
{ databaseFileList ->
|
||||||
|
databaseFileList?.let {
|
||||||
|
databaseFileListResult.invoke(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addOrUpdateDatabaseUri(databaseUri: Uri,
|
fun addOrUpdateDatabaseUri(databaseUri: Uri,
|
||||||
keyFileUri: Uri? = null,
|
keyFileUri: Uri? = null,
|
||||||
hardwareKey: HardwareKey? = null,
|
hardwareKey: HardwareKey? = null,
|
||||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
databaseFileAddedOrUpdatedResult: ((com.kunzisoft.keepass.model.DatabaseFile?) -> Unit)? = null) {
|
||||||
addOrUpdateDatabaseFile(DatabaseFile(
|
addOrUpdateDatabaseFile(com.kunzisoft.keepass.model.DatabaseFile(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
keyFileUri,
|
keyFileUri,
|
||||||
hardwareKey
|
hardwareKey
|
||||||
), databaseFileAddedOrUpdatedResult)
|
), databaseFileAddedOrUpdatedResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: DatabaseFile,
|
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: com.kunzisoft.keepass.model.DatabaseFile,
|
||||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
databaseFileAddedOrUpdatedResult: ((com.kunzisoft.keepass.model.DatabaseFile?) -> Unit)? = null) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
||||||
// Try to get info in database first
|
// Try to get info in database first
|
||||||
val fileDatabaseHistoryRetrieve = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
val fileDatabaseHistoryRetrieve =
|
||||||
|
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||||
|
|
||||||
// Complete alias if not exists
|
// Complete alias if not exists
|
||||||
val fileDatabaseHistory = FileDatabaseHistoryEntity(
|
val fileDatabaseHistory =
|
||||||
databaseUri.toString(),
|
FileDatabaseHistoryEntity(
|
||||||
databaseFileToAddOrUpdate.databaseAlias
|
databaseUri.toString(),
|
||||||
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
databaseFileToAddOrUpdate.databaseAlias
|
||||||
?: "",
|
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
||||||
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
?: "",
|
||||||
databaseFileToAddOrUpdate.hardwareKey?.value,
|
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
||||||
System.currentTimeMillis()
|
databaseFileToAddOrUpdate.hardwareKey?.value,
|
||||||
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Update values if history element not yet in the database
|
// Update values if history element not yet in the database
|
||||||
try {
|
try {
|
||||||
if (fileDatabaseHistoryRetrieve == null) {
|
if (fileDatabaseHistoryRetrieve == null) {
|
||||||
databaseFileHistoryDao.add(fileDatabaseHistory)
|
databaseFileHistoryDao.add(fileDatabaseHistory)
|
||||||
} else {
|
} else {
|
||||||
databaseFileHistoryDao.update(fileDatabaseHistory)
|
databaseFileHistoryDao.update(fileDatabaseHistory)
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Unable to add or update database history", e)
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
Log.e(TAG, "Unable to add or update database history", e)
|
||||||
fileDatabaseHistory.databaseUri)
|
|
||||||
DatabaseFile(
|
|
||||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
|
||||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
|
||||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
|
||||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
|
||||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
|
||||||
fileDatabaseInfo.exists,
|
|
||||||
fileDatabaseInfo.getLastModificationString(),
|
|
||||||
fileDatabaseInfo.getSizeString()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
val fileDatabaseInfo =
|
||||||
databaseFileAddedOrUpdatedResult?.invoke(it)
|
FileDatabaseInfo(applicationContext,
|
||||||
|
fileDatabaseHistory.databaseUri)
|
||||||
|
DatabaseFile(
|
||||||
|
UriUtilDatabase.parse(fileDatabaseHistory.databaseUri),
|
||||||
|
UriUtilDatabase.parse(fileDatabaseHistory.keyFileUri),
|
||||||
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||||
|
UriUtilDatabase.decode(fileDatabaseHistory.databaseUri),
|
||||||
|
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||||
|
fileDatabaseInfo.exists,
|
||||||
|
fileDatabaseInfo.getLastModificationString(),
|
||||||
|
fileDatabaseInfo.getSizeString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
databaseFileAddedOrUpdatedResult?.invoke(it)
|
||||||
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile,
|
fun deleteDatabaseFile(databaseFileToDelete: com.kunzisoft.keepass.model.DatabaseFile,
|
||||||
databaseFileDeletedResult: (DatabaseFile?) -> Unit) {
|
databaseFileDeletedResult: (com.kunzisoft.keepass.model.DatabaseFile?) -> Unit) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
||||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())?.let { fileDatabaseHistory ->
|
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||||
|
?.let { fileDatabaseHistory ->
|
||||||
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||||
if (returnValue > 0) {
|
if (returnValue > 0) {
|
||||||
DatabaseFile(
|
DatabaseFile(
|
||||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
UriUtilDatabase.parse(fileDatabaseHistory.databaseUri),
|
||||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
UriUtilDatabase.parse(fileDatabaseHistory.keyFileUri),
|
||||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
UriUtilDatabase.decode(fileDatabaseHistory.databaseUri),
|
||||||
databaseFileToDelete.databaseAlias
|
databaseFileToDelete.databaseAlias
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
databaseFileDeletedResult.invoke(it)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
databaseFileDeletedResult.invoke(it)
|
||||||
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteKeyFileByDatabaseUri(databaseUri: Uri,
|
fun deleteKeyFileByDatabaseUri(databaseUri: Uri,
|
||||||
result: (() ->Unit)? = null) {
|
result: (() ->Unit)? = null) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileHistoryDao.deleteKeyFileByDatabaseUri(databaseUri.toString())
|
databaseFileHistoryDao.deleteKeyFileByDatabaseUri(databaseUri.toString())
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
result?.invoke()
|
result?.invoke()
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAllKeyFiles(result: (() ->Unit)? = null) {
|
fun deleteAllKeyFiles(result: (() ->Unit)? = null) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileHistoryDao.deleteAllKeyFiles()
|
databaseFileHistoryDao.deleteAllKeyFiles()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
result?.invoke()
|
result?.invoke()
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAll(result: (() ->Unit)? = null) {
|
fun deleteAll(result: (() ->Unit)? = null) {
|
||||||
IOActionTask(
|
IOActionTask(
|
||||||
{
|
{
|
||||||
databaseFileHistoryDao.deleteAll()
|
databaseFileHistoryDao.deleteAll()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
result?.invoke()
|
result?.invoke()
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : SingletonHolderParameter<FileDatabaseHistoryAction, Context>(::FileDatabaseHistoryAction) {
|
companion object : com.kunzisoft.keepass.utils.SingletonHolderParameter<FileDatabaseHistoryAction, Context>(::FileDatabaseHistoryAction) {
|
||||||
private val TAG = FileDatabaseHistoryAction::class.java.name
|
private val TAG = FileDatabaseHistoryAction::class.java.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import android.os.CancellationSignal
|
|||||||
import android.service.autofill.*
|
import android.service.autofill.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.autofill.AutofillId
|
import android.view.autofill.AutofillId
|
||||||
import android.view.inputmethod.InlineSuggestionsRequest
|
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.autofill.inline.UiVersions
|
import androidx.autofill.inline.UiVersions
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package com.kunzisoft.keepass.database.action
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
|
||||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
@@ -54,7 +53,7 @@ open class AssignMainCredentialInDatabaseRunnable (
|
|||||||
super.onFinishRun()
|
super.onFinishRun()
|
||||||
|
|
||||||
// Erase the biometric
|
// Erase the biometric
|
||||||
CipherDatabaseAction.getInstance(context)
|
com.kunzisoft.keepass.app.database.CipherDatabaseAction.getInstance(context)
|
||||||
.deleteByDatabaseUri(mDatabaseUri)
|
.deleteByDatabaseUri(mDatabaseUri)
|
||||||
// Erase the register keyfile
|
// Erase the register keyfile
|
||||||
FileDatabaseHistoryAction.getInstance(context)
|
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
|
package com.kunzisoft.keepass.database.action
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.*
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context.*
|
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.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.kunzisoft.keepass.R
|
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_START_TASK_ACTION
|
||||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||||
import com.kunzisoft.keepass.viewmodels.ChallengeResponseViewModel
|
import com.kunzisoft.keepass.viewmodels.ChallengeResponseViewModel
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to connect an activity or a service to the DatabaseTaskNotificationService,
|
* Utility class to connect an activity or a service to the DatabaseTaskNotificationService,
|
||||||
@@ -103,7 +89,8 @@ class DatabaseTaskProvider {
|
|||||||
|
|
||||||
var onActionFinish: ((database: Database,
|
var onActionFinish: ((database: Database,
|
||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result) -> Unit)? = null
|
result: ActionRunnable.Result
|
||||||
|
) -> Unit)? = null
|
||||||
|
|
||||||
private var intentDatabaseTask: Intent
|
private var intentDatabaseTask: Intent
|
||||||
|
|
||||||
@@ -177,7 +164,8 @@ class DatabaseTaskProvider {
|
|||||||
|
|
||||||
private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener {
|
private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener {
|
||||||
override fun onStartAction(database: Database,
|
override fun onStartAction(database: Database,
|
||||||
progressMessage: ProgressMessage) {
|
progressMessage: ProgressMessage
|
||||||
|
) {
|
||||||
startDialog(progressMessage)
|
startDialog(progressMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +176,8 @@ class DatabaseTaskProvider {
|
|||||||
|
|
||||||
override fun onStopAction(database: Database,
|
override fun onStopAction(database: Database,
|
||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result) {
|
result: ActionRunnable.Result
|
||||||
|
) {
|
||||||
onActionFinish?.invoke(database, actionTask, result)
|
onActionFinish?.invoke(database, actionTask, result)
|
||||||
// Remove the progress task
|
// Remove the progress task
|
||||||
stopDialog()
|
stopDialog()
|
||||||
@@ -310,7 +299,7 @@ class DatabaseTaskProvider {
|
|||||||
private fun bindService() {
|
private fun bindService() {
|
||||||
initServiceConnection()
|
initServiceConnection()
|
||||||
serviceConnection?.let {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,4 +752,4 @@ class DatabaseTaskProvider {
|
|||||||
companion object {
|
companion object {
|
||||||
private val TAG = DatabaseTaskProvider::class.java.name
|
private val TAG = DatabaseTaskProvider::class.java.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,30 +21,29 @@ package com.kunzisoft.keepass.database.action
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
|
||||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
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.element.binary.BinaryData
|
||||||
import com.kunzisoft.keepass.database.exception.DatabaseInputException
|
import com.kunzisoft.keepass.database.exception.DatabaseInputException
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.database.element.MainCredential
|
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
|
||||||
|
|
||||||
class LoadDatabaseRunnable(private val context: Context,
|
class LoadDatabaseRunnable(
|
||||||
private val mDatabase: Database,
|
private val context: Context,
|
||||||
private val mDatabaseUri: Uri,
|
private val mDatabase: Database,
|
||||||
private val mMainCredential: MainCredential,
|
private val mDatabaseUri: Uri,
|
||||||
private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray,
|
private val mMainCredential: MainCredential,
|
||||||
private val mReadonly: Boolean,
|
private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray,
|
||||||
private val mCipherEncryptDatabase: CipherEncryptDatabase?,
|
private val mReadonly: Boolean,
|
||||||
private val mFixDuplicateUUID: Boolean,
|
private val mCipherEncryptDatabase: CipherEncryptDatabase?,
|
||||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
private val mFixDuplicateUUID: Boolean,
|
||||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||||
: ActionRunnable() {
|
private val mLoadDatabaseResult: ((Result) -> Unit)?,
|
||||||
|
) : ActionRunnable() {
|
||||||
|
|
||||||
override fun onStartRun() {
|
override fun onStartRun() {
|
||||||
// Clear before we load
|
// Clear before we load
|
||||||
@@ -59,15 +58,14 @@ class LoadDatabaseRunnable(private val context: Context,
|
|||||||
mMainCredential,
|
mMainCredential,
|
||||||
mChallengeResponseRetriever,
|
mChallengeResponseRetriever,
|
||||||
mReadonly,
|
mReadonly,
|
||||||
UriUtil.getBinaryDir(context),
|
com.kunzisoft.keepass.utils.UriUtilDatabase.getBinaryDir(context),
|
||||||
{ memoryWanted ->
|
{ memoryWanted ->
|
||||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||||
},
|
},
|
||||||
mFixDuplicateUUID,
|
mFixDuplicateUUID,
|
||||||
progressTaskUpdater
|
progressTaskUpdater
|
||||||
)
|
)
|
||||||
}
|
} catch (e: DatabaseInputException) {
|
||||||
catch (e: DatabaseInputException) {
|
|
||||||
setError(e)
|
setError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,17 +73,17 @@ class LoadDatabaseRunnable(private val context: Context,
|
|||||||
// Save keyFile in app database
|
// Save keyFile in app database
|
||||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||||
FileDatabaseHistoryAction.getInstance(context)
|
FileDatabaseHistoryAction.getInstance(context)
|
||||||
.addOrUpdateDatabaseUri(
|
.addOrUpdateDatabaseUri(
|
||||||
mDatabaseUri,
|
mDatabaseUri,
|
||||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null,
|
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null,
|
||||||
if (PreferencesUtil.rememberHardwareKey(context)) mMainCredential.hardwareKey else null,
|
if (PreferencesUtil.rememberHardwareKey(context)) mMainCredential.hardwareKey else null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the biometric
|
// Register the biometric
|
||||||
mCipherEncryptDatabase?.let { cipherDatabase ->
|
mCipherEncryptDatabase?.let { cipherDatabase ->
|
||||||
CipherDatabaseAction.getInstance(context)
|
com.kunzisoft.keepass.app.database.CipherDatabaseAction.getInstance(context)
|
||||||
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
|
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the current time to init the lock timer
|
// Register the current time to init the lock timer
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class HardwareKeyResponseHelper {
|
class HardwareKeyResponseHelper {
|
||||||
@@ -134,11 +133,11 @@ class HardwareKeyResponseHelper {
|
|||||||
activity.getString(R.string.error_driver_required, hardwareKey.toString())
|
activity.getString(R.string.error_driver_required, hardwareKey.toString())
|
||||||
)
|
)
|
||||||
.setPositiveButton(R.string.download) { _, _ ->
|
.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) { _, _ -> }
|
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
builder.create().show()
|
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
|
package com.kunzisoft.keepass.icons
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.kunzisoft.keepass.BuildConfig
|
import com.kunzisoft.keepass.BuildConfig
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to built and select an IconPack dynamically by libraries importation
|
* Utility class to built and select an IconPack dynamically by libraries importation
|
||||||
*
|
*
|
||||||
* @author J-Jamet
|
* @author J-Jamet
|
||||||
*/
|
*/
|
||||||
object IconPackChooser {
|
object IconPackChooser : InterfaceIconPackChooser {
|
||||||
|
|
||||||
private val TAG = IconPackChooser::class.java.name
|
private val TAG = IconPackChooser::class.java.name
|
||||||
|
|
||||||
@@ -50,7 +31,7 @@ object IconPackChooser {
|
|||||||
* @param context Context to construct each pack with the resources
|
* @param context Context to construct each pack with the resources
|
||||||
* @return An unique instance of [IconPackChooser], recall [.build] provide the same instance
|
* @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) {
|
synchronized(IconPackChooser::class.java) {
|
||||||
if (!isIconPackChooserBuilt) {
|
if (!isIconPackChooserBuilt) {
|
||||||
isIconPackChooserBuilt = true
|
isIconPackChooserBuilt = true
|
||||||
@@ -69,7 +50,7 @@ object IconPackChooser {
|
|||||||
/**
|
/**
|
||||||
* Construct dynamically the icon pack provide by the default string resource "resource_id"
|
* 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)
|
val resourceId = context.resources.getIdentifier("resource_id", "string", context.packageName)
|
||||||
iconPackList.add(IconPack(context.packageName, context.resources, resourceId))
|
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
|
* 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 {
|
try {
|
||||||
iconPackList.add(IconPack(context.packageName, context.resources, context.resources.getIdentifier(
|
iconPackList.add(IconPack(context.packageName,
|
||||||
|
context.resources,
|
||||||
|
context.resources.getIdentifier(
|
||||||
iconPackString + "_resource_id",
|
iconPackString + "_resource_id",
|
||||||
"string",
|
"string",
|
||||||
context.packageName)))
|
context.packageName)))
|
||||||
@@ -89,7 +72,7 @@ object IconPackChooser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelectedIconPack(iconPackIdString: String?) {
|
override fun setSelectedIconPack(iconPackIdString: String?) {
|
||||||
for (iconPack in iconPackList) {
|
for (iconPack in iconPackList) {
|
||||||
if (iconPack.id == iconPackIdString) {
|
if (iconPack.id == iconPackIdString) {
|
||||||
iconPackSelected = iconPack
|
iconPackSelected = iconPack
|
||||||
@@ -104,10 +87,10 @@ object IconPackChooser {
|
|||||||
* @param context Context to build the icon pack if not already build
|
* @param context Context to build the icon pack if not already build
|
||||||
* @return IconPack currently in usage
|
* @return IconPack currently in usage
|
||||||
*/
|
*/
|
||||||
fun getSelectedIconPack(context: Context): IconPack? {
|
override fun getSelectedIconPack(context: Context): IconPack? {
|
||||||
build(context)
|
build(context)
|
||||||
if (iconPackSelected == null) {
|
if (iconPackSelected == null) {
|
||||||
setSelectedIconPack(PreferencesUtil.getIconPackSelectedId(context))
|
setSelectedIconPack(DatabasePreferencesUtil.getIconPackSelectedId(context))
|
||||||
}
|
}
|
||||||
return iconPackSelected
|
return iconPackSelected
|
||||||
}
|
}
|
||||||
@@ -118,7 +101,7 @@ object IconPackChooser {
|
|||||||
* @param context Context to build the icon pack if not already build
|
* @param context Context to build the icon pack if not already build
|
||||||
* @return IconPack available
|
* @return IconPack available
|
||||||
*/
|
*/
|
||||||
fun getIconPackList(context: Context): List<IconPack> {
|
override fun getIconPackList(context: Context): List<IconPack> {
|
||||||
build(context)
|
build(context)
|
||||||
return iconPackList
|
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
|
package com.kunzisoft.keepass.model
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -24,9 +5,8 @@ import android.net.Uri
|
|||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility data class to get FileDatabaseInfo at a `t` time
|
* Utility data class to get FileDatabaseInfo at a `t` time
|
||||||
@@ -90,12 +70,12 @@ data class SnapFileDatabaseInfo(var fileUri: Uri?,
|
|||||||
return arrayOfNulls(size)
|
return arrayOfNulls(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromFileDatabaseInfo(fileDatabaseInfo: FileDatabaseInfo): SnapFileDatabaseInfo {
|
fun fromFileDatabaseInfo(fileDatabaseInfo: com.kunzisoft.keepass.viewmodels.FileDatabaseInfo): SnapFileDatabaseInfo {
|
||||||
return SnapFileDatabaseInfo(
|
return SnapFileDatabaseInfo(
|
||||||
fileDatabaseInfo.fileUri,
|
fileDatabaseInfo.fileUri,
|
||||||
fileDatabaseInfo.exists,
|
fileDatabaseInfo.exists,
|
||||||
fileDatabaseInfo.getLastModification(),
|
fileDatabaseInfo.getLastModification(),
|
||||||
fileDatabaseInfo.getSize())
|
fileDatabaseInfo.getSize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package com.kunzisoft.keepass.services
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.PendingIntent
|
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.net.Uri
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import com.kunzisoft.keepass.R
|
|
||||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
|
||||||
|
|
||||||
class AdvancedUnlockNotificationService : NotificationService() {
|
class AdvancedUnlockNotificationService : NotificationService() {
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun retrieveChannelName(): String {
|
override fun retrieveChannelName(): String {
|
||||||
return getString(R.string.advanced_unlock)
|
return getString(com.kunzisoft.keepass.R.string.advanced_unlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@@ -69,12 +70,12 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
val biometricUnlockEnabled = PreferencesUtil.isBiometricUnlockEnable(this)
|
val biometricUnlockEnabled = PreferencesUtil.isBiometricUnlockEnable(this)
|
||||||
val notificationBuilder = buildNewNotification().apply {
|
val notificationBuilder = buildNewNotification().apply {
|
||||||
setSmallIcon(if (biometricUnlockEnabled) {
|
setSmallIcon(if (biometricUnlockEnabled) {
|
||||||
R.drawable.notification_ic_fingerprint_unlock_24dp
|
com.kunzisoft.keepass.R.drawable.notification_ic_fingerprint_unlock_24dp
|
||||||
} else {
|
} else {
|
||||||
R.drawable.notification_ic_device_unlock_24dp
|
com.kunzisoft.keepass.R.drawable.notification_ic_device_unlock_24dp
|
||||||
})
|
})
|
||||||
setContentTitle(getString(R.string.advanced_unlock))
|
setContentTitle(getString(com.kunzisoft.keepass.R.string.advanced_unlock))
|
||||||
setContentText(getString(R.string.advanced_unlock_tap_delete))
|
setContentText(getString(com.kunzisoft.keepass.R.string.advanced_unlock_tap_delete))
|
||||||
setContentIntent(pendingDeleteIntent)
|
setContentIntent(pendingDeleteIntent)
|
||||||
// Unfortunately swipe is disabled in lollipop+
|
// Unfortunately swipe is disabled in lollipop+
|
||||||
setDeleteIntent(pendingDeleteIntent)
|
setDeleteIntent(pendingDeleteIntent)
|
||||||
@@ -82,7 +83,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
|
|
||||||
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
|
||||||
// Not necessarily a foreground service
|
// Not necessarily a foreground service
|
||||||
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
|
if (mTimerJob == null && notificationTimeoutMilliSecs != com.kunzisoft.keepass.timeout.TimeoutHelper.NEVER) {
|
||||||
defineTimerJob(notificationBuilder, notificationTimeoutMilliSecs) {
|
defineTimerJob(notificationBuilder, notificationTimeoutMilliSecs) {
|
||||||
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
// Only one service connection
|
// Only one service connection
|
||||||
fun bindService(context: Context, serviceConnection: ServiceConnection, flags: Int) {
|
fun bindService(context: Context, serviceConnection: ServiceConnection, flags: Int) {
|
||||||
context.bindService(Intent(context,
|
context.bindService(Intent(context,
|
||||||
AdvancedUnlockNotificationService::class.java),
|
AdvancedUnlockNotificationService::class.java),
|
||||||
serviceConnection,
|
serviceConnection,
|
||||||
flags)
|
flags)
|
||||||
}
|
}
|
||||||
@@ -131,4 +132,4 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
|||||||
context.unbindService(serviceConnection)
|
context.unbindService(serviceConnection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.NodeId
|
||||||
import com.kunzisoft.keepass.database.element.node.Type
|
import com.kunzisoft.keepass.database.element.node.Type
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
|
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.model.ProgressMessage
|
import com.kunzisoft.keepass.model.ProgressMessage
|
||||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
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.LOCK_ACTION
|
||||||
import com.kunzisoft.keepass.utils.closeDatabase
|
import com.kunzisoft.keepass.utils.closeDatabase
|
||||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||||
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
open class DatabaseTaskNotificationService : LockNotificationService(), ProgressTaskUpdater {
|
open class DatabaseTaskNotificationService : LockNotificationService(), ProgressTaskUpdater {
|
||||||
|
|
||||||
@@ -75,6 +76,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
private var mDatabaseInfoListeners = mutableListOf<DatabaseInfoListener>()
|
private var mDatabaseInfoListeners = mutableListOf<DatabaseInfoListener>()
|
||||||
private var mActionTaskBinder = ActionTaskBinder()
|
private var mActionTaskBinder = ActionTaskBinder()
|
||||||
private var mActionTaskListeners = mutableListOf<ActionTaskListener>()
|
private var mActionTaskListeners = mutableListOf<ActionTaskListener>()
|
||||||
|
|
||||||
// Channel to connect asynchronously a listener or a response
|
// Channel to connect asynchronously a listener or a response
|
||||||
private var mRequestChallengeListenerChannel: Channel<RequestChallengeListener>? = null
|
private var mRequestChallengeListenerChannel: Channel<RequestChallengeListener>? = null
|
||||||
private var mResponseChallengeChannel: Channel<ByteArray?>? = null
|
private var mResponseChallengeChannel: Channel<ByteArray?>? = null
|
||||||
@@ -93,7 +95,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
return getString(R.string.database)
|
return getString(R.string.database)
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ActionTaskBinder: Binder() {
|
inner class ActionTaskBinder : Binder() {
|
||||||
|
|
||||||
fun getService(): DatabaseTaskNotificationService = this@DatabaseTaskNotificationService
|
fun getService(): DatabaseTaskNotificationService = this@DatabaseTaskNotificationService
|
||||||
|
|
||||||
@@ -154,18 +156,28 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DatabaseInfoListener {
|
interface DatabaseInfoListener {
|
||||||
fun onDatabaseInfoChanged(previousDatabaseInfo: SnapFileDatabaseInfo,
|
fun onDatabaseInfoChanged(
|
||||||
newDatabaseInfo: SnapFileDatabaseInfo)
|
previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActionTaskListener {
|
interface ActionTaskListener {
|
||||||
fun onStartAction(database: Database,
|
fun onStartAction(
|
||||||
progressMessage: ProgressMessage)
|
database: Database,
|
||||||
fun onUpdateAction(database: Database,
|
progressMessage: ProgressMessage,
|
||||||
progressMessage: ProgressMessage)
|
)
|
||||||
fun onStopAction(database: Database,
|
|
||||||
actionTask: String,
|
fun onUpdateAction(
|
||||||
result: ActionRunnable.Result)
|
database: Database,
|
||||||
|
progressMessage: ProgressMessage,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun onStopAction(
|
||||||
|
database: Database,
|
||||||
|
actionTask: String,
|
||||||
|
result: ActionRunnable.Result,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RequestChallengeListener {
|
interface RequestChallengeListener {
|
||||||
@@ -183,7 +195,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
mDatabase?.fileUri?.let {
|
mDatabase?.fileUri?.let {
|
||||||
val previousDatabaseInfo = mSnapFileDatabaseInfo
|
val previousDatabaseInfo = mSnapFileDatabaseInfo
|
||||||
val lastFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
val lastFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
||||||
FileDatabaseInfo(applicationContext, it))
|
FileDatabaseInfo(applicationContext, it))
|
||||||
|
|
||||||
val oldDatabaseModification = previousDatabaseInfo?.lastModification
|
val oldDatabaseModification = previousDatabaseInfo?.lastModification
|
||||||
val newDatabaseModification = lastFileDatabaseInfo.lastModification
|
val newDatabaseModification = lastFileDatabaseInfo.lastModification
|
||||||
@@ -194,12 +206,12 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
// To prevent dialog opening too often
|
// To prevent dialog opening too often
|
||||||
// Add 10 seconds delta time to prevent spamming
|
// Add 10 seconds delta time to prevent spamming
|
||||||
val conditionLastModification =
|
val conditionLastModification =
|
||||||
(oldDatabaseModification != null && newDatabaseModification != null
|
(oldDatabaseModification != null && newDatabaseModification != null
|
||||||
&& oldDatabaseSize != null
|
&& oldDatabaseSize != null
|
||||||
&& oldDatabaseModification > 0 && newDatabaseModification > 0
|
&& oldDatabaseModification > 0 && newDatabaseModification > 0
|
||||||
&& oldDatabaseSize > 0
|
&& oldDatabaseSize > 0
|
||||||
&& oldDatabaseModification < newDatabaseModification
|
&& oldDatabaseModification < newDatabaseModification
|
||||||
&& mLastLocalSaveTime + 10000 < newDatabaseModification)
|
&& mLastLocalSaveTime + 10000 < newDatabaseModification)
|
||||||
|
|
||||||
if (conditionExists || conditionLastModification) {
|
if (conditionExists || conditionLastModification) {
|
||||||
// Show the dialog only if it's real new info and not a delay after a save
|
// Show the dialog only if it's real new info and not a delay after a save
|
||||||
@@ -208,7 +220,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
// Call listener to indicate a change in database info
|
// Call listener to indicate a change in database info
|
||||||
if (!mSaveState && previousDatabaseInfo != null) {
|
if (!mSaveState && previousDatabaseInfo != null) {
|
||||||
mDatabaseInfoListeners.forEach { listener ->
|
mDatabaseInfoListeners.forEach { listener ->
|
||||||
listener.onDatabaseInfoChanged(previousDatabaseInfo, lastFileDatabaseInfo)
|
listener.onDatabaseInfoChanged(previousDatabaseInfo,
|
||||||
|
lastFileDatabaseInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSnapFileDatabaseInfo = lastFileDatabaseInfo
|
mSnapFileDatabaseInfo = lastFileDatabaseInfo
|
||||||
@@ -223,7 +236,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
try {
|
try {
|
||||||
mDatabase?.fileUri?.let {
|
mDatabase?.fileUri?.let {
|
||||||
mSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
mSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
||||||
FileDatabaseInfo(applicationContext, it))
|
FileDatabaseInfo(applicationContext, it))
|
||||||
Log.i(TAG, "Database file saved $mSnapFileDatabaseInfo")
|
Log.i(TAG, "Database file saved $mSnapFileDatabaseInfo")
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -294,7 +307,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
super.onStartCommand(intent, flags, startId)
|
super.onStartCommand(intent, flags, startId)
|
||||||
|
|
||||||
val database = Database.getInstance()
|
val database = Database.getInstance(IconPackChooser)
|
||||||
if (mDatabase != database) {
|
if (mDatabase != database) {
|
||||||
mDatabase = database
|
mDatabase = database
|
||||||
mDatabaseListeners.forEach { listener ->
|
mDatabaseListeners.forEach { listener ->
|
||||||
@@ -323,23 +336,36 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
val actionRunnable: ActionRunnable? = when (intentAction) {
|
val actionRunnable: ActionRunnable? = when (intentAction) {
|
||||||
ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent, database)
|
ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent, database)
|
||||||
ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent, database)
|
ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent, database)
|
||||||
ACTION_DATABASE_MERGE_TASK -> buildDatabaseMergeActionTask(intent, database)
|
ACTION_DATABASE_MERGE_TASK -> buildDatabaseMergeActionTask(intent, database)
|
||||||
ACTION_DATABASE_RELOAD_TASK -> buildDatabaseReloadActionTask(database)
|
ACTION_DATABASE_RELOAD_TASK -> buildDatabaseReloadActionTask(database)
|
||||||
ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent, database)
|
ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent,
|
||||||
ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent, database)
|
database)
|
||||||
ACTION_DATABASE_UPDATE_GROUP_TASK -> buildDatabaseUpdateGroupActionTask(intent, database)
|
ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent,
|
||||||
ACTION_DATABASE_CREATE_ENTRY_TASK -> buildDatabaseCreateEntryActionTask(intent, database)
|
database)
|
||||||
ACTION_DATABASE_UPDATE_ENTRY_TASK -> buildDatabaseUpdateEntryActionTask(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_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent, database)
|
||||||
ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent, database)
|
ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent, database)
|
||||||
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent, database)
|
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent,
|
||||||
ACTION_DATABASE_RESTORE_ENTRY_HISTORY -> buildDatabaseRestoreEntryHistoryActionTask(intent, database)
|
database)
|
||||||
ACTION_DATABASE_DELETE_ENTRY_HISTORY -> buildDatabaseDeleteEntryHistoryActionTask(intent, database)
|
ACTION_DATABASE_RESTORE_ENTRY_HISTORY -> buildDatabaseRestoreEntryHistoryActionTask(
|
||||||
ACTION_DATABASE_UPDATE_COMPRESSION_TASK -> buildDatabaseUpdateCompressionActionTask(intent, database)
|
intent,
|
||||||
ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK -> buildDatabaseRemoveUnlinkedDataActionTask(intent, database)
|
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_NAME_TASK,
|
||||||
ACTION_DATABASE_UPDATE_DESCRIPTION_TASK,
|
ACTION_DATABASE_UPDATE_DESCRIPTION_TASK,
|
||||||
ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_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_KEY_DERIVATION_TASK,
|
||||||
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
||||||
ACTION_DATABASE_UPDATE_PARALLELISM_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)
|
ACTION_DATABASE_SAVE -> buildDatabaseSave(intent, database)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@@ -361,79 +388,81 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
if (actionRunnable != null) {
|
if (actionRunnable != null) {
|
||||||
mainScope.launch {
|
mainScope.launch {
|
||||||
executeAction(this@DatabaseTaskNotificationService,
|
executeAction(this@DatabaseTaskNotificationService,
|
||||||
{
|
{
|
||||||
TimeoutHelper.temporarilyDisableTimeout()
|
TimeoutHelper.temporarilyDisableTimeout()
|
||||||
|
|
||||||
mActionRunning = true
|
mActionRunning = true
|
||||||
|
|
||||||
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
|
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
|
||||||
putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId)
|
putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId)
|
||||||
putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId)
|
putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId)
|
||||||
putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId)
|
putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId)
|
||||||
})
|
})
|
||||||
|
|
||||||
mActionTaskListeners.forEach { actionTaskListener ->
|
mActionTaskListeners.forEach { actionTaskListener ->
|
||||||
actionTaskListener.onStartAction(
|
actionTaskListener.onStartAction(
|
||||||
database, mProgressMessage
|
database, mProgressMessage
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
actionRunnable
|
|
||||||
},
|
|
||||||
{ result ->
|
|
||||||
try {
|
|
||||||
mActionTaskListeners.forEach { actionTaskListener ->
|
|
||||||
mTaskRemovedRequested = false
|
|
||||||
actionTaskListener.onStopAction(database, intentAction!!, result)
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
// Save the database info before performing action
|
|
||||||
when (intentAction) {
|
|
||||||
ACTION_DATABASE_LOAD_TASK,
|
|
||||||
ACTION_DATABASE_MERGE_TASK,
|
|
||||||
ACTION_DATABASE_RELOAD_TASK -> {
|
|
||||||
saveDatabaseInfo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val save = !database.isReadOnly
|
|
||||||
&& (intentAction == ACTION_DATABASE_SAVE
|
|
||||||
|| intent?.getBooleanExtra(SAVE_DATABASE_KEY, false) == true)
|
|
||||||
// Save the database info after performing save action
|
|
||||||
if (save) {
|
|
||||||
database.fileUri?.let {
|
|
||||||
val newSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
|
||||||
FileDatabaseInfo(applicationContext, it))
|
|
||||||
mLastLocalSaveTime = System.currentTimeMillis()
|
|
||||||
mSnapFileDatabaseInfo = newSnapFileDatabaseInfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
removeIntentData(intent)
|
|
||||||
TimeoutHelper.releaseTemporarilyDisableTimeout()
|
|
||||||
// Stop service after save if user remove task
|
|
||||||
if (save && mTaskRemovedRequested) {
|
|
||||||
actionOnLock()
|
|
||||||
} else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) {
|
|
||||||
if (!database.loaded) {
|
|
||||||
stopSelf()
|
|
||||||
} else {
|
|
||||||
// Restart the service to open lock notification
|
|
||||||
try {
|
|
||||||
startService(Intent(applicationContext,
|
|
||||||
DatabaseTaskNotificationService::class.java))
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
Log.w(TAG, "Cannot restart the database task service", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mTaskRemovedRequested = false
|
|
||||||
}
|
|
||||||
|
|
||||||
sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION))
|
|
||||||
|
|
||||||
mActionRunning = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionRunnable
|
||||||
|
},
|
||||||
|
{ result ->
|
||||||
|
try {
|
||||||
|
mActionTaskListeners.forEach { actionTaskListener ->
|
||||||
|
mTaskRemovedRequested = false
|
||||||
|
actionTaskListener.onStopAction(database, intentAction!!, result)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Save the database info before performing action
|
||||||
|
when (intentAction) {
|
||||||
|
ACTION_DATABASE_LOAD_TASK,
|
||||||
|
ACTION_DATABASE_MERGE_TASK,
|
||||||
|
ACTION_DATABASE_RELOAD_TASK,
|
||||||
|
-> {
|
||||||
|
saveDatabaseInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val save = !database.isReadOnly
|
||||||
|
&& (intentAction == ACTION_DATABASE_SAVE
|
||||||
|
|| intent?.getBooleanExtra(SAVE_DATABASE_KEY, false) == true)
|
||||||
|
// Save the database info after performing save action
|
||||||
|
if (save) {
|
||||||
|
database.fileUri?.let {
|
||||||
|
val newSnapFileDatabaseInfo =
|
||||||
|
SnapFileDatabaseInfo.fromFileDatabaseInfo(
|
||||||
|
FileDatabaseInfo(applicationContext, it))
|
||||||
|
mLastLocalSaveTime = System.currentTimeMillis()
|
||||||
|
mSnapFileDatabaseInfo = newSnapFileDatabaseInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeIntentData(intent)
|
||||||
|
TimeoutHelper.releaseTemporarilyDisableTimeout()
|
||||||
|
// Stop service after save if user remove task
|
||||||
|
if (save && mTaskRemovedRequested) {
|
||||||
|
actionOnLock()
|
||||||
|
} else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) {
|
||||||
|
if (!database.loaded) {
|
||||||
|
stopSelf()
|
||||||
|
} else {
|
||||||
|
// Restart the service to open lock notification
|
||||||
|
try {
|
||||||
|
startService(Intent(applicationContext,
|
||||||
|
DatabaseTaskNotificationService::class.java))
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
Log.w(TAG, "Cannot restart the database task service", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mTaskRemovedRequested = false
|
||||||
|
}
|
||||||
|
|
||||||
|
sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION))
|
||||||
|
|
||||||
|
mActionRunning = false
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,7 +471,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
ACTION_DATABASE_LOAD_TASK,
|
ACTION_DATABASE_LOAD_TASK,
|
||||||
ACTION_DATABASE_MERGE_TASK,
|
ACTION_DATABASE_MERGE_TASK,
|
||||||
ACTION_DATABASE_RELOAD_TASK,
|
ACTION_DATABASE_RELOAD_TASK,
|
||||||
null -> {
|
null,
|
||||||
|
-> {
|
||||||
START_STICKY
|
START_STICKY
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -470,9 +500,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
||||||
ACTION_DATABASE_LOAD_TASK,
|
ACTION_DATABASE_LOAD_TASK,
|
||||||
ACTION_DATABASE_MERGE_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_ASSIGN_PASSWORD_TASK,
|
||||||
ACTION_DATABASE_SAVE -> R.string.saving_database
|
ACTION_DATABASE_SAVE,
|
||||||
|
-> R.string.saving_database
|
||||||
else -> {
|
else -> {
|
||||||
if (mSaveState)
|
if (mSaveState)
|
||||||
R.string.saving_database
|
R.string.saving_database
|
||||||
@@ -486,12 +518,12 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
|
|
||||||
// Warning if data is saved
|
// Warning if data is saved
|
||||||
mProgressMessage.warningId =
|
mProgressMessage.warningId =
|
||||||
if (mSaveState)
|
if (mSaveState)
|
||||||
R.string.do_not_kill_app
|
R.string.do_not_kill_app
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
|
|
||||||
val notificationBuilder = buildNewNotification().apply {
|
val notificationBuilder = buildNewNotification().apply {
|
||||||
setSmallIcon(iconId)
|
setSmallIcon(iconId)
|
||||||
intent?.let {
|
intent?.let {
|
||||||
setContentTitle(getString(
|
setContentTitle(getString(
|
||||||
@@ -582,11 +614,13 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute action with a coroutine
|
* Execute action with a coroutine
|
||||||
*/
|
*/
|
||||||
private suspend fun executeAction(progressTaskUpdater: ProgressTaskUpdater,
|
private suspend fun executeAction(
|
||||||
onPreExecute: () -> Unit,
|
progressTaskUpdater: ProgressTaskUpdater,
|
||||||
onExecute: (ProgressTaskUpdater?) -> ActionRunnable?,
|
onPreExecute: () -> Unit,
|
||||||
onPostExecute: (result: ActionRunnable.Result) -> Unit) {
|
onExecute: (ProgressTaskUpdater?) -> ActionRunnable?,
|
||||||
|
onPostExecute: (result: ActionRunnable.Result) -> Unit,
|
||||||
|
) {
|
||||||
onPreExecute.invoke()
|
onPreExecute.invoke()
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
onExecute.invoke(progressTaskUpdater)?.apply {
|
onExecute.invoke(progressTaskUpdater)?.apply {
|
||||||
@@ -634,8 +668,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
super.onTaskRemoved(rootIntent)
|
super.onTaskRemoved(rootIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun retrieveResponseFromChallenge(hardwareKey: HardwareKey,
|
private fun retrieveResponseFromChallenge(
|
||||||
seed: ByteArray?): ByteArray {
|
hardwareKey: HardwareKey,
|
||||||
|
seed: ByteArray?,
|
||||||
|
): ByteArray {
|
||||||
// Request a challenge - response
|
// Request a challenge - response
|
||||||
var response: ByteArray
|
var response: ByteArray
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@@ -670,10 +706,11 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
private fun buildDatabaseCreateActionTask(intent: Intent, database: Database): ActionRunnable? {
|
private fun buildDatabaseCreateActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||||
|
|
||||||
if (intent.hasExtra(DATABASE_URI_KEY)
|
if (intent.hasExtra(DATABASE_URI_KEY)
|
||||||
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
||||||
) {
|
) {
|
||||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_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)
|
if (databaseUri == null)
|
||||||
return null
|
return null
|
||||||
@@ -702,18 +739,20 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
private fun buildDatabaseLoadActionTask(intent: Intent, database: Database): ActionRunnable? {
|
private fun buildDatabaseLoadActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||||
|
|
||||||
if (intent.hasExtra(DATABASE_URI_KEY)
|
if (intent.hasExtra(DATABASE_URI_KEY)
|
||||||
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
||||||
&& intent.hasExtra(READ_ONLY_KEY)
|
&& intent.hasExtra(READ_ONLY_KEY)
|
||||||
&& intent.hasExtra(CIPHER_DATABASE_KEY)
|
&& intent.hasExtra(CIPHER_DATABASE_KEY)
|
||||||
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
|
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
|
||||||
) {
|
) {
|
||||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_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 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)
|
if (databaseUri == null)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return LoadDatabaseRunnable(
|
return LoadDatabaseRunnable(
|
||||||
this,
|
this,
|
||||||
@@ -768,18 +807,21 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
|
|
||||||
private fun buildDatabaseReloadActionTask(database: Database): ActionRunnable {
|
private fun buildDatabaseReloadActionTask(database: Database): ActionRunnable {
|
||||||
return ReloadDatabaseRunnable(
|
return ReloadDatabaseRunnable(
|
||||||
this,
|
this,
|
||||||
database,
|
database,
|
||||||
this
|
this
|
||||||
) { result ->
|
) { result ->
|
||||||
// No need to add each info to reload database
|
// No need to add each info to reload database
|
||||||
result.data = Bundle()
|
result.data = Bundle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDatabaseAssignPasswordActionTask(intent: Intent, database: Database): ActionRunnable? {
|
private fun buildDatabaseAssignPasswordActionTask(
|
||||||
|
intent: Intent,
|
||||||
|
database: Database,
|
||||||
|
): ActionRunnable? {
|
||||||
return if (intent.hasExtra(DATABASE_URI_KEY)
|
return if (intent.hasExtra(DATABASE_URI_KEY)
|
||||||
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
&& intent.hasExtra(MAIN_CREDENTIAL_KEY)
|
||||||
) {
|
) {
|
||||||
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) ?: return null
|
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) ?: return null
|
||||||
AssignMainCredentialInDatabaseRunnable(this,
|
AssignMainCredentialInDatabaseRunnable(this,
|
||||||
@@ -795,8 +837,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class AfterActionNodesRunnable : AfterActionNodesFinish() {
|
private inner class AfterActionNodesRunnable : AfterActionNodesFinish() {
|
||||||
override fun onActionNodesFinish(result: ActionRunnable.Result,
|
override fun onActionNodesFinish(
|
||||||
actionNodesValues: ActionNodesValues) {
|
result: ActionRunnable.Result,
|
||||||
|
actionNodesValues: ActionNodesValues,
|
||||||
|
) {
|
||||||
val bundle = result.data ?: Bundle()
|
val bundle = result.data ?: Bundle()
|
||||||
bundle.putBundle(OLD_NODES_KEY, getBundleFromListNodes(actionNodesValues.oldNodes))
|
bundle.putBundle(OLD_NODES_KEY, getBundleFromListNodes(actionNodesValues.oldNodes))
|
||||||
bundle.putBundle(NEW_NODES_KEY, getBundleFromListNodes(actionNodesValues.newNodes))
|
bundle.putBundle(NEW_NODES_KEY, getBundleFromListNodes(actionNodesValues.newNodes))
|
||||||
@@ -804,16 +848,20 @@ 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)
|
return if (intent.hasExtra(GROUP_KEY)
|
||||||
&& intent.hasExtra(PARENT_ID_KEY)
|
&& intent.hasExtra(PARENT_ID_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
|
val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
|
||||||
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
||||||
|
|
||||||
if (parentId == null
|
if (parentId == null
|
||||||
|| newGroup == null)
|
|| newGroup == null
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
database.getGroupById(parentId)?.let { parent ->
|
database.getGroupById(parentId)?.let { parent ->
|
||||||
@@ -832,16 +880,20 @@ 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)
|
return if (intent.hasExtra(GROUP_ID_KEY)
|
||||||
&& intent.hasExtra(GROUP_KEY)
|
&& intent.hasExtra(GROUP_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val groupId: NodeId<*>? = intent.getParcelableExtra(GROUP_ID_KEY)
|
val groupId: NodeId<*>? = intent.getParcelableExtra(GROUP_ID_KEY)
|
||||||
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
|
||||||
|
|
||||||
if (groupId == null
|
if (groupId == null
|
||||||
|| newGroup == null)
|
|| newGroup == null
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
database.getGroupById(groupId)?.let { oldGroup ->
|
database.getGroupById(groupId)?.let { oldGroup ->
|
||||||
@@ -860,16 +912,20 @@ 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)
|
return if (intent.hasExtra(ENTRY_KEY)
|
||||||
&& intent.hasExtra(PARENT_ID_KEY)
|
&& intent.hasExtra(PARENT_ID_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
|
val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
|
||||||
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
||||||
|
|
||||||
if (parentId == null
|
if (parentId == null
|
||||||
|| newEntry == null)
|
|| newEntry == null
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
database.getGroupById(parentId)?.let { parent ->
|
database.getGroupById(parentId)?.let { parent ->
|
||||||
@@ -888,16 +944,20 @@ 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)
|
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRY_KEY)
|
&& intent.hasExtra(ENTRY_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val entryId: NodeId<UUID>? = intent.getParcelableExtra(ENTRY_ID_KEY)
|
val entryId: NodeId<UUID>? = intent.getParcelableExtra(ENTRY_ID_KEY)
|
||||||
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
|
||||||
|
|
||||||
if (entryId == null
|
if (entryId == null
|
||||||
|| newEntry == null)
|
|| newEntry == null
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
database.getEntryById(entryId)?.let { oldEntry ->
|
database.getEntryById(entryId)?.let { oldEntry ->
|
||||||
@@ -916,11 +976,14 @@ 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)
|
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||||
&& intent.hasExtra(PARENT_ID_KEY)
|
&& intent.hasExtra(PARENT_ID_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
|
val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
|
||||||
|
|
||||||
@@ -940,11 +1003,14 @@ 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)
|
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||||
&& intent.hasExtra(PARENT_ID_KEY)
|
&& intent.hasExtra(PARENT_ID_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
|
val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
|
||||||
|
|
||||||
@@ -964,28 +1030,34 @@ 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)
|
return if (intent.hasExtra(GROUPS_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRIES_ID_KEY)
|
&& intent.hasExtra(ENTRIES_ID_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
DeleteNodesRunnable(this,
|
DeleteNodesRunnable(this,
|
||||||
database,
|
database,
|
||||||
getListNodesFromBundle(database, intent.extras!!),
|
getListNodesFromBundle(database, intent.extras!!),
|
||||||
!database.isReadOnly && intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
|
!database.isReadOnly && intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
|
||||||
AfterActionNodesRunnable()
|
AfterActionNodesRunnable()
|
||||||
) { hardwareKey, seed ->
|
) { hardwareKey, seed ->
|
||||||
retrieveResponseFromChallenge(hardwareKey, seed)
|
retrieveResponseFromChallenge(hardwareKey, seed)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDatabaseRestoreEntryHistoryActionTask(intent: Intent, database: Database): ActionRunnable? {
|
private fun buildDatabaseRestoreEntryHistoryActionTask(
|
||||||
|
intent: Intent,
|
||||||
|
database: Database,
|
||||||
|
): ActionRunnable? {
|
||||||
return if (intent.hasExtra(ENTRY_ID_KEY)
|
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
|
val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
|
||||||
|
|
||||||
@@ -1004,10 +1076,13 @@ 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)
|
return if (intent.hasExtra(ENTRY_ID_KEY)
|
||||||
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
&& intent.hasExtra(ENTRY_HISTORY_POSITION_KEY)
|
||||||
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
&& intent.hasExtra(SAVE_DATABASE_KEY)
|
||||||
) {
|
) {
|
||||||
val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
|
val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
|
||||||
|
|
||||||
@@ -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)
|
return if (intent.hasExtra(OLD_ELEMENT_KEY)
|
||||||
&& intent.hasExtra(NEW_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 oldElement: CompressionAlgorithm? = intent.getParcelableExtra(OLD_ELEMENT_KEY)
|
||||||
val newElement: CompressionAlgorithm? = intent.getParcelableExtra(NEW_ELEMENT_KEY)
|
val newElement: CompressionAlgorithm? = intent.getParcelableExtra(NEW_ELEMENT_KEY)
|
||||||
|
|
||||||
if (oldElement == null
|
if (oldElement == null
|
||||||
|| newElement == null)
|
|| newElement == null
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return UpdateCompressionBinariesDatabaseRunnable(this,
|
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 if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||||
|
|
||||||
return RemoveUnlinkedDataDatabaseRunnable(this,
|
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 if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||||
return SaveDatabaseRunnable(this,
|
return SaveDatabaseRunnable(this,
|
||||||
database,
|
database,
|
||||||
@@ -1120,7 +1206,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
|
|
||||||
private val TAG = DatabaseTaskNotificationService::class.java.name
|
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_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK"
|
||||||
const val ACTION_DATABASE_LOAD_TASK = "ACTION_DATABASE_LOAD_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_RESTORE_ENTRY_HISTORY = "ACTION_DATABASE_RESTORE_ENTRY_HISTORY"
|
||||||
const val ACTION_DATABASE_DELETE_ENTRY_HISTORY = "ACTION_DATABASE_DELETE_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_NAME_TASK = "ACTION_DATABASE_UPDATE_NAME_TASK"
|
||||||
const val ACTION_DATABASE_UPDATE_DESCRIPTION_TASK = "ACTION_DATABASE_UPDATE_DESCRIPTION_TASK"
|
const val ACTION_DATABASE_UPDATE_DESCRIPTION_TASK =
|
||||||
const val ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK = "ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_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_COLOR_TASK = "ACTION_DATABASE_UPDATE_COLOR_TASK"
|
||||||
const val ACTION_DATABASE_UPDATE_COMPRESSION_TASK = "ACTION_DATABASE_UPDATE_COMPRESSION_TASK"
|
const val ACTION_DATABASE_UPDATE_COMPRESSION_TASK =
|
||||||
const val ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK = "ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK"
|
"ACTION_DATABASE_UPDATE_COMPRESSION_TASK"
|
||||||
const val ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK = "ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK"
|
const val ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK =
|
||||||
const val ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK = "ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK"
|
"ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK"
|
||||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK"
|
const val ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK =
|
||||||
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_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_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_KEY_DERIVATION_TASK =
|
||||||
const val ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK = "ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK"
|
"ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK"
|
||||||
const val ACTION_DATABASE_UPDATE_PARALLELISM_TASK = "ACTION_DATABASE_UPDATE_PARALLELISM_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_UPDATE_ITERATIONS_TASK = "ACTION_DATABASE_UPDATE_ITERATIONS_TASK"
|
||||||
const val ACTION_DATABASE_SAVE = "ACTION_DATABASE_SAVE"
|
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 SAVE_DATABASE_KEY = "SAVE_DATABASE_KEY"
|
||||||
const val OLD_NODES_KEY = "OLD_NODES_KEY"
|
const val OLD_NODES_KEY = "OLD_NODES_KEY"
|
||||||
const val NEW_NODES_KEY = "NEW_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 OLD_ELEMENT_KEY =
|
||||||
const val NEW_ELEMENT_KEY = "NEW_ELEMENT_KEY" // Warning type of this thing change every time
|
"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> {
|
fun getListNodesFromBundle(database: Database, bundle: Bundle): List<Node> {
|
||||||
val nodesAction = ArrayList<Node>()
|
val nodesAction = ArrayList<Node>()
|
||||||
@@ -1211,4 +1311,4 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
package com.kunzisoft.keepass.settings
|
||||||
|
|
||||||
import android.app.backup.BackupManager
|
import android.app.backup.BackupManager
|
||||||
@@ -26,18 +7,18 @@ import android.content.res.Resources
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.kunzisoft.keepass.BuildConfig
|
|
||||||
import com.kunzisoft.keepass.R
|
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.element.SortNodeEnum
|
||||||
import com.kunzisoft.keepass.database.search.SearchParameters
|
import com.kunzisoft.keepass.database.search.SearchParameters
|
||||||
import com.kunzisoft.keepass.education.Education
|
import com.kunzisoft.keepass.education.Education
|
||||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
import java.util.HashSet
|
||||||
import com.kunzisoft.keepass.password.PassphraseGenerator
|
import java.util.Properties
|
||||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.APP_TIMEOUT_KEY
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil.HIDE_EXPIRED_ENTRIES_KEY
|
||||||
import java.util.*
|
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 {
|
object PreferencesUtil {
|
||||||
|
|
||||||
@@ -61,7 +42,8 @@ object PreferencesUtil {
|
|||||||
|
|
||||||
fun saveNodeSort(context: Context,
|
fun saveNodeSort(context: Context,
|
||||||
sortNodeEnum: SortNodeEnum,
|
sortNodeEnum: SortNodeEnum,
|
||||||
sortNodeParameters: SortNodeEnum.SortNodeParameters) {
|
sortNodeParameters: SortNodeEnum.SortNodeParameters
|
||||||
|
) {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
prefs?.edit()?.apply {
|
prefs?.edit()?.apply {
|
||||||
putString(context.getString(R.string.sort_node_key), sortNodeEnum.name)
|
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))
|
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 {
|
fun showEntryColors(context: Context): Boolean {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.show_entry_colors_key),
|
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))
|
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 {
|
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)
|
val styleString = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getString(context.getString(R.string.setting_style_key), defaultStyleString)
|
.getString(context.getString(R.string.setting_style_key), defaultStyleString)
|
||||||
?: defaultStyleString
|
?: defaultStyleString
|
||||||
// Return the system style
|
// 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) {
|
fun setStyle(context: Context, styleString: String) {
|
||||||
var tempThemeString = styleString
|
var tempThemeString = styleString
|
||||||
if (!UriUtil.contributingUser(context)) {
|
if (!com.kunzisoft.keepass.utils.UriUtil.contributingUser(context)) {
|
||||||
if (tempThemeString in BuildConfig.STYLES_DISABLED) {
|
if (tempThemeString in com.kunzisoft.keepass.BuildConfig.STYLES_DISABLED) {
|
||||||
tempThemeString = Stylish.defaultStyle(context)
|
tempThemeString =
|
||||||
|
com.kunzisoft.keepass.activities.stylish.Stylish.defaultStyle(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Store light style to show selection in array list
|
// 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)
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.edit()
|
.edit()
|
||||||
.putString(context.getString(R.string.setting_style_key), tempThemeString)
|
.putString(context.getString(R.string.setting_style_key), tempThemeString)
|
||||||
.apply()
|
.apply()
|
||||||
Stylish.load(context)
|
com.kunzisoft.keepass.activities.stylish.Stylish.load(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStyleBrightness(context: Context): String? {
|
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)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return PassphraseGenerator.WordCase
|
return com.kunzisoft.keepass.password.PassphraseGenerator.WordCase.Companion.getByOrdinal(
|
||||||
.getByOrdinal(prefs.getInt(context
|
prefs.getInt(context
|
||||||
.getString(R.string.passphrase_generator_word_case_key),
|
.getString(R.string.passphrase_generator_word_case_key),
|
||||||
0)
|
0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDefaultPassphraseWordCase(context: Context, wordCase: PassphraseGenerator.WordCase) {
|
fun setDefaultPassphraseWordCase(context: Context, wordCase: com.kunzisoft.keepass.password.PassphraseGenerator.WordCase) {
|
||||||
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
||||||
putInt(
|
putInt(
|
||||||
context.getString(R.string.passphrase_generator_word_case_key),
|
context.getString(R.string.passphrase_generator_word_case_key),
|
||||||
@@ -414,45 +390,23 @@ object PreferencesUtil {
|
|||||||
*/
|
*/
|
||||||
fun saveCurrentTime(context: Context) {
|
fun saveCurrentTime(context: Context) {
|
||||||
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
|
||||||
putLong(context.getString(R.string.timeout_backup_key), System.currentTimeMillis())
|
putLong(TIMEOUT_BACKUP_KEY, System.currentTimeMillis())
|
||||||
apply()
|
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 {
|
fun getClipboardTimeout(context: Context): Long {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getString(context.getString(R.string.clipboard_timeout_key),
|
return prefs.getString(context.getString(R.string.clipboard_timeout_key),
|
||||||
context.getString(R.string.clipboard_timeout_default))?.toLong()
|
TIMEOUT_DEFAULT)?.toLong()
|
||||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
?: com.kunzisoft.keepass.timeout.TimeoutHelper.DEFAULT_TIMEOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAdvancedUnlockTimeout(context: Context): Long {
|
fun getAdvancedUnlockTimeout(context: Context): Long {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getString(context.getString(R.string.temp_advanced_unlock_timeout_key),
|
return prefs.getString(context.getString(R.string.temp_advanced_unlock_timeout_key),
|
||||||
context.getString(R.string.temp_advanced_unlock_timeout_default))?.toLong()
|
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 {
|
fun isLockDatabaseWhenScreenShutOffEnable(context: Context): Boolean {
|
||||||
@@ -500,7 +454,8 @@ object PreferencesUtil {
|
|||||||
return prefs.getBoolean(context.getString(R.string.biometric_unlock_enable_key),
|
return prefs.getBoolean(context.getString(R.string.biometric_unlock_enable_key),
|
||||||
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
|
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
|
||||||
&& (if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
&& (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 {
|
} else {
|
||||||
false
|
false
|
||||||
})
|
})
|
||||||
@@ -593,13 +548,6 @@ object PreferencesUtil {
|
|||||||
.apply()
|
.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 {
|
fun emptyPasswordAllowed(context: Context): Boolean {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.allow_no_password_key),
|
return prefs.getBoolean(context.getString(R.string.allow_no_password_key),
|
||||||
@@ -631,7 +579,9 @@ object PreferencesUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isKeyboardSaveSearchInfoEnable(context: Context): Boolean {
|
fun isKeyboardSaveSearchInfoEnable(context: Context): Boolean {
|
||||||
if (!MagikeyboardService.activatedInSettings(context))
|
if (!com.kunzisoft.keepass.magikeyboard.MagikeyboardService.Companion.activatedInSettings(
|
||||||
|
context)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.keyboard_save_search_info_key),
|
return prefs.getBoolean(context.getString(R.string.keyboard_save_search_info_key),
|
||||||
@@ -716,7 +666,7 @@ object PreferencesUtil {
|
|||||||
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
|
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
|
||||||
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
|
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
|
||||||
?.toMutableSet()?.apply {
|
?.toMutableSet()?.apply {
|
||||||
add(BuildConfig.APPLICATION_ID)
|
add(com.kunzisoft.keepass.BuildConfig.APPLICATION_ID)
|
||||||
} ?: emptySet()
|
} ?: emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,10 +704,12 @@ object PreferencesUtil {
|
|||||||
|
|
||||||
fun getAppProperties(context: Context): Properties {
|
fun getAppProperties(context: Context): Properties {
|
||||||
val properties = Properties()
|
val properties = Properties()
|
||||||
for ((name, value) in PreferenceManager.getDefaultSharedPreferences(context).all) {
|
for ((name, value) in PreferenceManager.getDefaultSharedPreferences(
|
||||||
|
context).all) {
|
||||||
properties[name] = value.toString()
|
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()
|
properties[name] = value.toString()
|
||||||
}
|
}
|
||||||
return properties
|
return properties
|
||||||
@@ -780,7 +732,9 @@ object PreferencesUtil {
|
|||||||
try {
|
try {
|
||||||
putProperty(this, name as String, value as String)
|
putProperty(this, name as String, value as String)
|
||||||
} catch (e:Exception) {
|
} 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()
|
}.apply()
|
||||||
@@ -788,7 +742,7 @@ object PreferencesUtil {
|
|||||||
|
|
||||||
fun setAppProperties(context: Context, properties: Properties) {
|
fun setAppProperties(context: Context, properties: Properties) {
|
||||||
putPropertiesInPreferences(properties,
|
putPropertiesInPreferences(properties,
|
||||||
PreferenceManager.getDefaultSharedPreferences(context)) { editor, name, value ->
|
PreferenceManager.getDefaultSharedPreferences(context)) { editor, name, value ->
|
||||||
when (name) {
|
when (name) {
|
||||||
context.getString(R.string.allow_no_password_key) -> editor.putBoolean(name, value.toBoolean())
|
context.getString(R.string.allow_no_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.delete_entered_password_key) -> editor.putBoolean(name, value.toBoolean())
|
context.getString(R.string.delete_entered_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
@@ -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_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.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.auto_focus_search_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.subdomain_search_key) -> editor.putBoolean(name, value.toBoolean())
|
SUBDOMAIN_SEARCH_KEY -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.app_timeout_key) -> editor.putString(name, value.toLong().toString())
|
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_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_back_root_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.lock_database_show_button_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_key) -> setStyle(context, value)
|
||||||
context.getString(R.string.setting_style_brightness_key) -> editor.putString(name, 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.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.hide_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.colorize_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.show_uuid_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
context.getString(R.string.list_size_key) -> editor.putString(name, value)
|
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.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.enable_education_screens_key) -> editor.putBoolean(name, value.toBoolean())
|
||||||
|
|
||||||
context.getString(R.string.password_generator_length_key) -> editor.putInt(name, value.toInt())
|
context.getString(R.string.password_generator_length_key) -> editor.putInt(name, value.toInt())
|
||||||
@@ -869,8 +823,13 @@ object PreferencesUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
putPropertiesInPreferences(properties,
|
putPropertiesInPreferences(properties,
|
||||||
Education.getEducationSharedPreferences(context)) { editor, name, value ->
|
Education.getEducationSharedPreferences(
|
||||||
Education.putPropertiesInEducationPreferences(context, editor, name, value)
|
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_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 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 REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD"
|
||||||
const val BACK_PREVIOUS_KEYBOARD_ACTION = "com.kunzisoft.keepass.BACK_PREVIOUS_KEYBOARD"
|
const val BACK_PREVIOUS_KEYBOARD_ACTION = "com.kunzisoft.keepass.BACK_PREVIOUS_KEYBOARD"
|
||||||
|
|
||||||
@@ -165,4 +164,4 @@ fun Context.closeDatabase(database: Database?) {
|
|||||||
|
|
||||||
// Release not useful URI permission
|
// Release not useful URI permission
|
||||||
UriUtil.releaseAllUnnecessaryPermissionUris(applicationContext)
|
UriUtil.releaseAllUnnecessaryPermissionUris(applicationContext)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.utils
|
package com.kunzisoft.keepass.utils
|
||||||
|
|
||||||
open class SingletonHolderParameter<out T, in A>(private val constructor: (A) -> T) {
|
open class SingletonHolderParameter<out T, in A>(private val constructor: (A) -> T) {
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var instance: T? = null
|
private var instance: T? = null
|
||||||
|
|
||||||
fun getInstance(arg: A): T {
|
fun getInstance(arg: A): T {
|
||||||
return when {
|
return when {
|
||||||
instance != null -> instance!!
|
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
|
package com.kunzisoft.keepass.viewmodels
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import androidx.documentfile.provider.DocumentFile
|
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
class FileDatabaseInfo : Serializable {
|
class FileDatabaseInfo : Serializable {
|
||||||
|
|
||||||
private var context: Context
|
private var context: Context
|
||||||
private var documentFile: DocumentFile? = null
|
private var documentFile: androidx.documentfile.provider.DocumentFile? = null
|
||||||
var fileUri: Uri?
|
var fileUri: Uri?
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@@ -43,16 +22,16 @@ class FileDatabaseInfo : Serializable {
|
|||||||
|
|
||||||
constructor(context: Context, filePath: String) {
|
constructor(context: Context, filePath: String) {
|
||||||
this.context = context
|
this.context = context
|
||||||
this.fileUri = UriUtil.parse(filePath)
|
this.fileUri = com.kunzisoft.keepass.utils.UriUtil.parse(filePath)
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
// Check permission
|
// Check permission
|
||||||
fileUri?.let { uri ->
|
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
|
var exists: Boolean = false
|
||||||
@@ -92,4 +71,4 @@ class FileDatabaseInfo : Serializable {
|
|||||||
else -> if (exists) documentFile?.name else fileUri?.path
|
else -> if (exists) documentFile?.name else fileUri?.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,9 @@
|
|||||||
<dimen name="card_view_margin_vertical">5dp</dimen>
|
<dimen name="card_view_margin_vertical">5dp</dimen>
|
||||||
<dimen name="card_view_padding">14dp</dimen>
|
<dimen name="card_view_padding">14dp</dimen>
|
||||||
<dimen name="item_file_info_height">148dp</dimen>
|
<dimen name="item_file_info_height">148dp</dimen>
|
||||||
<dimen name="icon_size">32dp</dimen>
|
|
||||||
<dimen name="lock_button_size">48dp</dimen>
|
<dimen name="lock_button_size">48dp</dimen>
|
||||||
<dimen name="hidden_lock_button_size">0dp</dimen>
|
<dimen name="hidden_lock_button_size">0dp</dimen>
|
||||||
<dimen name="content_percent">1</dimen>
|
<dimen name="content_percent">1</dimen>
|
||||||
<dimen name="toolbar_parallax_height">160dp</dimen>
|
<dimen name="toolbar_parallax_height">160dp</dimen>
|
||||||
<integer name="animation_duration">260</integer>
|
<integer name="animation_duration">260</integer>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -78,12 +78,10 @@
|
|||||||
<string name="content_description_remove_from_list">Remove</string>
|
<string name="content_description_remove_from_list">Remove</string>
|
||||||
<string name="content_description_keyboard_close_fields">Close fields</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="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_request">Waiting for the challenge request…</string>
|
||||||
<string name="waiting_challenge_response">Waiting for the challenge response…</string>
|
<string name="waiting_challenge_response">Waiting for the challenge response…</string>
|
||||||
<string name="database">Database</string>
|
<string name="database">Database</string>
|
||||||
<string name="template_group_name">Templates</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="default_checkbox">Use as default database</string>
|
||||||
<string name="digits">Digits</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>.
|
<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="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_accessed">Accessed</string>
|
||||||
<string name="entry_cancel">Cancel</string>
|
<string name="entry_cancel">Cancel</string>
|
||||||
<string name="entry_notes">Notes</string>
|
|
||||||
<string name="entry_confpassword">Confirm password</string>
|
<string name="entry_confpassword">Confirm password</string>
|
||||||
<string name="entry_created">Created</string>
|
<string name="entry_created">Created</string>
|
||||||
<string name="entry_expires">Expires</string>
|
|
||||||
<string name="expired">Expired</string>
|
<string name="expired">Expired</string>
|
||||||
<string name="entry_UUID">UUID</string>
|
<string name="entry_UUID">UUID</string>
|
||||||
<string name="entry_history">History</string>
|
<string name="entry_history">History</string>
|
||||||
@@ -108,11 +104,9 @@
|
|||||||
<string name="auto_type">Auto-Type</string>
|
<string name="auto_type">Auto-Type</string>
|
||||||
<string name="auto_type_sequence">Auto-Type sequence</string>
|
<string name="auto_type_sequence">Auto-Type sequence</string>
|
||||||
<string name="entry_not_found">Could not find entry data.</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="tags">Tags</string>
|
||||||
<string name="custom_data">Custom data</string>
|
<string name="custom_data">Custom data</string>
|
||||||
<string name="save">Save</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="entry_setup_otp">Set up one-time password</string>
|
||||||
<string name="otp_type">OTP type</string>
|
<string name="otp_type">OTP type</string>
|
||||||
<string name="otp_secret">Secret</string>
|
<string name="otp_secret">Secret</string>
|
||||||
@@ -124,38 +118,8 @@
|
|||||||
<string name="current_group">Current group</string>
|
<string name="current_group">Current group</string>
|
||||||
<string name="case_sensitive">Case sensitive</string>
|
<string name="case_sensitive">Case sensitive</string>
|
||||||
<string name="regex">Regular expression</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_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_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_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_can_not_handle_uri">Could not handle this URI in KeePassDX.</string>
|
||||||
<string name="error_file_not_create">Could not create file</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_word_reserved">This word is reserved and cannot be used.</string>
|
||||||
<string name="error_nokeyfile">Select a keyfile.</string>
|
<string name="error_nokeyfile">Select a keyfile.</string>
|
||||||
<string name="error_no_hardware_key">Select a hardware key.</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_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_disallow_no_credentials">At least one credential must be set.</string>
|
||||||
<string name="error_pass_match">The passwords do not match.</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_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_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_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">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_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_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_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>
|
<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_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_cancel_by_user">Cancelled by user.</string>
|
||||||
<string name="error_driver_required">Driver for %1$s is required.</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_name">Field name</string>
|
||||||
<string name="field_value">Field value</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="file_browser">File manager</string>
|
||||||
<string name="generate_password">Generate password</string>
|
<string name="generate_password">Generate password</string>
|
||||||
<string name="hint_conf_pass">Confirm password</string>
|
<string name="hint_conf_pass">Confirm password</string>
|
||||||
@@ -224,10 +173,6 @@
|
|||||||
<string name="hint_pass">Password</string>
|
<string name="hint_pass">Password</string>
|
||||||
<string name="password">Password</string>
|
<string name="password">Password</string>
|
||||||
<string name="passphrase">Passphrase</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="keyfile_is_empty">The keyfile is empty.</string>
|
||||||
<string name="length">Length</string>
|
<string name="length">Length</string>
|
||||||
<string name="hide_password_title">Hide passwords</string>
|
<string name="hide_password_title">Hide passwords</string>
|
||||||
@@ -349,7 +294,6 @@
|
|||||||
<string name="special">Special</string>
|
<string name="special">Special</string>
|
||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
<string name="underline">Underline</string>
|
<string name="underline">Underline</string>
|
||||||
<string name="unsupported_db_version">Unsupported database version.</string>
|
|
||||||
<string name="uppercase">Upper-case</string>
|
<string name="uppercase">Upper-case</string>
|
||||||
<string name="warning">Warning</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>
|
<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="application_appearance">Interface</string>
|
||||||
<string name="other">Other</string>
|
<string name="other">Other</string>
|
||||||
<string name="compression">Compression</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="keyboard">Keyboard</string>
|
||||||
<string name="magic_keyboard_title">Magikeyboard</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>
|
<string name="magic_keyboard_explanation_summary">Activate a custom keyboard populating your passwords and all identity fields</string>
|
||||||
@@ -702,4 +642,4 @@
|
|||||||
<string name="show_entry_colors_summary">Displays foreground and background colors for an entry</string>
|
<string name="show_entry_colors_summary">Displays foreground and background colors for an entry</string>
|
||||||
<string name="hide_expired_entries_title">Hide expired entries</string>
|
<string name="hide_expired_entries_title">Hide expired entries</string>
|
||||||
<string name="hide_expired_entries_summary">Expired entries are not shown</string>
|
<string name="hide_expired_entries_summary">Expired entries are not shown</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
plugins {
|
apply plugin: 'com.android.library'
|
||||||
id 'com.android.library'
|
apply plugin: 'kotlin-android'
|
||||||
id 'org.jetbrains.kotlin.android'
|
apply plugin: 'kotlin-parcelize'
|
||||||
}
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 32
|
compileSdkVersion 32
|
||||||
@@ -16,6 +16,13 @@ android {
|
|||||||
consumerProguardFiles "consumer-rules.pro"
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
|
||||||
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
|
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
arguments {
|
||||||
|
arg("room.incremental", "true")
|
||||||
|
arg("room.schemaLocation", "$projectDir/schemas".toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -33,6 +40,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def room_version = "2.4.3"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "androidx.core:core-ktx:$android_core_version"
|
implementation "androidx.core:core-ktx:$android_core_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
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-classic')
|
||||||
implementation project(path: ':icon-pack-material')
|
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')
|
implementation project(path: ':crypto')
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
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.element.binary.BinaryData
|
||||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
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.ActionRunnable
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class MergeDatabaseRunnable(private val context: Context,
|
|||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
// Register the current time to init the lock timer
|
// Register the current time to init the lock timer
|
||||||
PreferencesUtil.saveCurrentTime(context)
|
DatabasePreferencesUtil.saveCurrentTime(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,37 +23,39 @@ import android.content.Context
|
|||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
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.ActionRunnable
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
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 mDatabase: Database,
|
private val context: Context,
|
||||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
private val mDatabase: Database,
|
||||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||||
: ActionRunnable() {
|
private val mLoadDatabaseResult: ((Result) -> Unit)?,
|
||||||
|
) : ActionRunnable() {
|
||||||
|
|
||||||
override fun onStartRun() {
|
override fun onStartRun() {
|
||||||
// Clear before we load
|
// Clear before we load
|
||||||
mDatabase.clearIndexesAndBinaries(UriUtil.getBinaryDir(context))
|
mDatabase.clearIndexesAndBinaries(UriUtilDatabase.getBinaryDir(
|
||||||
|
context))
|
||||||
mDatabase.wasReloaded = true
|
mDatabase.wasReloaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionRun() {
|
override fun onActionRun() {
|
||||||
try {
|
try {
|
||||||
mDatabase.reloadData(context.contentResolver,
|
mDatabase.reloadData(context.contentResolver,
|
||||||
{ memoryWanted ->
|
{ memoryWanted ->
|
||||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||||
},
|
},
|
||||||
progressTaskUpdater)
|
progressTaskUpdater)
|
||||||
} catch (e: DatabaseException) {
|
} catch (e: DatabaseException) {
|
||||||
setError(e)
|
setError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
// Register the current time to init the lock timer
|
// Register the current time to init the lock timer
|
||||||
PreferencesUtil.saveCurrentTime(context)
|
DatabasePreferencesUtil.saveCurrentTime(context)
|
||||||
} else {
|
} else {
|
||||||
mDatabase.clearAndClose(context)
|
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.database.search.SearchParameters
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||||
|
import com.kunzisoft.keepass.icons.InterfaceIconPackChooser
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||||
import com.kunzisoft.keepass.utils.*
|
import com.kunzisoft.keepass.utils.*
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class Database {
|
class Database(private val iconPackChooser: InterfaceIconPackChooser) {
|
||||||
|
|
||||||
// To keep a reference for specific methods provided by version
|
// To keep a reference for specific methods provided by version
|
||||||
private var mDatabaseKDB: DatabaseKDB? = null
|
private var mDatabaseKDB: DatabaseKDB? = null
|
||||||
@@ -76,8 +77,9 @@ class Database {
|
|||||||
var isReadOnly = false
|
var isReadOnly = false
|
||||||
|
|
||||||
val iconDrawableFactory = IconDrawableFactory(
|
val iconDrawableFactory = IconDrawableFactory(
|
||||||
{ binaryCache },
|
iconPackChooser = iconPackChooser,
|
||||||
{ iconId -> iconsManager.getBinaryForCustomIcon(iconId) }
|
retrieveBinaryCache = { binaryCache },
|
||||||
|
retrieveCustomIconBinary = { iconId -> iconsManager.getBinaryForCustomIcon(iconId) }
|
||||||
)
|
)
|
||||||
|
|
||||||
var loaded = false
|
var loaded = false
|
||||||
@@ -646,7 +648,7 @@ class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New database instance to get new changes
|
// New database instance to get new changes
|
||||||
val databaseToMerge = Database()
|
val databaseToMerge = Database(iconPackChooser)
|
||||||
databaseToMerge.fileUri = databaseToMergeUri ?: this.fileUri
|
databaseToMerge.fileUri = databaseToMergeUri ?: this.fileUri
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -785,7 +787,7 @@ class Database {
|
|||||||
openDatabaseKDBX: (InputStream) -> Unit) {
|
openDatabaseKDBX: (InputStream) -> Unit) {
|
||||||
try {
|
try {
|
||||||
// Load Data, pass Uris as InputStreams
|
// Load Data, pass Uris as InputStreams
|
||||||
val databaseStream = UriUtil.getUriInputStream(contentResolver, databaseUri)
|
val databaseStream = UriUtilDatabase.getUriInputStream(contentResolver, databaseUri)
|
||||||
?: throw UnknownDatabaseLocationException()
|
?: throw UnknownDatabaseLocationException()
|
||||||
|
|
||||||
BufferedInputStream(databaseStream).use { databaseInputStream ->
|
BufferedInputStream(databaseStream).use { databaseInputStream ->
|
||||||
@@ -866,7 +868,7 @@ class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Copy from the cache to the final stream
|
// Copy from the cache to the final stream
|
||||||
UriUtil.getUriOutputStream(contentResolver, saveUri)?.use { outputStream ->
|
UriUtilDatabase.getUriOutputStream(contentResolver, saveUri)?.use { outputStream ->
|
||||||
cacheFile.inputStream().use { inputStream ->
|
cacheFile.inputStream().use { inputStream ->
|
||||||
inputStream.readAllBytes { buffer ->
|
inputStream.readAllBytes { buffer ->
|
||||||
outputStream.write(buffer)
|
outputStream.write(buffer)
|
||||||
@@ -1005,7 +1007,7 @@ class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clearAndClose(context: Context? = null) {
|
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.mDatabaseKDB = null
|
||||||
this.mDatabaseKDBX = null
|
this.mDatabaseKDBX = null
|
||||||
this.fileUri = 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.database.element.node.*
|
||||||
import com.kunzisoft.keepass.model.EntryInfo
|
import com.kunzisoft.keepass.model.EntryInfo
|
||||||
import com.kunzisoft.keepass.model.GroupInfo
|
import com.kunzisoft.keepass.model.GroupInfo
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.DatabasePreferencesUtil
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getDefaults(context: Context): Array<ChildFilter> {
|
fun getDefaults(context: Context): Array<ChildFilter> {
|
||||||
return if (PreferencesUtil.showExpiredEntries(context)) {
|
return if (DatabasePreferencesUtil.showExpiredEntries(context)) {
|
||||||
arrayOf(META_STREAM)
|
arrayOf(META_STREAM)
|
||||||
} else {
|
} else {
|
||||||
arrayOf(META_STREAM, EXPIRED)
|
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.hardware.HardwareKey
|
||||||
import com.kunzisoft.keepass.utils.StringUtil.removeSpaceChars
|
import com.kunzisoft.keepass.utils.StringUtil.removeSpaceChars
|
||||||
import com.kunzisoft.keepass.utils.StringUtil.toHexString
|
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.readEnum
|
||||||
import com.kunzisoft.keepass.utils.writeEnum
|
import com.kunzisoft.keepass.utils.writeEnum
|
||||||
import org.apache.commons.codec.binary.Hex
|
import org.apache.commons.codec.binary.Hex
|
||||||
@@ -148,7 +148,7 @@ data class MainCredential(var password: String? = null,
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
private fun getKeyFileData(contentResolver: ContentResolver,
|
private fun getKeyFileData(contentResolver: ContentResolver,
|
||||||
keyFileUri: Uri): ByteArray? {
|
keyFileUri: Uri): ByteArray? {
|
||||||
UriUtil.getUriInputStream(contentResolver, keyFileUri)?.use { keyFileInputStream ->
|
UriUtilDatabase.getUriInputStream(contentResolver, keyFileUri)?.use { keyFileInputStream ->
|
||||||
return keyFileInputStream.readBytes()
|
return keyFileInputStream.readBytes()
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.database.element.database
|
|||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
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.ObjectNameResource
|
||||||
import com.kunzisoft.keepass.utils.readEnum
|
import com.kunzisoft.keepass.utils.readEnum
|
||||||
import com.kunzisoft.keepass.utils.writeEnum
|
import com.kunzisoft.keepass.utils.writeEnum
|
||||||
@@ -24,7 +24,7 @@ import android.content.res.Resources
|
|||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.kunzisoft.encrypt.HashManager
|
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.action.node.NodeHandler
|
||||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||||
import com.kunzisoft.keepass.database.crypto.VariantDictionary
|
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.KdfEngine
|
||||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfFactory
|
import com.kunzisoft.keepass.database.crypto.kdf.KdfFactory
|
||||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfParameters
|
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.binary.BinaryData
|
||||||
import com.kunzisoft.keepass.database.element.database.DatabaseKDB.Companion.BACKUP_FOLDER_TITLE
|
import com.kunzisoft.keepass.database.element.database.DatabaseKDB.Companion.BACKUP_FOLDER_TITLE
|
||||||
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
|
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
|
||||||
@@ -58,7 +63,8 @@ import java.io.IOException
|
|||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.security.NoSuchAlgorithmException
|
import java.security.NoSuchAlgorithmException
|
||||||
import java.util.*
|
import java.util.Arrays
|
||||||
|
import java.util.UUID
|
||||||
import javax.crypto.Mac
|
import javax.crypto.Mac
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -141,6 +147,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
|
|
||||||
var maintenanceHistoryDays = UnsignedInt(365)
|
var maintenanceHistoryDays = UnsignedInt(365)
|
||||||
var color = ""
|
var color = ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if RecycleBin is enable or not
|
* Determine if RecycleBin is enable or not
|
||||||
* @return true if RecycleBin enable, false if is not available or not enable
|
* @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
|
* Create a new database with a root group
|
||||||
*/
|
*/
|
||||||
constructor(databaseName: String,
|
constructor(
|
||||||
rootName: String,
|
databaseName: String,
|
||||||
templatesGroupName: String? = null) {
|
rootName: String,
|
||||||
|
templatesGroupName: String? = null,
|
||||||
|
) {
|
||||||
name = databaseName
|
name = databaseName
|
||||||
kdbxVersion = FILE_VERSION_31
|
kdbxVersion = FILE_VERSION_31
|
||||||
val group = createGroup().apply {
|
val group = createGroup().apply {
|
||||||
@@ -187,7 +196,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
|
|
||||||
override val version: String
|
override val version: String
|
||||||
get() {
|
get() {
|
||||||
val kdbxStringVersion = when(kdbxVersion) {
|
val kdbxStringVersion = when (kdbxVersion) {
|
||||||
FILE_VERSION_31 -> "3.1"
|
FILE_VERSION_31 -> "3.1"
|
||||||
FILE_VERSION_40 -> "4.0"
|
FILE_VERSION_40 -> "4.0"
|
||||||
FILE_VERSION_41 -> "4.1"
|
FILE_VERSION_41 -> "4.1"
|
||||||
@@ -199,7 +208,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
override val defaultFileExtension: String
|
override val defaultFileExtension: String
|
||||||
get() = ".kdbx"
|
get() = ".kdbx"
|
||||||
|
|
||||||
private open class NodeOperationHandler<T: NodeKDBXInterface> : NodeHandler<T>() {
|
private open class NodeOperationHandler<T : NodeKDBXInterface> : NodeHandler<T>() {
|
||||||
var containsCustomData = false
|
var containsCustomData = false
|
||||||
override fun operate(node: T): Boolean {
|
override fun operate(node: T): Boolean {
|
||||||
if (node.customData.isNotEmpty()) {
|
if (node.customData.isNotEmpty()) {
|
||||||
@@ -209,7 +218,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class EntryOperationHandler: NodeOperationHandler<EntryKDBX>() {
|
private inner class EntryOperationHandler : NodeOperationHandler<EntryKDBX>() {
|
||||||
var passwordQualityEstimationDisabled = false
|
var passwordQualityEstimationDisabled = false
|
||||||
override fun operate(node: EntryKDBX): Boolean {
|
override fun operate(node: EntryKDBX): Boolean {
|
||||||
if (!node.qualityCheck) {
|
if (!node.qualityCheck) {
|
||||||
@@ -219,7 +228,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class GroupOperationHandler: NodeOperationHandler<GroupKDBX>() {
|
private inner class GroupOperationHandler : NodeOperationHandler<GroupKDBX>() {
|
||||||
var containsTags = false
|
var containsTags = false
|
||||||
override fun operate(node: GroupKDBX): Boolean {
|
override fun operate(node: GroupKDBX): Boolean {
|
||||||
if (node.tags.isNotEmpty())
|
if (node.tags.isNotEmpty())
|
||||||
@@ -231,7 +240,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
fun deriveMasterKey(
|
fun deriveMasterKey(
|
||||||
contentResolver: ContentResolver,
|
contentResolver: ContentResolver,
|
||||||
mainCredential: MainCredential,
|
mainCredential: MainCredential,
|
||||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||||
) {
|
) {
|
||||||
// Retrieve each plain credential
|
// Retrieve each plain credential
|
||||||
val password = mainCredential.password
|
val password = mainCredential.password
|
||||||
@@ -263,7 +272,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
|
|
||||||
@Throws(DatabaseOutputException::class)
|
@Throws(DatabaseOutputException::class)
|
||||||
fun deriveCompositeKey(
|
fun deriveCompositeKey(
|
||||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||||
) {
|
) {
|
||||||
val passwordBytes = mCompositeKey.passwordData
|
val passwordBytes = mCompositeKey.passwordData
|
||||||
val keyFileBytes = mCompositeKey.keyFileData
|
val keyFileBytes = mCompositeKey.keyFileData
|
||||||
@@ -286,9 +295,11 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun composedKeyToMasterKey(passwordData: ByteArray?,
|
private fun composedKeyToMasterKey(
|
||||||
keyFileData: ByteArray?,
|
passwordData: ByteArray?,
|
||||||
hardwareKeyData: ByteArray? = null): ByteArray {
|
keyFileData: ByteArray?,
|
||||||
|
hardwareKeyData: ByteArray? = null,
|
||||||
|
): ByteArray {
|
||||||
return HashManager.hashSha256(
|
return HashManager.hashSha256(
|
||||||
passwordData,
|
passwordData,
|
||||||
keyFileData,
|
keyFileData,
|
||||||
@@ -308,26 +319,33 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
|
|
||||||
// https://keepass.info/help/kb/kdbx_4.1.html
|
// https://keepass.info/help/kb/kdbx_4.1.html
|
||||||
val containsGroupWithTag = groupHandler.containsTags
|
val containsGroupWithTag = groupHandler.containsTags
|
||||||
val containsEntryWithPasswordQualityEstimationDisabled = entryHandler.passwordQualityEstimationDisabled
|
val containsEntryWithPasswordQualityEstimationDisabled =
|
||||||
val containsCustomIconWithNameOrLastModificationTime = iconsManager.containsCustomIconWithNameOrLastModificationTime()
|
entryHandler.passwordQualityEstimationDisabled
|
||||||
val containsHeaderCustomDataWithLastModificationTime = customData.containsItemWithLastModificationTime()
|
val containsCustomIconWithNameOrLastModificationTime =
|
||||||
|
iconsManager.containsCustomIconWithNameOrLastModificationTime()
|
||||||
|
val containsHeaderCustomDataWithLastModificationTime =
|
||||||
|
customData.containsItemWithLastModificationTime()
|
||||||
|
|
||||||
// https://keepass.info/help/kb/kdbx_4.html
|
// https://keepass.info/help/kb/kdbx_4.html
|
||||||
// If AES is not use, it's at least 4.0
|
// If AES is not use, it's at least 4.0
|
||||||
val keyDerivationFunction = kdfEngine
|
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 containsHeaderCustomData = customData.isNotEmpty()
|
||||||
val containsNodeCustomData = entryHandler.containsCustomData || groupHandler.containsCustomData
|
val containsNodeCustomData =
|
||||||
|
entryHandler.containsCustomData || groupHandler.containsCustomData
|
||||||
|
|
||||||
// Check each condition to determine version
|
// Check each condition to determine version
|
||||||
return if (containsGroupWithTag
|
return if (containsGroupWithTag
|
||||||
|| containsEntryWithPasswordQualityEstimationDisabled
|
|| containsEntryWithPasswordQualityEstimationDisabled
|
||||||
|| containsCustomIconWithNameOrLastModificationTime
|
|| containsCustomIconWithNameOrLastModificationTime
|
||||||
|| containsHeaderCustomDataWithLastModificationTime) {
|
|| containsHeaderCustomDataWithLastModificationTime
|
||||||
|
) {
|
||||||
FILE_VERSION_41
|
FILE_VERSION_41
|
||||||
} else if (kdfIsNotAes
|
} else if (kdfIsNotAes
|
||||||
|| containsHeaderCustomData
|
|| containsHeaderCustomData
|
||||||
|| containsNodeCustomData) {
|
|| containsNodeCustomData
|
||||||
|
) {
|
||||||
FILE_VERSION_40
|
FILE_VERSION_40
|
||||||
} else {
|
} else {
|
||||||
FILE_VERSION_31
|
FILE_VERSION_31
|
||||||
@@ -339,8 +357,10 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
CompressionAlgorithm.GZip
|
CompressionAlgorithm.GZip
|
||||||
)
|
)
|
||||||
|
|
||||||
fun changeBinaryCompression(oldCompression: CompressionAlgorithm,
|
fun changeBinaryCompression(
|
||||||
newCompression: CompressionAlgorithm) {
|
oldCompression: CompressionAlgorithm,
|
||||||
|
newCompression: CompressionAlgorithm,
|
||||||
|
) {
|
||||||
when (oldCompression) {
|
when (oldCompression) {
|
||||||
CompressionAlgorithm.None -> {
|
CompressionAlgorithm.None -> {
|
||||||
when (newCompression) {
|
when (newCompression) {
|
||||||
@@ -455,17 +475,21 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
return this.iconsManager.getIcon(iconId)
|
return this.iconsManager.getIcon(iconId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildNewCustomIcon(customIconId: UUID? = null,
|
fun buildNewCustomIcon(
|
||||||
result: (IconImageCustom, BinaryData?) -> Unit) {
|
customIconId: UUID? = null,
|
||||||
|
result: (IconImageCustom, BinaryData?) -> Unit,
|
||||||
|
) {
|
||||||
// Create a binary file for a brand new custom icon
|
// Create a binary file for a brand new custom icon
|
||||||
addCustomIcon(customIconId, "", null, false, result)
|
addCustomIcon(customIconId, "", null, false, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCustomIcon(customIconId: UUID? = null,
|
fun addCustomIcon(
|
||||||
name: String,
|
customIconId: UUID? = null,
|
||||||
lastModificationTime: DateInstant?,
|
name: String,
|
||||||
smallSize: Boolean,
|
lastModificationTime: DateInstant?,
|
||||||
result: (IconImageCustom, BinaryData?) -> Unit) {
|
smallSize: Boolean,
|
||||||
|
result: (IconImageCustom, BinaryData?) -> Unit,
|
||||||
|
) {
|
||||||
iconsManager.addCustomIcon(customIconId, name, lastModificationTime, { uniqueBinaryId ->
|
iconsManager.addCustomIcon(customIconId, name, lastModificationTime, { uniqueBinaryId ->
|
||||||
// Create a byte array for better performance with small data
|
// Create a byte array for better performance with small data
|
||||||
binaryCache.getBinaryData(uniqueBinaryId, smallSize)
|
binaryCache.getBinaryData(uniqueBinaryId, smallSize)
|
||||||
@@ -525,7 +549,10 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
return mTemplateEngine.getTemplate(entry)
|
return mTemplateEngine.getTemplate(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decodeEntryWithTemplateConfiguration(entryKDBX: EntryKDBX, entryIsTemplate: Boolean): EntryKDBX {
|
fun decodeEntryWithTemplateConfiguration(
|
||||||
|
entryKDBX: EntryKDBX,
|
||||||
|
entryIsTemplate: Boolean,
|
||||||
|
): EntryKDBX {
|
||||||
return if (entryIsTemplate) {
|
return if (entryIsTemplate) {
|
||||||
mTemplateEngine.decodeTemplateEntry(entryKDBX)
|
mTemplateEngine.decodeTemplateEntry(entryKDBX)
|
||||||
} else {
|
} 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) {
|
return if (entryIsTemplate) {
|
||||||
mTemplateEngine.encodeTemplateEntry(entryKDBX)
|
mTemplateEngine.encodeTemplateEntry(entryKDBX)
|
||||||
} else {
|
} else {
|
||||||
@@ -603,7 +634,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
val kdfEngine = getKdfEngineFromParameters(keyDerivationFunctionParameters)
|
val kdfEngine = getKdfEngineFromParameters(keyDerivationFunctionParameters)
|
||||||
?: throw IOException("Unknown key derivation function")
|
?: throw IOException("Unknown key derivation function")
|
||||||
|
|
||||||
var transformedMasterKey = kdfEngine.transform(masterKey, keyDerivationFunctionParameters)
|
var transformedMasterKey =
|
||||||
|
kdfEngine.transform(masterKey, keyDerivationFunctionParameters)
|
||||||
if (transformedMasterKey.size != 32) {
|
if (transformedMasterKey.size != 32) {
|
||||||
transformedMasterKey = HashManager.hashSha256(transformedMasterKey)
|
transformedMasterKey = HashManager.hashSha256(transformedMasterKey)
|
||||||
}
|
}
|
||||||
@@ -702,7 +734,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
var currentGroup: GroupKDBX? = group
|
var currentGroup: GroupKDBX? = group
|
||||||
while (currentGroup != null) {
|
while (currentGroup != null) {
|
||||||
if (currentGroup.parent == rootGroup
|
if (currentGroup.parent == rootGroup
|
||||||
&& currentGroup.title.equals(BACKUP_FOLDER_TITLE, ignoreCase = true)) {
|
&& currentGroup.title.equals(BACKUP_FOLDER_TITLE, ignoreCase = true)
|
||||||
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
currentGroup = currentGroup.parent
|
currentGroup = currentGroup.parent
|
||||||
@@ -761,7 +794,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
if (recycleBin == null)
|
if (recycleBin == null)
|
||||||
return false
|
return false
|
||||||
if (node is GroupKDBX
|
if (node is GroupKDBX
|
||||||
&& recycleBin!!.isContainedIn(node))
|
&& recycleBin!!.isContainedIn(node)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
if (!node.isContainedIn(recycleBin!!))
|
if (!node.isContainedIn(recycleBin!!))
|
||||||
return true
|
return true
|
||||||
@@ -798,10 +832,12 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
mFieldReferenceEngine.clear()
|
mFieldReferenceEngine.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildNewBinaryAttachment(smallSize: Boolean,
|
fun buildNewBinaryAttachment(
|
||||||
compression: Boolean,
|
smallSize: Boolean,
|
||||||
protection: Boolean,
|
compression: Boolean,
|
||||||
binaryPoolId: Int? = null): BinaryData {
|
protection: Boolean,
|
||||||
|
binaryPoolId: Int? = null,
|
||||||
|
): BinaryData {
|
||||||
return attachmentPool.put(binaryPoolId) { uniqueBinaryId ->
|
return attachmentPool.put(binaryPoolId) { uniqueBinaryId ->
|
||||||
binaryCache.getBinaryData(uniqueBinaryId, smallSize, compression, protection)
|
binaryCache.getBinaryData(uniqueBinaryId, smallSize, compression, protection)
|
||||||
}.binary
|
}.binary
|
||||||
@@ -873,4 +909,4 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
|||||||
|
|
||||||
const val BASE_64_FLAG = Base64.NO_WRAP
|
const val BASE_64_FLAG = Base64.NO_WRAP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user