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)
|
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"
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user