mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix output KDB and private indexes
This commit is contained in:
@@ -51,12 +51,6 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
kdfListV3.add(KdfFactory.aesKdf)
|
||||
}
|
||||
|
||||
private fun getGroupById(groupId: Int): GroupKDB? {
|
||||
if (groupId == -1)
|
||||
return null
|
||||
return getGroupById(NodeIdInt(groupId))
|
||||
}
|
||||
|
||||
val backupGroup: GroupKDB?
|
||||
get() {
|
||||
return retrieveBackup()
|
||||
@@ -81,11 +75,6 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
return list
|
||||
}
|
||||
|
||||
val rootGroups: List<GroupKDB>
|
||||
get() {
|
||||
return rootGroup?.getChildGroups() ?: ArrayList()
|
||||
}
|
||||
|
||||
override val passwordEncoding: String
|
||||
get() = "ISO-8859-1"
|
||||
|
||||
|
||||
@@ -414,37 +414,37 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
}
|
||||
|
||||
fun getEntryByTitle(title: String, recursionLevel: Int): EntryKDBX? {
|
||||
return this.entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.decodeTitleKey(recursionLevel).equals(title, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntryByUsername(username: String, recursionLevel: Int): EntryKDBX? {
|
||||
return this.entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.decodeUsernameKey(recursionLevel).equals(username, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntryByURL(url: String, recursionLevel: Int): EntryKDBX? {
|
||||
return this.entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.decodeUrlKey(recursionLevel).equals(url, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntryByPassword(password: String, recursionLevel: Int): EntryKDBX? {
|
||||
return this.entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.decodePasswordKey(recursionLevel).equals(password, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntryByNotes(notes: String, recursionLevel: Int): EntryKDBX? {
|
||||
return this.entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.decodeNotesKey(recursionLevel).equals(notes, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEntryByCustomData(customDataValue: String): EntryKDBX? {
|
||||
return entryIndexes.values.find { entry ->
|
||||
return findEntry { entry ->
|
||||
entry.customData.containsItemWithValue(customDataValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ abstract class DatabaseVersioned<
|
||||
var changeDuplicateId = false
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -220,14 +214,7 @@ abstract class DatabaseVersioned<
|
||||
return groupIndexes.values
|
||||
}
|
||||
|
||||
fun setGroupIndexes(groupList: List<Group>) {
|
||||
this.groupIndexes.clear()
|
||||
for (currentGroup in groupList) {
|
||||
this.groupIndexes[currentGroup.nodeId] = currentGroup
|
||||
}
|
||||
}
|
||||
|
||||
fun getGroupById(id: NodeId<GroupId>): Group? {
|
||||
open fun getGroupById(id: NodeId<GroupId>): Group? {
|
||||
return this.groupIndexes[id]
|
||||
}
|
||||
|
||||
@@ -251,16 +238,6 @@ abstract class DatabaseVersioned<
|
||||
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 {
|
||||
return entryIndexes.containsKey(id)
|
||||
}
|
||||
@@ -273,6 +250,10 @@ abstract class DatabaseVersioned<
|
||||
return this.entryIndexes[id]
|
||||
}
|
||||
|
||||
fun findEntry(predicate: (Entry) -> Boolean): Entry? {
|
||||
return this.entryIndexes.values.find(predicate)
|
||||
}
|
||||
|
||||
fun addEntryIndex(entry: Entry) {
|
||||
val entryId = entry.nodeId
|
||||
if (entryIndexes.containsKey(entryId)) {
|
||||
@@ -293,10 +274,6 @@ abstract class DatabaseVersioned<
|
||||
this.entryIndexes.remove(entry.nodeId)
|
||||
}
|
||||
|
||||
fun numberOfEntries(): Int {
|
||||
return entryIndexes.size
|
||||
}
|
||||
|
||||
open fun clearCache() {
|
||||
this.groupIndexes.clear()
|
||||
this.entryIndexes.clear()
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.database.file.output
|
||||
import com.kunzisoft.encrypt.HashManager
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
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.exception.DatabaseOutputException
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeader
|
||||
@@ -34,7 +35,6 @@ import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.security.*
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.CipherOutputStream
|
||||
|
||||
@@ -44,6 +44,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
|
||||
private var headerHashBlock: ByteArray? = null
|
||||
|
||||
private var mGroupList = mutableListOf<GroupKDB>()
|
||||
private var mEntryList = mutableListOf<EntryKDB>()
|
||||
|
||||
@Throws(DatabaseOutputException::class)
|
||||
fun getFinalKey(header: DatabaseHeader): ByteArray? {
|
||||
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
|
||||
// also remove the virtual root not present in kdb
|
||||
val rootGroup = mDatabaseKDB.rootGroup
|
||||
sortGroupsForOutput()
|
||||
sortNodesForOutput()
|
||||
|
||||
val header = outputHeader(mOutputStream)
|
||||
|
||||
@@ -91,6 +94,8 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
} finally {
|
||||
// Add again the virtual root group for better management
|
||||
mDatabaseKDB.rootGroup = rootGroup
|
||||
mGroupList.clear()
|
||||
mEntryList.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +125,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
}
|
||||
|
||||
header.version = DatabaseHeaderKDB.DBVER_DW
|
||||
header.numGroups = UnsignedInt(mDatabaseKDB.numberOfGroups())
|
||||
header.numEntries = UnsignedInt(mDatabaseKDB.numberOfEntries())
|
||||
// To remove root
|
||||
header.numGroups = UnsignedInt(mGroupList.size)
|
||||
header.numEntries = UnsignedInt(mEntryList.size)
|
||||
header.numKeyEncRounds = UnsignedInt.fromKotlinLong(mDatabaseKDB.numberKeyEncryptionRounds)
|
||||
|
||||
setIVs(header)
|
||||
@@ -194,31 +200,40 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
}
|
||||
|
||||
// Groups
|
||||
mDatabaseKDB.doForEachGroupInIndex { group ->
|
||||
GroupOutputKDB(group, outputStream).output()
|
||||
mGroupList.forEach { group ->
|
||||
if (group != mDatabaseKDB.rootGroup) {
|
||||
GroupOutputKDB(group, outputStream).output()
|
||||
}
|
||||
}
|
||||
// Entries
|
||||
mDatabaseKDB.doForEachEntryInIndex { entry ->
|
||||
mEntryList.forEach { entry ->
|
||||
EntryOutputKDB(mDatabaseKDB, entry, outputStream).output()
|
||||
}
|
||||
}
|
||||
|
||||
private fun sortGroupsForOutput() {
|
||||
val groupList = ArrayList<GroupKDB>()
|
||||
private fun sortNodesForOutput() {
|
||||
mGroupList.clear()
|
||||
mEntryList.clear()
|
||||
// Rebuild list according to sorting order removing any orphaned groups
|
||||
for (rootGroup in mDatabaseKDB.rootGroups) {
|
||||
sortGroup(rootGroup, groupList)
|
||||
// Do not keep root
|
||||
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
|
||||
groupList.add(group)
|
||||
mGroupList.add(group)
|
||||
|
||||
for (childEntry in group.getChildEntries()) {
|
||||
mEntryList.add(childEntry)
|
||||
}
|
||||
|
||||
// Recurse over children
|
||||
for (childGroup in group.getChildGroups()) {
|
||||
sortGroup(childGroup, groupList)
|
||||
sortGroup(childGroup)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user