Fix output KDB and private indexes

This commit is contained in:
J-Jamet
2022-01-07 18:12:45 +01:00
parent 27d5733dbc
commit 23ce320d75
4 changed files with 42 additions and 61 deletions

View File

@@ -51,12 +51,6 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
kdfListV3.add(KdfFactory.aesKdf) kdfListV3.add(KdfFactory.aesKdf)
} }
private fun getGroupById(groupId: Int): GroupKDB? {
if (groupId == -1)
return null
return getGroupById(NodeIdInt(groupId))
}
val backupGroup: GroupKDB? val backupGroup: GroupKDB?
get() { get() {
return retrieveBackup() return retrieveBackup()
@@ -81,11 +75,6 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
return list return list
} }
val rootGroups: List<GroupKDB>
get() {
return rootGroup?.getChildGroups() ?: ArrayList()
}
override val passwordEncoding: String override val passwordEncoding: String
get() = "ISO-8859-1" get() = "ISO-8859-1"

View File

@@ -414,37 +414,37 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
} }
fun getEntryByTitle(title: String, recursionLevel: Int): EntryKDBX? { fun getEntryByTitle(title: String, recursionLevel: Int): EntryKDBX? {
return this.entryIndexes.values.find { entry -> return findEntry { entry ->
entry.decodeTitleKey(recursionLevel).equals(title, true) entry.decodeTitleKey(recursionLevel).equals(title, true)
} }
} }
fun getEntryByUsername(username: String, recursionLevel: Int): EntryKDBX? { fun getEntryByUsername(username: String, recursionLevel: Int): EntryKDBX? {
return this.entryIndexes.values.find { entry -> return findEntry { entry ->
entry.decodeUsernameKey(recursionLevel).equals(username, true) entry.decodeUsernameKey(recursionLevel).equals(username, true)
} }
} }
fun getEntryByURL(url: String, recursionLevel: Int): EntryKDBX? { fun getEntryByURL(url: String, recursionLevel: Int): EntryKDBX? {
return this.entryIndexes.values.find { entry -> return findEntry { entry ->
entry.decodeUrlKey(recursionLevel).equals(url, true) entry.decodeUrlKey(recursionLevel).equals(url, true)
} }
} }
fun getEntryByPassword(password: String, recursionLevel: Int): EntryKDBX? { fun getEntryByPassword(password: String, recursionLevel: Int): EntryKDBX? {
return this.entryIndexes.values.find { entry -> return findEntry { entry ->
entry.decodePasswordKey(recursionLevel).equals(password, true) entry.decodePasswordKey(recursionLevel).equals(password, true)
} }
} }
fun getEntryByNotes(notes: String, recursionLevel: Int): EntryKDBX? { fun getEntryByNotes(notes: String, recursionLevel: Int): EntryKDBX? {
return this.entryIndexes.values.find { entry -> return findEntry { entry ->
entry.decodeNotesKey(recursionLevel).equals(notes, true) entry.decodeNotesKey(recursionLevel).equals(notes, true)
} }
} }
fun getEntryByCustomData(customDataValue: String): EntryKDBX? { fun getEntryByCustomData(customDataValue: String): EntryKDBX? {
return entryIndexes.values.find { entry -> return findEntry { entry ->
entry.customData.containsItemWithValue(customDataValue) entry.customData.containsItemWithValue(customDataValue)
} }
} }

View File

@@ -67,7 +67,7 @@ abstract class DatabaseVersioned<
var changeDuplicateId = false var changeDuplicateId = false
private var groupIndexes = LinkedHashMap<NodeId<GroupId>, Group>() private var groupIndexes = LinkedHashMap<NodeId<GroupId>, Group>()
protected var entryIndexes = LinkedHashMap<NodeId<EntryId>, Entry>() private var entryIndexes = LinkedHashMap<NodeId<EntryId>, Entry>()
abstract val version: String abstract val version: String
@@ -199,12 +199,6 @@ abstract class DatabaseVersioned<
* ------------------------------------- * -------------------------------------
*/ */
fun doForEachGroupInIndex(action: (Group) -> Unit) {
for (group in groupIndexes) {
action.invoke(group.value)
}
}
/** /**
* Determine if an id number is already in use * Determine if an id number is already in use
* *
@@ -220,14 +214,7 @@ abstract class DatabaseVersioned<
return groupIndexes.values return groupIndexes.values
} }
fun setGroupIndexes(groupList: List<Group>) { open fun getGroupById(id: NodeId<GroupId>): Group? {
this.groupIndexes.clear()
for (currentGroup in groupList) {
this.groupIndexes[currentGroup.nodeId] = currentGroup
}
}
fun getGroupById(id: NodeId<GroupId>): Group? {
return this.groupIndexes[id] return this.groupIndexes[id]
} }
@@ -251,16 +238,6 @@ abstract class DatabaseVersioned<
this.groupIndexes.remove(group.nodeId) this.groupIndexes.remove(group.nodeId)
} }
fun numberOfGroups(): Int {
return groupIndexes.size
}
fun doForEachEntryInIndex(action: (Entry) -> Unit) {
for (entry in entryIndexes) {
action.invoke(entry.value)
}
}
fun isEntryIdUsed(id: NodeId<EntryId>): Boolean { fun isEntryIdUsed(id: NodeId<EntryId>): Boolean {
return entryIndexes.containsKey(id) return entryIndexes.containsKey(id)
} }
@@ -273,6 +250,10 @@ abstract class DatabaseVersioned<
return this.entryIndexes[id] return this.entryIndexes[id]
} }
fun findEntry(predicate: (Entry) -> Boolean): Entry? {
return this.entryIndexes.values.find(predicate)
}
fun addEntryIndex(entry: Entry) { fun addEntryIndex(entry: Entry) {
val entryId = entry.nodeId val entryId = entry.nodeId
if (entryIndexes.containsKey(entryId)) { if (entryIndexes.containsKey(entryId)) {
@@ -293,10 +274,6 @@ abstract class DatabaseVersioned<
this.entryIndexes.remove(entry.nodeId) this.entryIndexes.remove(entry.nodeId)
} }
fun numberOfEntries(): Int {
return entryIndexes.size
}
open fun clearCache() { open fun clearCache() {
this.groupIndexes.clear() this.groupIndexes.clear()
this.entryIndexes.clear() this.entryIndexes.clear()

View File

@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.database.file.output
import com.kunzisoft.encrypt.HashManager import com.kunzisoft.encrypt.HashManager
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.element.database.DatabaseKDB import com.kunzisoft.keepass.database.element.database.DatabaseKDB
import com.kunzisoft.keepass.database.element.entry.EntryKDB
import com.kunzisoft.keepass.database.element.group.GroupKDB import com.kunzisoft.keepass.database.element.group.GroupKDB
import com.kunzisoft.keepass.database.exception.DatabaseOutputException import com.kunzisoft.keepass.database.exception.DatabaseOutputException
import com.kunzisoft.keepass.database.file.DatabaseHeader import com.kunzisoft.keepass.database.file.DatabaseHeader
@@ -34,7 +35,6 @@ import java.io.ByteArrayOutputStream
import java.io.IOException import java.io.IOException
import java.io.OutputStream import java.io.OutputStream
import java.security.* import java.security.*
import java.util.*
import javax.crypto.Cipher import javax.crypto.Cipher
import javax.crypto.CipherOutputStream import javax.crypto.CipherOutputStream
@@ -44,6 +44,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
private var headerHashBlock: ByteArray? = null private var headerHashBlock: ByteArray? = null
private var mGroupList = mutableListOf<GroupKDB>()
private var mEntryList = mutableListOf<EntryKDB>()
@Throws(DatabaseOutputException::class) @Throws(DatabaseOutputException::class)
fun getFinalKey(header: DatabaseHeader): ByteArray? { fun getFinalKey(header: DatabaseHeader): ByteArray? {
try { try {
@@ -61,7 +64,7 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
// and remove any orphaned nodes that are no longer part of the tree hierarchy // and remove any orphaned nodes that are no longer part of the tree hierarchy
// also remove the virtual root not present in kdb // also remove the virtual root not present in kdb
val rootGroup = mDatabaseKDB.rootGroup val rootGroup = mDatabaseKDB.rootGroup
sortGroupsForOutput() sortNodesForOutput()
val header = outputHeader(mOutputStream) val header = outputHeader(mOutputStream)
@@ -91,6 +94,8 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} finally { } finally {
// Add again the virtual root group for better management // Add again the virtual root group for better management
mDatabaseKDB.rootGroup = rootGroup mDatabaseKDB.rootGroup = rootGroup
mGroupList.clear()
mEntryList.clear()
} }
} }
@@ -120,8 +125,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} }
header.version = DatabaseHeaderKDB.DBVER_DW header.version = DatabaseHeaderKDB.DBVER_DW
header.numGroups = UnsignedInt(mDatabaseKDB.numberOfGroups()) // To remove root
header.numEntries = UnsignedInt(mDatabaseKDB.numberOfEntries()) header.numGroups = UnsignedInt(mGroupList.size)
header.numEntries = UnsignedInt(mEntryList.size)
header.numKeyEncRounds = UnsignedInt.fromKotlinLong(mDatabaseKDB.numberKeyEncryptionRounds) header.numKeyEncRounds = UnsignedInt.fromKotlinLong(mDatabaseKDB.numberKeyEncryptionRounds)
setIVs(header) setIVs(header)
@@ -194,31 +200,40 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} }
// Groups // Groups
mDatabaseKDB.doForEachGroupInIndex { group -> mGroupList.forEach { group ->
if (group != mDatabaseKDB.rootGroup) {
GroupOutputKDB(group, outputStream).output() GroupOutputKDB(group, outputStream).output()
} }
}
// Entries // Entries
mDatabaseKDB.doForEachEntryInIndex { entry -> mEntryList.forEach { entry ->
EntryOutputKDB(mDatabaseKDB, entry, outputStream).output() EntryOutputKDB(mDatabaseKDB, entry, outputStream).output()
} }
} }
private fun sortGroupsForOutput() { private fun sortNodesForOutput() {
val groupList = ArrayList<GroupKDB>() mGroupList.clear()
mEntryList.clear()
// Rebuild list according to sorting order removing any orphaned groups // Rebuild list according to sorting order removing any orphaned groups
for (rootGroup in mDatabaseKDB.rootGroups) { // Do not keep root
sortGroup(rootGroup, groupList) mDatabaseKDB.rootGroup?.getChildGroups()?.let { rootSubGroups ->
for (rootGroup in rootSubGroups) {
sortGroup(rootGroup)
}
} }
mDatabaseKDB.setGroupIndexes(groupList)
} }
private fun sortGroup(group: GroupKDB, groupList: MutableList<GroupKDB>) { private fun sortGroup(group: GroupKDB) {
// Add current tree // Add current tree
groupList.add(group) mGroupList.add(group)
for (childEntry in group.getChildEntries()) {
mEntryList.add(childEntry)
}
// Recurse over children // Recurse over children
for (childGroup in group.getChildGroups()) { for (childGroup in group.getChildGroups()) {
sortGroup(childGroup, groupList) sortGroup(childGroup)
} }
} }