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

View File

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

View File

@@ -61,6 +61,9 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
return listOf(BACKUP_FOLDER_TITLE)
}
var defaultUserName: String = ""
var color: Int? = null
override val kdfEngine: KdfEngine
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.BinaryData
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.node.NodeId
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
@@ -60,8 +61,7 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
private var binaryDataId: Int? = null
// Determine if this is a MetaStream entry
val isMetaStream: Boolean
get() {
fun isMetaStream(): Boolean {
if (notes.isEmpty()) return false
if (binaryDescription != PMS_ID_BINDESC) return false
if (title.isEmpty()) return false
@@ -73,6 +73,32 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
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> {
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_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
val CREATOR: Parcelable.Creator<EntryKDB> = object : Parcelable.Creator<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.NodeIdUUID
import com.kunzisoft.keepass.database.exception.*
import com.kunzisoft.keepass.database.file.DatabaseHeader
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.*
@@ -300,6 +299,22 @@ class DatabaseInputKDB(cacheDirectory: File,
}
newEntry?.let { 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++
newEntry = null
}

View File

@@ -47,6 +47,9 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
private var mGroupList = mutableListOf<GroupKDB>()
private var mEntryList = mutableListOf<EntryKDB>()
private var mDefaultUsernameAdded = false
private var mDatabaseColorAdded = false
@Throws(DatabaseOutputException::class)
fun getFinalKey(header: DatabaseHeader): ByteArray? {
try {
@@ -94,8 +97,7 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
} finally {
// Add again the virtual root group for better management
mDatabaseKDB.rootGroup = rootGroup
mGroupList.clear()
mEntryList.clear()
clearParser()
}
}
@@ -211,9 +213,14 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
}
}
private fun sortNodesForOutput() {
private fun clearParser() {
mGroupList.clear()
mEntryList.clear()
mDefaultUsernameAdded = false
}
private fun sortNodesForOutput() {
clearParser()
// Rebuild list according to sorting order removing any orphaned groups
// Do not keep root
mDatabaseKDB.rootGroup?.getChildGroups()?.let { rootSubGroups ->
@@ -228,7 +235,39 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
mGroupList.add(group)
for (childEntry in group.getChildEntries()) {
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
@@ -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? {
return try {
val byteArrayOutputStream = ByteArrayOutputStream()

View File

@@ -30,8 +30,8 @@ import androidx.preference.PreferenceCategory
import androidx.preference.SwitchPreference
import com.kunzisoft.androidclearchroma.ChromaUtil
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
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.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
@@ -165,16 +165,10 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
// Database default username
dbDefaultUsernamePref = findPreference(getString(R.string.database_default_username_key))
if (database.allowDefaultUsername) {
dbDefaultUsernamePref?.summary = database.defaultUsername
} else {
dbDefaultUsernamePref?.isEnabled = false
// TODO dbGeneralPrefCategory?.removePreference(dbDefaultUsername)
}
// Database custom color
dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key))
if (database.allowCustomColor) {
dbCustomColorPref?.apply {
try {
color = Color.parseColor(database.customColor)
@@ -184,10 +178,6 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
summary = ""
}
}
} else {
dbCustomColorPref?.isEnabled = false
// TODO dbGeneralPrefCategory?.removePreference(dbCustomColorPref)
}
// Version
findPreference<Preference>(getString(R.string.database_version_key))