Manage default user name and color in KDB

This commit is contained in:
J-Jamet
2022-01-08 19:35:42 +01:00
parent b0d1f93bfc
commit b9652291bd
7 changed files with 148 additions and 50 deletions

View File

@@ -22,10 +22,10 @@ package com.kunzisoft.keepass.database.element
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Build
import android.util.Log import android.util.Log
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.androidclearchroma.ChromaUtil
import com.kunzisoft.keepass.database.action.node.NodeHandler import com.kunzisoft.keepass.database.action.node.NodeHandler
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
@@ -226,30 +226,31 @@ class Database {
mDatabaseKDBX?.descriptionChanged = DateInstant() mDatabaseKDBX?.descriptionChanged = DateInstant()
} }
val allowDefaultUsername: Boolean
get() = mDatabaseKDBX != null
// TODO get() = mDatabaseKDB != null || mDatabaseKDBX != null
var defaultUsername: String var defaultUsername: String
get() { get() {
return mDatabaseKDBX?.defaultUserName ?: "" // TODO mDatabaseKDB default username return mDatabaseKDB?.defaultUserName ?: mDatabaseKDBX?.defaultUserName ?: ""
} }
set(username) { set(username) {
mDatabaseKDB?.defaultUserName = username
mDatabaseKDBX?.defaultUserName = username mDatabaseKDBX?.defaultUserName = username
mDatabaseKDBX?.defaultUserNameChanged = DateInstant() mDatabaseKDBX?.defaultUserNameChanged = DateInstant()
} }
val allowCustomColor: Boolean
get() = mDatabaseKDBX != null
// TODO get() = mDatabaseKDB != null || mDatabaseKDBX != null
// with format "#000000" // with format "#000000"
var customColor: String var customColor: String
get() { get() {
return mDatabaseKDBX?.color ?: "" // TODO mDatabaseKDB color var colorString = ""
mDatabaseKDB?.color?.let {
colorString = ChromaUtil.getFormattedColorString(it, false)
}
return mDatabaseKDBX?.color ?: colorString
} }
set(value) { set(value) {
// TODO Check color string mDatabaseKDB?.color = if (value == "") {
null
} else {
Color.parseColor(value)
}
mDatabaseKDBX?.color = value mDatabaseKDBX?.color = value
} }

View File

@@ -309,8 +309,9 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
val withoutMetaStream = filters.contains(ChildFilter.META_STREAM) val withoutMetaStream = filters.contains(ChildFilter.META_STREAM)
val showExpiredEntries = !filters.contains(ChildFilter.EXPIRED) val showExpiredEntries = !filters.contains(ChildFilter.EXPIRED)
// TODO Change KDB parser to remove meta entries
return groupKDB?.getChildEntries()?.filter { return groupKDB?.getChildEntries()?.filter {
(!withoutMetaStream || (withoutMetaStream && !it.isMetaStream)) (!withoutMetaStream || (withoutMetaStream && !it.isMetaStream()))
&& (!it.isCurrentlyExpires or showExpiredEntries) && (!it.isCurrentlyExpires or showExpiredEntries)
}?.map { }?.map {
Entry(it) Entry(it)

View File

@@ -61,6 +61,9 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
return listOf(BACKUP_FOLDER_TITLE) return listOf(BACKUP_FOLDER_TITLE)
} }
var defaultUserName: String = ""
var color: Int? = null
override val kdfEngine: KdfEngine override val kdfEngine: KdfEngine
get() = kdfListV3[0] get() = kdfListV3[0]

View File

@@ -25,6 +25,7 @@ import com.kunzisoft.keepass.database.element.Attachment
import com.kunzisoft.keepass.database.element.binary.AttachmentPool import com.kunzisoft.keepass.database.element.binary.AttachmentPool
import com.kunzisoft.keepass.database.element.binary.BinaryData import com.kunzisoft.keepass.database.element.binary.BinaryData
import com.kunzisoft.keepass.database.element.group.GroupKDB import com.kunzisoft.keepass.database.element.group.GroupKDB
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
import com.kunzisoft.keepass.database.element.icon.IconImageStandard.Companion.KEY_ID import com.kunzisoft.keepass.database.element.icon.IconImageStandard.Companion.KEY_ID
import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.NodeIdUUID import com.kunzisoft.keepass.database.element.node.NodeIdUUID
@@ -60,18 +61,43 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
private var binaryDataId: Int? = null private var binaryDataId: Int? = null
// Determine if this is a MetaStream entry // Determine if this is a MetaStream entry
val isMetaStream: Boolean fun isMetaStream(): Boolean {
get() { if (notes.isEmpty()) return false
if (notes.isEmpty()) return false if (binaryDescription != PMS_ID_BINDESC) return false
if (binaryDescription != PMS_ID_BINDESC) return false if (title.isEmpty()) return false
if (title.isEmpty()) return false if (title != PMS_ID_TITLE) return false
if (title != PMS_ID_TITLE) return false if (username.isEmpty()) return false
if (username.isEmpty()) return false if (username != PMS_ID_USER) return false
if (username != PMS_ID_USER) return false if (url.isEmpty()) return false
if (url.isEmpty()) return false if (url != PMS_ID_URL) return false
if (url != PMS_ID_URL) return false return icon.standard.id == KEY_ID
return icon.standard.id == KEY_ID }
}
fun isMetaStreamDefaultUsername(): Boolean {
return isMetaStream() && notes == PMS_STREAM_DEFAULTUSER
}
private fun setMetaStream() {
binaryDescription = PMS_ID_BINDESC
title = PMS_ID_TITLE
username = PMS_ID_USER
url = PMS_ID_URL
icon.standard = IconImageStandard(KEY_ID)
}
fun setMetaStreamDefaultUsername() {
notes = PMS_STREAM_DEFAULTUSER
setMetaStream()
}
fun isMetaStreamDatabaseColor(): Boolean {
return isMetaStream() && notes == PMS_STREAM_DBCOLOR
}
fun setMetaStreamDatabaseColor() {
notes = PMS_STREAM_DBCOLOR
setMetaStream()
}
override fun initNodeId(): NodeId<UUID> { override fun initNodeId(): NodeId<UUID> {
return NodeIdUUID() return NodeIdUUID()
@@ -184,6 +210,13 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
private const val PMS_ID_USER = "SYSTEM" private const val PMS_ID_USER = "SYSTEM"
private const val PMS_ID_URL = "$" private const val PMS_ID_URL = "$"
const val PMS_STREAM_SIMPLESTATE = "Simple UI State"
const val PMS_STREAM_DEFAULTUSER = "Default User Name"
const val PMS_STREAM_SEARCHHISTORYITEM = "Search History Item"
const val PMS_STREAM_CUSTOMKVP = "Custom KVP"
const val PMS_STREAM_DBCOLOR = "Database Color"
const val PMS_STREAM_KPXICON2 = "KPX_CUSTOM_ICONS_2"
@JvmField @JvmField
val CREATOR: Parcelable.Creator<EntryKDB> = object : Parcelable.Creator<EntryKDB> { val CREATOR: Parcelable.Creator<EntryKDB> = object : Parcelable.Creator<EntryKDB> {
override fun createFromParcel(parcel: Parcel): EntryKDB { override fun createFromParcel(parcel: Parcel): EntryKDB {

View File

@@ -30,7 +30,6 @@ import com.kunzisoft.keepass.database.element.group.GroupKDB
import com.kunzisoft.keepass.database.element.node.NodeIdInt import com.kunzisoft.keepass.database.element.node.NodeIdInt
import com.kunzisoft.keepass.database.element.node.NodeIdUUID import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.exception.* import com.kunzisoft.keepass.database.exception.*
import com.kunzisoft.keepass.database.file.DatabaseHeader
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.* import com.kunzisoft.keepass.utils.*
@@ -300,6 +299,22 @@ class DatabaseInputKDB(cacheDirectory: File,
} }
newEntry?.let { entry -> newEntry?.let { entry ->
mDatabase.addEntryIndex(entry) mDatabase.addEntryIndex(entry)
// Parse meta info
if (entry.isMetaStreamDefaultUsername()) {
var defaultUser = ""
entry.getBinary(mDatabase.attachmentPool)
?.getInputDataStream(mDatabase.binaryCache)?.use {
defaultUser = String(it.readBytes())
}
mDatabase.defaultUserName = defaultUser
} else if (entry.isMetaStreamDatabaseColor()) {
var color: Int? = null
entry.getBinary(mDatabase.attachmentPool)
?.getInputDataStream(mDatabase.binaryCache)?.use {
color = it.read()
}
mDatabase.color = color
}
currentEntryNumber++ currentEntryNumber++
newEntry = null newEntry = null
} }

View File

@@ -47,6 +47,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
private var mGroupList = mutableListOf<GroupKDB>() private var mGroupList = mutableListOf<GroupKDB>()
private var mEntryList = mutableListOf<EntryKDB>() private var mEntryList = mutableListOf<EntryKDB>()
private var mDefaultUsernameAdded = false
private var mDatabaseColorAdded = false
@Throws(DatabaseOutputException::class) @Throws(DatabaseOutputException::class)
fun getFinalKey(header: DatabaseHeader): ByteArray? { fun getFinalKey(header: DatabaseHeader): ByteArray? {
try { try {
@@ -94,8 +97,7 @@ 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() clearParser()
mEntryList.clear()
} }
} }
@@ -211,9 +213,14 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} }
} }
private fun sortNodesForOutput() { private fun clearParser() {
mGroupList.clear() mGroupList.clear()
mEntryList.clear() mEntryList.clear()
mDefaultUsernameAdded = false
}
private fun sortNodesForOutput() {
clearParser()
// Rebuild list according to sorting order removing any orphaned groups // Rebuild list according to sorting order removing any orphaned groups
// Do not keep root // Do not keep root
mDatabaseKDB.rootGroup?.getChildGroups()?.let { rootSubGroups -> mDatabaseKDB.rootGroup?.getChildGroups()?.let { rootSubGroups ->
@@ -228,7 +235,39 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
mGroupList.add(group) mGroupList.add(group)
for (childEntry in group.getChildEntries()) { for (childEntry in group.getChildEntries()) {
mEntryList.add(childEntry) if (childEntry.isMetaStreamDefaultUsername()
&& mDatabaseKDB.defaultUserName.isNotEmpty()) {
setDefaultUsername(childEntry)
mEntryList.add(childEntry)
mDefaultUsernameAdded = true
} else if (childEntry.isMetaStreamDatabaseColor()
&& mDatabaseKDB.color != null) {
setDatabaseColor(childEntry)
mEntryList.add(childEntry)
mDatabaseColorAdded = true
} else {
mEntryList.add(childEntry)
}
}
// Add MetaStream
if (!mDefaultUsernameAdded
&& mDatabaseKDB.defaultUserName.isNotEmpty()) {
val metaEntry = EntryKDB().apply {
setMetaStreamDefaultUsername()
setDefaultUsername(this)
}
mDatabaseKDB.addEntryTo(metaEntry, group)
mEntryList.add(metaEntry)
}
if (!mDatabaseColorAdded
&& mDatabaseKDB.color != null) {
val metaEntry = EntryKDB().apply {
setMetaStreamDatabaseColor()
setDatabaseColor(this)
}
mDatabaseKDB.addEntryTo(metaEntry, group)
mEntryList.add(metaEntry)
} }
// Recurse over children // Recurse over children
@@ -237,6 +276,22 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} }
} }
private fun setDefaultUsername(entryKDB: EntryKDB) {
val binaryData = mDatabaseKDB.buildNewAttachment()
entryKDB.putBinary(binaryData, mDatabaseKDB.attachmentPool)
BufferedOutputStream(binaryData.getOutputDataStream(mDatabaseKDB.binaryCache)).use { outputStream ->
outputStream.write(mDatabaseKDB.defaultUserName.toByteArray())
}
}
private fun setDatabaseColor(entryKDB: EntryKDB) {
val binaryData = mDatabaseKDB.buildNewAttachment()
entryKDB.putBinary(binaryData, mDatabaseKDB.attachmentPool)
BufferedOutputStream(binaryData.getOutputDataStream(mDatabaseKDB.binaryCache)).use { outputStream ->
outputStream.write(mDatabaseKDB.color!!)
}
}
private fun getHeaderHashBuffer(headerDigest: ByteArray): ByteArray? { private fun getHeaderHashBuffer(headerDigest: ByteArray): ByteArray? {
return try { return try {
val byteArrayOutputStream = ByteArrayOutputStream() val byteArrayOutputStream = ByteArrayOutputStream()

View File

@@ -30,8 +30,8 @@ import androidx.preference.PreferenceCategory
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import com.kunzisoft.androidclearchroma.ChromaUtil import com.kunzisoft.androidclearchroma.ChromaUtil
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
@@ -165,28 +165,18 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
// Database default username // Database default username
dbDefaultUsernamePref = findPreference(getString(R.string.database_default_username_key)) dbDefaultUsernamePref = findPreference(getString(R.string.database_default_username_key))
if (database.allowDefaultUsername) { dbDefaultUsernamePref?.summary = database.defaultUsername
dbDefaultUsernamePref?.summary = database.defaultUsername
} else {
dbDefaultUsernamePref?.isEnabled = false
// TODO dbGeneralPrefCategory?.removePreference(dbDefaultUsername)
}
// Database custom color // Database custom color
dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key)) dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key))
if (database.allowCustomColor) { dbCustomColorPref?.apply {
dbCustomColorPref?.apply { try {
try { color = Color.parseColor(database.customColor)
color = Color.parseColor(database.customColor) summary = database.customColor
summary = database.customColor } catch (e: Exception) {
} catch (e: Exception) { color = DialogColorPreference.DISABLE_COLOR
color = DialogColorPreference.DISABLE_COLOR summary = ""
summary = ""
}
} }
} else {
dbCustomColorPref?.isEnabled = false
// TODO dbGeneralPrefCategory?.removePreference(dbCustomColorPref)
} }
// Version // Version