From a90d4d5fb6d0f342fb01e0d7f819a0edb4d90df1 Mon Sep 17 00:00:00 2001 From: Herbert Poul Date: Sun, 30 Aug 2020 20:27:09 +0200 Subject: [PATCH] adding a couple of meta data fields. should now include almost all from keepass. --- lib/src/kdbx_header.dart | 3 +++ lib/src/kdbx_meta.dart | 40 ++++++++++++++++++++++++++++++++++++++-- lib/src/kdbx_xml.dart | 11 +++++++++-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/src/kdbx_header.dart b/lib/src/kdbx_header.dart index 16098bb..e4fbba8 100644 --- a/lib/src/kdbx_header.dart +++ b/lib/src/kdbx_header.dart @@ -22,6 +22,9 @@ class Consts { static const DefaultKdfIterations = 2; static const DefaultKdfMemory = 1024 * 1024; static const DefaultKdfVersion = 0x13; + + static const DefaultHistoryMaxItems = 20; + static const DefaultHistoryMaxSize = 10 * 1024 * 1024; } enum Compression { diff --git a/lib/src/kdbx_meta.dart b/lib/src/kdbx_meta.dart index a433f32..58c1977 100644 --- a/lib/src/kdbx_meta.dart +++ b/lib/src/kdbx_meta.dart @@ -24,8 +24,14 @@ class KdbxMeta extends KdbxNode implements KdbxNodeContext { _customIcons = {}, super.create('Meta') { this.databaseName.set(databaseName); + databaseDescription.set(null, force: true); + defaultUserName.set(null, force: true); this.generator.set(generator ?? 'kdbx.dart'); settingsChanged.setToNow(); + masterKeyChanged.setToNow(); + recycleBinChanged.setToNow(); + historyMaxItems.set(Consts.DefaultHistoryMaxItems); + historyMaxSize.set(Consts.DefaultHistoryMaxSize); } KdbxMeta.read(xml.XmlElement node, this.ctx) @@ -83,13 +89,30 @@ class KdbxMeta extends KdbxNode implements KdbxNodeContext { StringNode get generator => StringNode(this, 'Generator'); - StringNode get databaseName => StringNode(this, 'DatabaseName'); + StringNode get databaseName => StringNode(this, 'DatabaseName') + ..setOnModifyListener(() => databaseNameChanged.setToNow()); + DateTimeUtcNode get databaseNameChanged => + DateTimeUtcNode(this, 'DatabaseNameChanged'); + + StringNode get databaseDescription => StringNode(this, 'DatabaseDescription') + ..setOnModifyListener(() => databaseDescriptionChanged.setToNow()); + DateTimeUtcNode get databaseDescriptionChanged => + DateTimeUtcNode(this, 'DatabaseDescriptionChanged'); + + StringNode get defaultUserName => StringNode(this, 'DefaultUserName') + ..setOnModifyListener(() => defaultUserNameChanged.setToNow()); + DateTimeUtcNode get defaultUserNameChanged => + DateTimeUtcNode(this, 'DefaultUserNameChanged'); + + DateTimeUtcNode get masterKeyChanged => + DateTimeUtcNode(this, 'MasterKeyChanged'); Base64Node get headerHash => Base64Node(this, 'HeaderHash'); BooleanNode get recycleBinEnabled => BooleanNode(this, 'RecycleBinEnabled'); - UuidNode get recycleBinUUID => UuidNode(this, 'RecycleBinUUID'); + UuidNode get recycleBinUUID => UuidNode(this, 'RecycleBinUUID') + ..setOnModifyListener(() => recycleBinChanged.setToNow()); DateTimeUtcNode get settingsChanged => DateTimeUtcNode(this, 'SettingsChanged'); @@ -97,6 +120,19 @@ class KdbxMeta extends KdbxNode implements KdbxNodeContext { DateTimeUtcNode get recycleBinChanged => DateTimeUtcNode(this, 'RecycleBinChanged'); + UuidNode get entryTemplatesGroup => UuidNode(this, 'EntryTemplatesGroup') + ..setOnModifyListener(() => entryTemplatesGroupChanged.setToNow()); + DateTimeUtcNode get entryTemplatesGroupChanged => + DateTimeUtcNode(this, 'EntryTemplatesGroupChanged'); + + IntNode get historyMaxItems => IntNode(this, 'HistoryMaxItems'); + + /// max size of history in bytes. + IntNode get historyMaxSize => IntNode(this, 'HistoryMaxSize'); + + /// not sure what this node is supposed to do actually. + IntNode get maintenanceHistoryDays => IntNode(this, 'MaintenanceHistoryDays'); + // void addCustomIcon @override diff --git a/lib/src/kdbx_xml.dart b/lib/src/kdbx_xml.dart index 65aca64..fceaca4 100644 --- a/lib/src/kdbx_xml.dart +++ b/lib/src/kdbx_xml.dart @@ -77,6 +77,8 @@ extension on List { abstract class KdbxSubTextNode extends KdbxSubNode { KdbxSubTextNode(KdbxNode node, String name) : super(node, name); + void Function() _onModify; + @protected String encode(T value); @@ -87,6 +89,10 @@ abstract class KdbxSubTextNode extends KdbxSubNode { .findElements(nodeName) .singleWhere((x) => true, orElse: () => null); + void setOnModifyListener(void Function() onModify) { + _onModify = onModify; + } + @override T get() { final textValue = _opt(name)?.text; @@ -97,8 +103,8 @@ abstract class KdbxSubTextNode extends KdbxSubNode { } @override - void set(T value) { - if (get() == value) { + void set(T value, {bool force = false}) { + if (get() == value && force != true) { return; } node.modify(() { @@ -118,6 +124,7 @@ abstract class KdbxSubTextNode extends KdbxSubNode { } el.children.add(XmlText(stringValue)); }); + _onModify?.call(); } @override