Browse Source

add support for CustomData in entries.

pull/5/head
Herbert Poul 3 years ago
parent
commit
36007bbe4a
  1. 1
      CHANGELOG.md
  2. 16
      lib/src/kdbx_custom_data.dart
  3. 11
      lib/src/kdbx_entry.dart
  4. 9
      lib/src/kdbx_meta.dart
  5. 1
      lib/src/kdbx_xml.dart

1
CHANGELOG.md

@ -3,6 +3,7 @@
- Mark objects only as clean when saving was successful. - Mark objects only as clean when saving was successful.
- Only mark objects as clean if they have not been modified since we started saving. - Only mark objects as clean if they have not been modified since we started saving.
- Make credentials changeable. - Make credentials changeable.
- Add support for CustomData in entries.
## 2.2.0 ## 2.2.0

16
lib/src/kdbx_custom_data.dart

@ -17,7 +17,7 @@ class KdbxCustomData extends KdbxNode {
})), })),
super.read(node); super.read(node);
static const String TAG_NAME = 'CustomData'; static const String TAG_NAME = KdbxXml.NODE_CUSTOM_DATA;
final Map<String, String> _data; final Map<String, String> _data;
@ -43,4 +43,18 @@ class KdbxCustomData extends KdbxNode {
); );
return el; return el;
} }
void merge(KdbxCustomData other, bool otherIsNewer) {
// merge custom data
for (final otherCustomDataEntry in other.entries) {
if (otherIsNewer || !containsKey(otherCustomDataEntry.key)) {
this[otherCustomDataEntry.key] = otherCustomDataEntry.value;
}
}
}
void overwriteFrom(KdbxCustomData other) {
_data.clear();
_data.addAll(other._data);
}
} }

11
lib/src/kdbx_entry.dart

@ -5,6 +5,7 @@ import 'package:kdbx/src/crypto/protected_value.dart';
import 'package:kdbx/src/internal/extension_utils.dart'; import 'package:kdbx/src/internal/extension_utils.dart';
import 'package:kdbx/src/kdbx_binary.dart'; import 'package:kdbx/src/kdbx_binary.dart';
import 'package:kdbx/src/kdbx_consts.dart'; import 'package:kdbx/src/kdbx_consts.dart';
import 'package:kdbx/src/kdbx_custom_data.dart';
import 'package:kdbx/src/kdbx_exceptions.dart'; import 'package:kdbx/src/kdbx_exceptions.dart';
import 'package:kdbx/src/kdbx_file.dart'; import 'package:kdbx/src/kdbx_file.dart';
import 'package:kdbx/src/kdbx_format.dart'; import 'package:kdbx/src/kdbx_format.dart';
@ -127,6 +128,7 @@ extension KdbxEntryInternal on KdbxEntry {
)); ));
_binaries.clear(); _binaries.clear();
_binaries.addAll(newBinaries); _binaries.addAll(newBinaries);
customData.overwriteFrom(other.customData);
times.overwriteFrom(other.times); times.overwriteFrom(other.times);
if (includeHistory) { if (includeHistory) {
for (final historyEntry in other.history) { for (final historyEntry in other.history) {
@ -157,6 +159,7 @@ class KdbxEntry extends KdbxObject {
KdbxGroup parent, { KdbxGroup parent, {
this.isHistoryEntry = false, this.isHistoryEntry = false,
}) : history = [], }) : history = [],
customData = KdbxCustomData.create(),
super.create(file.ctx, file, 'Entry', parent) { super.create(file.ctx, file, 'Entry', parent) {
icon.set(KdbxIcon.Key); icon.set(KdbxIcon.Key);
} }
@ -164,6 +167,10 @@ class KdbxEntry extends KdbxObject {
KdbxEntry.read(KdbxReadWriteContext ctx, KdbxGroup? parent, XmlElement node, KdbxEntry.read(KdbxReadWriteContext ctx, KdbxGroup? parent, XmlElement node,
{this.isHistoryEntry = false}) {this.isHistoryEntry = false})
: history = [], : history = [],
customData = node
.singleElement(KdbxXml.NODE_CUSTOM_DATA)
?.let((e) => KdbxCustomData.read(e)) ??
KdbxCustomData.create(),
super.read(ctx, parent, node) { super.read(ctx, parent, node) {
_strings.addEntries(node.findElements(KdbxXml.NODE_STRING).map((el) { _strings.addEntries(node.findElements(KdbxXml.NODE_STRING).map((el) {
final key = KdbxKey(el.findElements(KdbxXml.NODE_KEY).single.text); final key = KdbxKey(el.findElements(KdbxXml.NODE_KEY).single.text);
@ -210,6 +217,8 @@ class KdbxEntry extends KdbxObject {
StringNode get overrideURL => StringNode(this, 'OverrideURL'); StringNode get overrideURL => StringNode(this, 'OverrideURL');
StringNode get tags => StringNode(this, 'Tags'); StringNode get tags => StringNode(this, 'Tags');
final KdbxCustomData customData;
@override @override
set file(KdbxFile file) { set file(KdbxFile file) {
super.file = file; super.file = file;
@ -233,7 +242,7 @@ class KdbxEntry extends KdbxObject {
@override @override
XmlElement toXml() { XmlElement toXml() {
final el = super.toXml(); final el = super.toXml()..replaceSingle(customData.toXml());
XmlUtils.removeChildrenByName(el, KdbxXml.NODE_STRING); XmlUtils.removeChildrenByName(el, KdbxXml.NODE_STRING);
XmlUtils.removeChildrenByName(el, KdbxXml.NODE_HISTORY); XmlUtils.removeChildrenByName(el, KdbxXml.NODE_HISTORY);
XmlUtils.removeChildrenByName(el, KdbxXml.NODE_BINARY); XmlUtils.removeChildrenByName(el, KdbxXml.NODE_BINARY);

9
lib/src/kdbx_meta.dart

@ -39,7 +39,7 @@ class KdbxMeta extends KdbxNode implements KdbxNodeContext {
KdbxMeta.read(xml.XmlElement node, this.ctx) KdbxMeta.read(xml.XmlElement node, this.ctx)
: customData = node : customData = node
.singleElement('CustomData') .singleElement(KdbxXml.NODE_CUSTOM_DATA)
?.let((e) => KdbxCustomData.read(e)) ?? ?.let((e) => KdbxCustomData.read(e)) ??
KdbxCustomData.create(), KdbxCustomData.create(),
binaries = node binaries = node
@ -206,13 +206,8 @@ class KdbxMeta extends KdbxNode implements KdbxNodeContext {
recycleBinChanged.set(other.recycleBinChanged.get()); recycleBinChanged.set(other.recycleBinChanged.get());
} }
final otherIsNewer = other.settingsChanged.isAfter(settingsChanged); final otherIsNewer = other.settingsChanged.isAfter(settingsChanged);
// merge custom data // merge custom data
for (final otherCustomDataEntry in other.customData.entries) { customData.merge(other.customData, otherIsNewer);
if (otherIsNewer || !customData.containsKey(otherCustomDataEntry.key)) {
customData[otherCustomDataEntry.key] = otherCustomDataEntry.value;
}
}
// merge custom icons // merge custom icons
for (final otherCustomIcon in other._customIcons.values) { for (final otherCustomIcon in other._customIcons.values) {
_customIcons[otherCustomIcon.uuid] ??= otherCustomIcon; _customIcons[otherCustomIcon.uuid] ??= otherCustomIcon;

1
lib/src/kdbx_xml.dart

@ -30,6 +30,7 @@ class KdbxXml {
static const ATTR_REF = 'Ref'; static const ATTR_REF = 'Ref';
static const NODE_PREVIOUS_PARENT_GROUP = 'PreviousParentGroup'; static const NODE_PREVIOUS_PARENT_GROUP = 'PreviousParentGroup';
static const NODE_CUSTOM_ICONS = 'CustomIcons'; static const NODE_CUSTOM_ICONS = 'CustomIcons';
static const NODE_CUSTOM_DATA = 'CustomData';
/// CustomIcons >> Icon /// CustomIcons >> Icon
static const NODE_ICON = 'Icon'; static const NODE_ICON = 'Icon';

Loading…
Cancel
Save