diff --git a/CHANGELOG b/CHANGELOG index 0bfa28eac..be5ac6694 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt index 47133e692..29f71c742 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt @@ -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) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index b3732bacc..46a0092f2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -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 diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt index e47dfe781..c2ac816a1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt @@ -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 { return "V2 - KDBX$kdbxStringVersion" } + private open class NodeOperationHandler : NodeHandler() { + var containsCustomData = false + override fun operate(node: T): Boolean { + if (node.customData.isNotEmpty()) { + containsCustomData = true + } + return true + } + } + + private inner class EntryOperationHandler: NodeOperationHandler() { + var passwordQualityEstimationDisabled = false + override fun operate(node: EntryKDBX): Boolean { + if (!node.qualityCheck) { + passwordQualityEstimationDisabled = true + } + return super.operate(node) + } + } + + private inner class GroupOperationHandler: NodeOperationHandler() { + 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 = listOf( CompressionAlgorithm.None, CompressionAlgorithm.GZip diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/DatabaseHeaderKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/DatabaseHeaderKDBX.kt index 9d5122833..b5c6bb137 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/DatabaseHeaderKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/DatabaseHeaderKDBX.kt @@ -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 : NodeHandler() { - var containsCustomData = false - override fun operate(node: T): Boolean { - if (node.customData.isNotEmpty()) { - containsCustomData = true - } - return true - } - } - - private inner class EntryOperationHandler: NodeOperationHandler() { - var passwordQualityEstimationDisabled = false - override fun operate(node: EntryKDBX): Boolean { - if (!node.qualityCheck) { - passwordQualityEstimationDisabled = true - } - return super.operate(node) - } - } - - private inner class GroupOperationHandler: NodeOperationHandler() { - 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 diff --git a/fastlane/metadata/android/en-US/changelogs/93.txt b/fastlane/metadata/android/en-US/changelogs/93.txt index 2094e3e5c..f6322a6d3 100644 --- a/fastlane/metadata/android/en-US/changelogs/93.txt +++ b/fastlane/metadata/android/en-US/changelogs/93.txt @@ -1,3 +1,4 @@ * Manage data merge #840 #977 * Inherit color from template #1213 - * Add path in quick search \ No newline at end of file + * Add path in quick search + * Small fixes \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/changelogs/93.txt b/fastlane/metadata/android/fr-FR/changelogs/93.txt index 7a3ba6cec..9be808804 100644 --- a/fastlane/metadata/android/fr-FR/changelogs/93.txt +++ b/fastlane/metadata/android/fr-FR/changelogs/93.txt @@ -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 \ No newline at end of file + * Ajout du chemin dans la recherche rapide + * Petis correctifs \ No newline at end of file