Fix many template options

This commit is contained in:
J-Jamet
2021-07-07 14:06:26 +02:00
parent 1947fc3e83
commit 7595f113ec
6 changed files with 177 additions and 50 deletions

View File

@@ -120,7 +120,7 @@ class Template : Parcelable {
TemplateAttributeType.TEXT,
true,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.NUMBER_LINES, "3")
put(TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR, "3")
},
TemplateAttributeAction.PASSWORD_GENERATION
)
@@ -129,21 +129,21 @@ class Template : Parcelable {
TemplateAttributeType.TEXT,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.LINKIFY, "true")
put(TemplateAttributeOption.TEXT_LINK_ATTR, "true")
})
val EXPIRATION_ATTRIBUTE = TemplateAttribute(
TemplateField.LABEL_EXPIRATION,
TemplateAttributeType.DATETIME,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.DATETIME_FORMAT, "datetime")
put(TemplateAttributeOption.DATETIME_FORMAT_ATTR, "datetime")
})
val NOTES_ATTRIBUTE = TemplateAttribute(
TemplateField.LABEL_NOTES,
TemplateAttributeType.TEXT,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.NUMBER_LINES, "-1")
put(TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR, "-1")
})
val STANDARD: Template

View File

@@ -13,33 +13,57 @@ class TemplateAttributeOption {
* Integer, can be "-1" or "many" to infinite value
* "1" if not defined
*/
const val NUMBER_LINES = "lines"
const val NUMBER_LINES_MANY = "many"
const val TEXT_NUMBER_LINES_ATTR = "lines"
const val TEXT_NUMBER_LINES_VALUE_MANY = "many"
const val TEXT_NUMBER_LINES_VALUE_DEFAULT = "1"
/**
* Applicable to type TEXT
* Integer, can be "-1" or "many" to infinite value
* "1" if not defined
*/
const val TEXT_NUMBER_CHARS_ATTR = "chars"
const val TEXT_NUMBER_CHARS_VALUE_DEFAULT = "many"
/**
* Applicable to type TEXT
* Boolean ("true" or "false")
* "true" if not defined
*/
const val LINKIFY = "linkify"
const val TEXT_LINK_ATTR = "link"
const val TEXT_LINK_VALUE_DEFAULT = "false"
/**
* Applicable to type LIST
* List of items, separator is '|'
*/
const val LIST_ITEMS = "items"
/**
* Applicable to type LIST
* Default string element representation
* 1st element if not defined
*/
const val LIST_DEFAULT_ITEM_ATTR = "default"
const val LIST_DEFAULT_ITEM_VALUE_DEFAULT = "1"
/**
* Applicable to type DATETIME
* String ("date" or "time" or "datetime" or based on https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)
* "datetime" if not defined
*/
const val DATETIME_FORMAT = "format"
const val DATETIME_FORMAT_DATE = "date"
const val DATETIME_FORMAT_TIME = "time"
const val DATETIME_FORMAT_MONTH_YEAR = "MM yy"
const val DATETIME_FORMAT_ATTR = "format"
const val DATETIME_FORMAT_VALUE_DATE = "date"
const val DATETIME_FORMAT_VALUE_TIME = "time"
const val DATETIME_FORMAT_VALUE_DEFAULT = "datetime"
fun getNumberLines(options: MutableMap<String, String>): Int {
return try {
val value = options[NUMBER_LINES]
if (value == NUMBER_LINES_MANY)
val value = options[TEXT_NUMBER_LINES_ATTR]
if (value == TEXT_NUMBER_LINES_VALUE_MANY)
-1
else
options[NUMBER_LINES]?.toInt() ?: 1
options[TEXT_NUMBER_LINES_ATTR]?.toInt() ?: 1
} catch (e: Exception) {
1
}
@@ -47,16 +71,24 @@ class TemplateAttributeOption {
fun isLinkify(options: MutableMap<String, String>): Boolean {
return try {
options[LINKIFY]?.toBoolean() ?: true
options[TEXT_LINK_ATTR]?.toBoolean() ?: true
} catch (e: Exception) {
true
}
}
fun listItemsFromString(itemsString: String): List<String> {
return itemsString.split("|")
}
fun stringFromListItems(items: List<String>): String {
return items.joinToString("|")
}
fun getDateFormat(options: MutableMap<String, String>): DateInstant.Type {
return when (options[DATETIME_FORMAT]) {
DATETIME_FORMAT_DATE -> DateInstant.Type.DATE
DATETIME_FORMAT_TIME -> DateInstant.Type.TIME
return when (options[DATETIME_FORMAT_ATTR]) {
DATETIME_FORMAT_VALUE_DATE -> DateInstant.Type.DATE
DATETIME_FORMAT_VALUE_TIME -> DateInstant.Type.TIME
else -> DateInstant.Type.DATE_TIME
}
}
@@ -87,6 +119,8 @@ class TemplateAttributeOption {
optionsString += ","
first = false
optionsString += "${URLEncoder.encode(key, "utf-8")}:${URLEncoder.encode(value, "utf-8")}"
// "|" is ok and part of a list
optionsString = optionsString.replace("%7C", "|")
}
optionsString += "}"
}

View File

@@ -19,14 +19,16 @@
package com.kunzisoft.keepass.database.element.template
enum class TemplateAttributeType(val label: String) {
TEXT("Text"),
DATETIME("DateTime"),
DIVIDER("Divider");
TEXT("text"),
LIST("list"),
DATETIME("datetime"),
DIVIDER("divider");
companion object {
fun getFromString(label: String): TemplateAttributeType {
return when {
label.contains(TEXT.label, true) -> TEXT
label.contains(LIST.label, true) -> LIST
label.contains(DATETIME.label, true) -> DATETIME
label.contains(DIVIDER.label, true) -> DIVIDER
else -> TEXT

View File

@@ -14,7 +14,7 @@ class TemplateBuilder {
TemplateAttributeType.TEXT,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.NUMBER_LINES, TemplateAttributeOption.NUMBER_LINES_MANY)
put(TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR, TemplateAttributeOption.TEXT_NUMBER_LINES_VALUE_MANY)
})
private val holderAttribute = TemplateAttribute(TemplateField.LABEL_HOLDER, TemplateAttributeType.TEXT)
private val numberAttribute = TemplateAttribute(TemplateField.LABEL_NUMBER, TemplateAttributeType.TEXT)
@@ -25,16 +25,13 @@ class TemplateBuilder {
private val dateOfIssueAttribute = TemplateAttribute(
TemplateField.LABEL_DATE_OF_ISSUE,
TemplateAttributeType.DATETIME,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.DATETIME_FORMAT, TemplateAttributeOption.DATETIME_FORMAT_DATE)
})
false)
private val expirationDateAttribute = TemplateAttribute(
TemplateField.LABEL_EXPIRATION,
TemplateAttributeType.DATETIME,
false,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.DATETIME_FORMAT, TemplateAttributeOption.DATETIME_FORMAT_DATE)
put(TemplateAttributeOption.DATETIME_FORMAT_ATTR, TemplateAttributeOption.DATETIME_FORMAT_VALUE_DATE)
})
private val emailAddressAttribute = TemplateAttribute(TemplateField.LABEL_EMAIL_ADDRESS, TemplateAttributeType.TEXT)
private val passwordAttribute = TemplateAttribute(TemplateField.LABEL_PASSWORD, TemplateAttributeType.TEXT, true)

View File

@@ -81,7 +81,7 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
val label = field.name
val value = field.protectedValue.stringValue
when {
label.startsWith(TEMPLATE_ATTRIBUTE_POSITION_PREFIX) -> {
label.startsWith(TEMPLATE_ATTRIBUTE_POSITION_PREFIX, true) -> {
try {
val attributeName = label.substring(TEMPLATE_ATTRIBUTE_POSITION_PREFIX.length)
val attribute = getOrRetrieveAttributeFromName(attributes, attributeName)
@@ -91,7 +91,7 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
Log.e(TAG, "Unable to retrieve template position", e)
}
}
label.startsWith(TEMPLATE_ATTRIBUTE_TITLE_PREFIX) -> {
label.startsWith(TEMPLATE_ATTRIBUTE_TITLE_PREFIX, true) -> {
try {
val attributeName = label.substring(TEMPLATE_ATTRIBUTE_TITLE_PREFIX.length)
val attribute = getOrRetrieveAttributeFromName(attributes, attributeName)
@@ -101,7 +101,7 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
Log.e(TAG, "Unable to retrieve template title", e)
}
}
label.startsWith(TEMPLATE_ATTRIBUTE_TYPE_PREFIX) -> {
label.startsWith(TEMPLATE_ATTRIBUTE_TYPE_PREFIX, true) -> {
try {
val attributeName = label.substring(TEMPLATE_ATTRIBUTE_TYPE_PREFIX.length)
val attribute = getOrRetrieveAttributeFromName(attributes, attributeName)
@@ -109,32 +109,42 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
attribute.attribute.protected = true
}
when {
value.contains(TEMPLATE_ATTRIBUTE_TYPE_INLINE_URL, true) -> {
attribute.attribute.type = TemplateAttributeType.TEXT
attribute.attribute.options[TemplateAttributeOption.TEXT_LINK_ATTR] =
true.toString()
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_INLINE, true) ||
value.contains(TEMPLATE_ATTRIBUTE_TYPE_POPOUT, true) -> {
attribute.attribute.type = TemplateAttributeType.TEXT
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_MULTILINE, true) ||
value.contains(TEMPLATE_ATTRIBUTE_TYPE_RICH_TEXTBOX, true) -> {
value.contains(TEMPLATE_ATTRIBUTE_TYPE_MULTILINE, true) -> {
attribute.attribute.type = TemplateAttributeType.TEXT
attribute.attribute.options[TemplateAttributeOption.NUMBER_LINES] =
TemplateAttributeOption.NUMBER_LINES_MANY
attribute.attribute.options[TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR] =
TemplateAttributeOption.TEXT_NUMBER_LINES_VALUE_MANY
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_RICH_TEXTBOX, true) -> {
attribute.attribute.type = TemplateAttributeType.TEXT
attribute.attribute.options[TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR] =
TemplateAttributeOption.TEXT_NUMBER_LINES_VALUE_MANY
attribute.attribute.options[TemplateAttributeOption.TEXT_LINK_ATTR] =
true.toString()
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_LISTBOX, true) -> {
attribute.attribute.type = TemplateAttributeType.LIST
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_DATE_TIME, true) -> {
attribute.attribute.type = TemplateAttributeType.DATETIME
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_DATE, true) -> {
attribute.attribute.type = TemplateAttributeType.DATETIME
attribute.attribute.options[TemplateAttributeOption.DATETIME_FORMAT] =
TemplateAttributeOption.DATETIME_FORMAT_DATE
attribute.attribute.options[TemplateAttributeOption.DATETIME_FORMAT_ATTR] =
TemplateAttributeOption.DATETIME_FORMAT_VALUE_DATE
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_TIME, true) -> {
attribute.attribute.type = TemplateAttributeType.DATETIME
attribute.attribute.options[TemplateAttributeOption.DATETIME_FORMAT] =
TemplateAttributeOption.DATETIME_FORMAT_TIME
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_LISTBOX, true) -> {
attribute.attribute.type = TemplateAttributeType.TEXT
// TODO List box
attribute.attribute.options[TemplateAttributeOption.DATETIME_FORMAT_ATTR] =
TemplateAttributeOption.DATETIME_FORMAT_VALUE_TIME
}
value.contains(TEMPLATE_ATTRIBUTE_TYPE_DIVIDER, true) -> {
attribute.attribute.type = TemplateAttributeType.DIVIDER
@@ -145,13 +155,88 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
Log.e(TAG, "Unable to retrieve template type", e)
}
}
label.startsWith(TEMPLATE_ATTRIBUTE_OPTIONS_PREFIX, true) -> {
try {
val attributeName = label.substring(TEMPLATE_ATTRIBUTE_OPTIONS_PREFIX.length)
val attribute = getOrRetrieveAttributeFromName(attributes, attributeName)
if (value.isNotEmpty()) {
attribute.attribute.options[TEMPLATE_ATTRIBUTE_OPTIONS_DEFAULT] = value
}
entryCopy.removeField(field.name)
} catch (e: Exception) {
Log.e(TAG, "Unable to retrieve template options", e)
}
}
}
}
val newFields = arrayOfNulls<Field>(attributes.size)
attributes.values.forEach {
newFields[it.position] = Field(buildTemplateEntryField(it.attribute))
val attribute = it.attribute
// Recognize each default option
attribute.options[TEMPLATE_ATTRIBUTE_OPTIONS_DEFAULT]?.let { defaultOption ->
when (attribute.type) {
TemplateAttributeType.TEXT -> {
try {
val linesString = attribute.options[TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR]
if (linesString == null || linesString == "1") {
// If one line, default attribute option is number of chars
attribute.options[TemplateAttributeOption.TEXT_NUMBER_CHARS_ATTR] =
defaultOption
} else {
// else it's number of lines
attribute.options[TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR] =
defaultOption
}
} catch (e: Exception) {
Log.e(TAG, "Unable to transform default text option", e)
}
}
TemplateAttributeType.LIST -> {
try {
// Default attribute option is items of the list
val items = defaultOption.split(",")
attribute.options[TemplateAttributeOption.LIST_ITEMS] =
TemplateAttributeOption.stringFromListItems(items)
// TODO Add default item
} catch (e: Exception) {
Log.e(TAG, "Unable to transform default list option", e)
}
}
TemplateAttributeType.DATETIME -> {
try {
// Default attribute option is datetime, date or time
when {
defaultOption.equals(TEMPLATE_ATTRIBUTE_TYPE_DATE_TIME, true) -> {
// Do not add option if it's datetime
}
defaultOption.equals(TEMPLATE_ATTRIBUTE_TYPE_DATE, true) -> {
attribute.options[TemplateAttributeOption.DATETIME_FORMAT_ATTR] =
TemplateAttributeOption.DATETIME_FORMAT_VALUE_DATE
}
defaultOption.equals(TEMPLATE_ATTRIBUTE_TYPE_TIME, true) -> {
attribute.options[TemplateAttributeOption.DATETIME_FORMAT_ATTR] =
TemplateAttributeOption.DATETIME_FORMAT_VALUE_TIME
}
}
} catch (e: Exception) {
Log.e(TAG, "Unable to transform default datetime", e)
}
}
TemplateAttributeType.DIVIDER -> {
// No option here
}
}
attribute.options.remove(TEMPLATE_ATTRIBUTE_OPTIONS_DEFAULT)
}
// Add position for each attribute
newFields[it.position] = Field(buildTemplateEntryField(attribute))
}
// Add custom fields to entry
newFields.forEach { field ->
field?.let {
entryCopy.putField(field)
@@ -193,15 +278,18 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
// Add protected string if needed
var typeString: String = when {
value.stringValue.contains(TemplateAttributeType.TEXT.label, true) -> {
when (TemplateAttributeOption.getOptionsFromString(field.protectedValue.stringValue)[TemplateAttributeOption.NUMBER_LINES]) {
TemplateAttributeOption.NUMBER_LINES_MANY -> TEMPLATE_ATTRIBUTE_TYPE_MULTILINE
when (TemplateAttributeOption.getOptionsFromString(field.protectedValue.stringValue)[TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR]) {
TemplateAttributeOption.TEXT_NUMBER_LINES_VALUE_MANY -> TEMPLATE_ATTRIBUTE_TYPE_MULTILINE
else -> TEMPLATE_ATTRIBUTE_TYPE_INLINE
}
}
value.stringValue.contains(TemplateAttributeType.LIST.label, true) -> {
TEMPLATE_ATTRIBUTE_TYPE_LISTBOX
}
value.stringValue.contains(TemplateAttributeType.DATETIME.label, true) -> {
when (TemplateAttributeOption.getOptionsFromString(field.protectedValue.stringValue)[TemplateAttributeOption.DATETIME_FORMAT]) {
TemplateAttributeOption.DATETIME_FORMAT_DATE -> TEMPLATE_ATTRIBUTE_TYPE_DATE
TemplateAttributeOption.DATETIME_FORMAT_TIME -> TEMPLATE_ATTRIBUTE_TYPE_TIME
when (TemplateAttributeOption.getOptionsFromString(field.protectedValue.stringValue)[TemplateAttributeOption.DATETIME_FORMAT_ATTR]) {
TemplateAttributeOption.DATETIME_FORMAT_VALUE_DATE -> TEMPLATE_ATTRIBUTE_TYPE_DATE
TemplateAttributeOption.DATETIME_FORMAT_VALUE_TIME -> TEMPLATE_ATTRIBUTE_TYPE_TIME
else -> TEMPLATE_ATTRIBUTE_TYPE_DATE_TIME
}
}
@@ -248,14 +336,17 @@ class TemplateEngineCompatible(database: DatabaseKDBX): TemplateEngine(database)
private const val TEMPLATE_ATTRIBUTE_POSITION_PREFIX = "_etm_position"
private const val TEMPLATE_ATTRIBUTE_TITLE_PREFIX = "_etm_title"
private const val TEMPLATE_ATTRIBUTE_TYPE_PREFIX = "_etm_type"
private const val TEMPLATE_ATTRIBUTE_OPTIONS_PREFIX = "_etm_options"
private const val TEMPLATE_ATTRIBUTE_OPTIONS_DEFAULT = "default_option"
private const val TEMPLATE_ATTRIBUTE_TYPE_PROTECTED = "Protected"
private const val TEMPLATE_ATTRIBUTE_TYPE_INLINE = "Inline"
private const val TEMPLATE_ATTRIBUTE_TYPE_INLINE_URL = "Inline URL"
private const val TEMPLATE_ATTRIBUTE_TYPE_MULTILINE = "Multiline"
private const val TEMPLATE_ATTRIBUTE_TYPE_LISTBOX = "Listbox"
private const val TEMPLATE_ATTRIBUTE_TYPE_DATE_TIME = "Date Time"
private const val TEMPLATE_ATTRIBUTE_TYPE_DATE = "Date"
private const val TEMPLATE_ATTRIBUTE_TYPE_TIME = "Time"
private const val TEMPLATE_ATTRIBUTE_TYPE_DIVIDER = "Divider"
private const val TEMPLATE_ATTRIBUTE_TYPE_LISTBOX = "Listbox"
private const val TEMPLATE_ATTRIBUTE_TYPE_POPOUT = "Popout"
private const val TEMPLATE_ATTRIBUTE_TYPE_RICH_TEXTBOX = "Rich Textbox"

View File

@@ -184,7 +184,7 @@ abstract class TemplateAbstractView<TEntryFieldView: GenericEntryFieldView, TDat
TemplateAttributeType.TEXT,
field.protectedValue.isProtected,
LinkedHashMap<String, String>().apply {
put(TemplateAttributeOption.NUMBER_LINES, "3")
put(TemplateAttributeOption.TEXT_NUMBER_LINES_ATTR, "3")
},
TemplateAttributeAction.CUSTOM_EDITION,
field.protectedValue.stringValue)
@@ -199,6 +199,9 @@ abstract class TemplateAbstractView<TEntryFieldView: GenericEntryFieldView, TDat
TemplateAttributeType.TEXT -> {
buildLinearTextView(templateAttribute, field) as View?
}
TemplateAttributeType.LIST -> {
buildLinearTextView(templateAttribute, field) as View?
}
TemplateAttributeType.DATETIME -> {
buildDataTimeView(templateAttribute, field) as View?
}