Upgrade database version after a modification

This commit is contained in:
J-Jamet
2022-01-25 14:22:26 +01:00
parent b8005466cd
commit fbf67f28f5
7 changed files with 76 additions and 64 deletions

View File

@@ -2,6 +2,7 @@ KeePassDX(3.2.0)
* Manage data merge #840 #977
* Inherit color from template #1213
* Add path in quick search
* Small fixes
KeePassDX(3.1.0)
* Add breadcrumb

View File

@@ -34,6 +34,7 @@ open class SaveDatabaseRunnable(protected var context: Context,
override fun onStartRun() {}
override fun onActionRun() {
database.checkVersion()
if (saveDatabase && result.isSuccess) {
try {
database.saveData(context.contentResolver)

View File

@@ -269,6 +269,12 @@ class Database {
val version: String
get() = mDatabaseKDB?.version ?: mDatabaseKDBX?.version ?: "-"
fun checkVersion() {
mDatabaseKDBX?.getMinKdbxVersion()?.let {
mDatabaseKDBX?.kdbxVersion = it
}
}
val type: Class<*>?
get() = mDatabaseKDB?.javaClass ?: mDatabaseKDBX?.javaClass

View File

@@ -27,6 +27,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.action.node.NodeHandler
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.VariantDictionary
import com.kunzisoft.keepass.database.crypto.kdf.AesKdf
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
import com.kunzisoft.keepass.database.crypto.kdf.KdfFactory
import com.kunzisoft.keepass.database.crypto.kdf.KdfParameters
@@ -42,6 +43,7 @@ import com.kunzisoft.keepass.database.element.icon.IconImageCustom
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.element.node.NodeKDBXInterface
import com.kunzisoft.keepass.database.element.node.NodeVersioned
import com.kunzisoft.keepass.database.element.security.MemoryProtectionConfig
import com.kunzisoft.keepass.database.element.template.Template
@@ -187,6 +189,67 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
return "V2 - KDBX$kdbxStringVersion"
}
private open class NodeOperationHandler<T: NodeKDBXInterface> : NodeHandler<T>() {
var containsCustomData = false
override fun operate(node: T): Boolean {
if (node.customData.isNotEmpty()) {
containsCustomData = true
}
return true
}
}
private inner class EntryOperationHandler: NodeOperationHandler<EntryKDBX>() {
var passwordQualityEstimationDisabled = false
override fun operate(node: EntryKDBX): Boolean {
if (!node.qualityCheck) {
passwordQualityEstimationDisabled = true
}
return super.operate(node)
}
}
private inner class GroupOperationHandler: NodeOperationHandler<GroupKDBX>() {
var containsTags = false
override fun operate(node: GroupKDBX): Boolean {
if (!node.tags.isEmpty())
containsTags = true
return super.operate(node)
}
}
fun getMinKdbxVersion(): UnsignedInt {
val entryHandler = EntryOperationHandler()
val groupHandler = GroupOperationHandler()
rootGroup?.doForEachChildAndForIt(entryHandler, groupHandler)
// https://keepass.info/help/kb/kdbx_4.1.html
val containsGroupWithTag = groupHandler.containsTags
val containsEntryWithPasswordQualityEstimationDisabled = entryHandler.passwordQualityEstimationDisabled
val containsCustomIconWithNameOrLastModificationTime = iconsManager.containsCustomIconWithNameOrLastModificationTime()
val containsHeaderCustomDataWithLastModificationTime = customData.containsItemWithLastModificationTime()
// https://keepass.info/help/kb/kdbx_4.html
// If AES is not use, it's at least 4.0
val kdfIsNotAes = kdfParameters?.uuid != AesKdf.CIPHER_UUID
val containsHeaderCustomData = customData.isNotEmpty()
val containsNodeCustomData = entryHandler.containsCustomData || groupHandler.containsCustomData
// Check each condition to determine version
return if (containsGroupWithTag
|| containsEntryWithPasswordQualityEstimationDisabled
|| containsCustomIconWithNameOrLastModificationTime
|| containsHeaderCustomDataWithLastModificationTime) {
FILE_VERSION_41
} else if (kdfIsNotAes
|| containsHeaderCustomData
|| containsNodeCustomData) {
FILE_VERSION_40
} else {
FILE_VERSION_31
}
}
val availableCompressionAlgorithms: List<CompressionAlgorithm> = listOf(
CompressionAlgorithm.None,
CompressionAlgorithm.GZip

View File

@@ -87,71 +87,10 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
inner class HeaderAndHash(var header: ByteArray, var hash: ByteArray)
init {
this.version = getMinKdbxVersion(databaseV4) // Only for writing
this.version = databaseV4.getMinKdbxVersion()
this.masterSeed = ByteArray(32)
}
private open class NodeOperationHandler<T: NodeKDBXInterface> : NodeHandler<T>() {
var containsCustomData = false
override fun operate(node: T): Boolean {
if (node.customData.isNotEmpty()) {
containsCustomData = true
}
return true
}
}
private inner class EntryOperationHandler: NodeOperationHandler<EntryKDBX>() {
var passwordQualityEstimationDisabled = false
override fun operate(node: EntryKDBX): Boolean {
if (!node.qualityCheck) {
passwordQualityEstimationDisabled = true
}
return super.operate(node)
}
}
private inner class GroupOperationHandler: NodeOperationHandler<GroupKDBX>() {
var containsTags = false
override fun operate(node: GroupKDBX): Boolean {
if (!node.tags.isEmpty())
containsTags = true
return super.operate(node)
}
}
private fun getMinKdbxVersion(databaseKDBX: DatabaseKDBX): UnsignedInt {
val entryHandler = EntryOperationHandler()
val groupHandler = GroupOperationHandler()
databaseKDBX.rootGroup?.doForEachChildAndForIt(entryHandler, groupHandler)
// https://keepass.info/help/kb/kdbx_4.1.html
val containsGroupWithTag = groupHandler.containsTags
val containsEntryWithPasswordQualityEstimationDisabled = entryHandler.passwordQualityEstimationDisabled
val containsCustomIconWithNameOrLastModificationTime = databaseKDBX.iconsManager.containsCustomIconWithNameOrLastModificationTime()
val containsHeaderCustomDataWithLastModificationTime = databaseKDBX.customData.containsItemWithLastModificationTime()
// https://keepass.info/help/kb/kdbx_4.html
// If AES is not use, it's at least 4.0
val kdfIsNotAes = databaseKDBX.kdfParameters?.uuid != AesKdf.CIPHER_UUID
val containsHeaderCustomData = databaseKDBX.customData.isNotEmpty()
val containsNodeCustomData = entryHandler.containsCustomData || groupHandler.containsCustomData
// Check each condition to determine version
return if (containsGroupWithTag
|| containsEntryWithPasswordQualityEstimationDisabled
|| containsCustomIconWithNameOrLastModificationTime
|| containsHeaderCustomDataWithLastModificationTime) {
FILE_VERSION_41
} else if (kdfIsNotAes
|| containsHeaderCustomData
|| containsNodeCustomData) {
FILE_VERSION_40
} else {
FILE_VERSION_31
}
}
/** Assumes the input stream is at the beginning of the .kdbx file
* @param inputStream
* @throws IOException

View File

@@ -1,3 +1,4 @@
* Manage data merge #840 #977
* Inherit color from template #1213
* Add path in quick search
* Small fixes

View File

@@ -1,3 +1,4 @@
* Gestion de la fusion des données #840 #977
* Héritage de la couleur du gabarit #1213
* Ajout du chemin dans la recherche rapide
* Petis correctifs