diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt index 0a4ede494..25001b55a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -212,10 +212,12 @@ class EntryActivity : LockingHideActivity() { entryContentsView?.assignComment(entry.notes) // Assign custom fields - if (entry.allowExtraFields()) { + if (entry.allowCustomFields()) { entryContentsView?.clearExtraFields() - entry.fields.doActionToAllCustomProtectedField { label, value -> + for (element in entry.customFields.entries) { + val label = element.key + val value = element.value val allowCopyProtectedField = !value.isProtected || allowCopyPasswordAndProtectedFields if (allowCopyProtectedField) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 59c5dc07f..59599981d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -152,7 +152,7 @@ class EntryEditActivity : LockingHideActivity(), saveView = findViewById(R.id.entry_edit_save) saveView?.setOnClickListener { saveEntry() } - entryEditContentsView?.allowCustomField(mNewEntry?.allowExtraFields() == true) { addNewCustomField() } + entryEditContentsView?.allowCustomField(mNewEntry?.allowCustomFields() == true) { addNewCustomField() } // Verify the education views entryEditActivityEducation = EntryEditActivityEducation(this) @@ -172,8 +172,8 @@ class EntryEditActivity : LockingHideActivity(), url = newEntry.url password = newEntry.password notes = newEntry.notes - newEntry.fields.doActionToAllCustomProtectedField { key, value -> - addNewCustomField(key, value) + for (entry in newEntry.customFields.entries) { + addNewCustomField(entry.key, entry.value) } } } @@ -307,7 +307,7 @@ class EntryEditActivity : LockingHideActivity(), ) if (!generatePasswordEducationPerformed) { // entryNewFieldEducationPerformed - mNewEntry != null && mNewEntry!!.allowExtraFields() && !mNewEntry!!.containsCustomFields() + mNewEntry != null && mNewEntry!!.allowCustomFields() && mNewEntry!!.customFields.isEmpty() && addNewFieldView != null && addNewFieldView.visibility == View.VISIBLE && entryEditActivityEducation.checkAndPerformedEntryNewFieldEducation( addNewFieldView, diff --git a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt index 370cc207e..d4b1c02dd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt @@ -24,8 +24,8 @@ class EntryCursorV4 : EntryCursor() { entry.notes )) - entry.fields.doActionToAllCustomProtectedField { key, value -> - extraFieldCursor.addExtraField(entryId, key, value) + for (element in entry.customFields.entries) { + extraFieldCursor.addExtraField(entryId, element.key, element.value) } entryId++ diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt index 7eb93df04..676f2ceb0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt @@ -227,42 +227,18 @@ class EntryVersioned : NodeVersioned, PwEntryInterface { } /** - * Retrieve extra fields to show, key is the label, value is the value of field + * Retrieve custom fields to show, key is the label, value is the value of field (protected or not) * @return Map of label/value */ - val fields: ExtraFields - get() = pwEntryV4?.fields ?: ExtraFields() + val customFields: HashMap + get() = pwEntryV4?.customFields ?: HashMap() /** - * To redefine if version of entry allow extra field, - * @return true if entry allows extra field + * To redefine if version of entry allow custom field, + * @return true if entry allows custom field */ - fun allowExtraFields(): Boolean { - return pwEntryV4?.allowExtraFields() ?: false - } - - /** - * If entry contains extra fields - * @return true if there is extra fields - */ - fun containsCustomFields(): Boolean { - return pwEntryV4?.containsCustomFields() ?: false - } - - /** - * If entry contains extra fields that are protected - * @return true if there is extra fields protected - */ - fun containsCustomFieldsProtected(): Boolean { - return pwEntryV4?.containsCustomFieldsProtected() ?: false - } - - /** - * If entry contains extra fields that are not protected - * @return true if there is extra fields not protected - */ - fun containsCustomFieldsNotProtected(): Boolean { - return pwEntryV4?.containsCustomFieldsNotProtected() ?: false + fun allowCustomFields(): Boolean { + return pwEntryV4?.allowCustomFields() ?: false } /** @@ -274,13 +250,6 @@ class EntryVersioned : NodeVersioned, PwEntryInterface { pwEntryV4?.addExtraField(label, value) } - /** - * Delete all custom fields - */ - fun removeAllCustomFields() { - pwEntryV4?.removeAllCustomFields() - } - fun startToManageFieldReferences(db: PwDatabaseV4) { pwEntryV4?.startToManageFieldReferences(db) } @@ -327,11 +296,9 @@ class EntryVersioned : NodeVersioned, PwEntryInterface { entryInfo.password = password entryInfo.url = url entryInfo.notes = notes - if (containsCustomFields()) { - fields.doActionToAllCustomProtectedField { key, value -> - entryInfo.customFields.add( - Field(key, value)) - } + for (entry in customFields.entries) { + entryInfo.customFields.add( + Field(entry.key, entry.value)) } if (!raw) database?.stopManageEntry(this) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/ExtraFields.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/ExtraFields.kt deleted file mode 100644 index cbbec73f1..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/ExtraFields.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2018 Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KeePass DX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePass DX. If not, see . - * - */ -package com.kunzisoft.keepass.database.element - -import android.os.Parcel -import android.os.Parcelable - -import com.kunzisoft.keepass.database.element.security.ProtectedString -import com.kunzisoft.keepass.utils.MemUtil - -import java.util.HashMap - -import com.kunzisoft.keepass.database.element.PwEntryV4.Companion.STR_TITLE -import com.kunzisoft.keepass.database.element.PwEntryV4.Companion.STR_USERNAME -import com.kunzisoft.keepass.database.element.PwEntryV4.Companion.STR_PASSWORD -import com.kunzisoft.keepass.database.element.PwEntryV4.Companion.STR_URL -import com.kunzisoft.keepass.database.element.PwEntryV4.Companion.STR_NOTES - -class ExtraFields : Parcelable { - - private var fields: MutableMap = HashMap() - - /** - * @return list of standard and customized fields - */ - val listOfAllFields: Map - get() = fields - - private val customProtectedFields: Map - get() { - val protectedFields = HashMap() - if (fields.isNotEmpty()) { - for ((key, value) in fields) { - if (isNotStandardField(key)) { - protectedFields[key] = value - } - } - } - return protectedFields - } - - constructor() - - constructor(extraFields: ExtraFields) : this() { - for ((key, value) in extraFields.fields) { - fields[key] = ProtectedString(value) - } - } - - constructor(parcel: Parcel) { - fields = MemUtil.readStringParcelableMap(parcel, ProtectedString::class.java) - } - - override fun describeContents(): Int { - return 0 - } - - override fun writeToParcel(dest: Parcel, flags: Int) { - MemUtil.writeStringParcelableMap(dest, flags, fields) - } - - fun containsCustomFields(): Boolean { - return customProtectedFields.keys.isNotEmpty() - } - - fun containsCustomFieldsProtected(): Boolean { - for ((_, value) in customProtectedFields) { - if (value.isProtected) - return true - } - return false - } - - fun containsCustomFieldsNotProtected(): Boolean { - for ((_, value) in customProtectedFields) { - if (!value.isProtected) - return true - } - return false - } - - fun getProtectedStringValue(key: String): String { - val value = fields[key] ?: return "" - return value.toString() - } - - fun putProtectedString(key: String, protectedString: ProtectedString) { - fields[key] = protectedString - } - - fun putProtectedString(key: String, value: String, protect: Boolean) { - val ps = ProtectedString(protect, value) - fields[key] = ps - } - - fun doActionToAllCustomProtectedField(actionProtected: (key: String, value: ProtectedString)-> Unit) { - for ((key, value) in customProtectedFields) { - actionProtected.invoke(key, value) - } - } - - interface ActionProtected { - fun doAction(key: String, value: ProtectedString) - } - - fun removeAllCustomFields() { - val iterator = fields.entries.iterator() - while (iterator.hasNext()) { - val pair = iterator.next() - if (isNotStandardField(pair.key)) { - iterator.remove() - } - } - } - - companion object { - - @JvmField - val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): ExtraFields { - return ExtraFields(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } - - private fun isNotStandardField(key: String): Boolean { - return (key != STR_TITLE && key != STR_USERNAME - && key != STR_PASSWORD && key != STR_URL - && key != STR_NOTES) - } - } -} diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt index 9764173eb..42027dc8c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt @@ -48,8 +48,7 @@ class PwEntryV4 : PwEntry, NodeV4Interface { } var iconCustom = PwIconCustom.UNKNOWN_ICON private var customData = HashMap() - var fields = ExtraFields() - private set + var fields = HashMap() val binaries = HashMap() var foregroundColor = "" var backgroundColor = "" @@ -63,9 +62,9 @@ class PwEntryV4 : PwEntry, NodeV4Interface { get() { var size = FIXED_LENGTH_SIZE - for ((key, value) in fields.listOfAllFields) { - size += key.length.toLong() - size += value.length().toLong() + for (entry in fields.entries) { + size += entry.key.length.toLong() + size += entry.value.length().toLong() } for ((key, value) in binaries) { @@ -96,7 +95,7 @@ class PwEntryV4 : PwEntry, NodeV4Interface { usageCount = parcel.readLong() locationChanged = parcel.readParcelable(PwDate::class.java.classLoader) customData = MemUtil.readStringParcelableMap(parcel) - fields = parcel.readParcelable(ExtraFields::class.java.classLoader) + fields = MemUtil.readStringParcelableMap(parcel, ProtectedString::class.java) // TODO binaries = MemUtil.readStringParcelableMap(parcel, ProtectedBinary.class); foregroundColor = parcel.readString() backgroundColor = parcel.readString() @@ -114,7 +113,7 @@ class PwEntryV4 : PwEntry, NodeV4Interface { dest.writeLong(usageCount) dest.writeParcelable(locationChanged, flags) MemUtil.writeStringParcelableMap(dest, customData) - dest.writeParcelable(fields, flags) + MemUtil.writeStringParcelableMap(dest, flags, fields) // TODO MemUtil.writeStringParcelableMap(dest, flags, binaries); dest.writeString(foregroundColor) dest.writeString(backgroundColor) @@ -137,13 +136,11 @@ class PwEntryV4 : PwEntry, NodeV4Interface { locationChanged = PwDate(source.locationChanged) // Add all custom elements in map customData.clear() - for ((key, value) in source.customData) { - customData[key] = value - } - fields = ExtraFields(source.fields) - for ((key, value) in source.binaries) { - binaries[key] = ProtectedBinary(value) - } + customData.putAll(source.customData) + fields.clear() + fields.putAll(source.fields) + binaries.clear() + binaries.putAll(source.binaries) foregroundColor = source.foregroundColor backgroundColor = source.backgroundColor overrideURL = source.overrideURL @@ -188,17 +185,18 @@ class PwEntryV4 : PwEntry, NodeV4Interface { * @return */ private fun decodeRefKey(decodeRef: Boolean, key: String): String { - val text = fields.getProtectedStringValue(key) - return if (decodeRef) { - if (mDatabase == null) text else SprEngineV4().compile(text, this, mDatabase!!) - } else text + return fields[key]?.toString()?.let { text -> + return if (decodeRef) { + if (mDatabase == null) text else SprEngineV4().compile(text, this, mDatabase!!) + } else text + } ?: "" } override var title: String get() = decodeRefKey(mDecodeRef, STR_TITLE) set(value) { val protect = mDatabase != null && mDatabase!!.memoryProtection.protectTitle - fields.putProtectedString(STR_TITLE, value, protect) + fields[STR_TITLE] = ProtectedString(protect, value) } override val type: Type @@ -208,28 +206,28 @@ class PwEntryV4 : PwEntry, NodeV4Interface { get() = decodeRefKey(mDecodeRef, STR_USERNAME) set(value) { val protect = mDatabase != null && mDatabase!!.memoryProtection.protectUserName - fields.putProtectedString(STR_USERNAME, value, protect) + fields[STR_USERNAME] = ProtectedString(protect, value) } override var password: String get() = decodeRefKey(mDecodeRef, STR_PASSWORD) set(value) { val protect = mDatabase != null && mDatabase!!.memoryProtection.protectPassword - fields.putProtectedString(STR_PASSWORD, value, protect) + fields[STR_PASSWORD] = ProtectedString(protect, value) } override var url get() = decodeRefKey(mDecodeRef, STR_URL) set(value) { val protect = mDatabase != null && mDatabase!!.memoryProtection.protectUrl - fields.putProtectedString(STR_URL, value, protect) + fields[STR_URL] = ProtectedString(protect, value) } override var notes: String get() = decodeRefKey(mDecodeRef, STR_NOTES) set(value) { val protect = mDatabase != null && mDatabase!!.memoryProtection.protectNotes - fields.putProtectedString(STR_NOTES, value, protect) + fields[STR_NOTES] = ProtectedString(protect, value) } override var usageCount: Long = 0 @@ -240,28 +238,33 @@ class PwEntryV4 : PwEntry, NodeV4Interface { locationChanged = PwDate() } - fun allowExtraFields(): Boolean { + private fun isStandardField(key: String): Boolean { + return (key == STR_TITLE + || key == STR_USERNAME + || key == STR_PASSWORD + || key == STR_URL + || key == STR_NOTES) + } + + var customFields = HashMap() + get() { + field.clear() + for (entry in fields.entries) { + val key = entry.key + val value = entry.value + if (!isStandardField(entry.key)) { + field[key] = ProtectedString(value.isProtected, decodeRefKey(mDecodeRef, key)) + } + } + return field + } + + fun allowCustomFields(): Boolean { return true } - fun containsCustomFields(): Boolean { - return fields.containsCustomFields() - } - - fun containsCustomFieldsProtected(): Boolean { - return fields.containsCustomFieldsProtected() - } - - fun containsCustomFieldsNotProtected(): Boolean { - return fields.containsCustomFieldsNotProtected() - } - fun addExtraField(label: String, value: ProtectedString) { - fields.putProtectedString(label, value) - } - - fun removeAllCustomFields() { - fields.removeAllCustomFields() + fields[label] = value } fun putProtectedBinary(key: String, value: ProtectedBinary) { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/save/PwDbV4Output.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/save/PwDbV4Output.kt index 8aac41bbf..45aae77cd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/save/PwDbV4Output.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/save/PwDbV4Output.kt @@ -349,7 +349,7 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt writeList(PwDatabaseV4XML.ElemTimes, entry) - writeList(entry.fields.listOfAllFields, true) + writeList(entry.fields, true) writeList(entry.binaries) writeList(PwDatabaseV4XML.ElemAutoType, entry.autoType) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/search/iterator/EntrySearchStringIteratorV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/search/iterator/EntrySearchStringIteratorV4.kt index ba72b0413..564e5b4f4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/search/iterator/EntrySearchStringIteratorV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/search/iterator/EntrySearchStringIteratorV4.kt @@ -33,13 +33,13 @@ class EntrySearchStringIteratorV4 : EntrySearchStringIterator { constructor(entry: PwEntryV4) { this.mSearchParametersV4 = SearchParametersV4() - mSetIterator = entry.fields.listOfAllFields.entries.iterator() + mSetIterator = entry.fields.entries.iterator() advance() } constructor(entry: PwEntryV4, searchParametersV4: SearchParametersV4) { this.mSearchParametersV4 = searchParametersV4 - mSetIterator = entry.fields.listOfAllFields.entries.iterator() + mSetIterator = entry.fields.entries.iterator() advance() }