import 'dart:convert'; import 'dart:typed_data'; import 'package:kdbx/kdbx.dart'; import 'package:kdbx/src/kdbx_consts.dart'; import 'package:meta/meta.dart'; import 'package:xml/xml.dart'; abstract class KdbxSubNode { KdbxSubNode(this.node, this.name); final KdbxNode node; final String name; T get(); void set(T value); } abstract class KdbxSubTextNode extends KdbxSubNode { KdbxSubTextNode(KdbxNode node, String name) : super(node, name); @protected String encode(T value); @protected T decode(String value); XmlElement _opt(String nodeName) => node.node.findElements(nodeName).singleWhere((x) => true, orElse: () => null); @override T get() { final textValue = _opt(name)?.text; if (textValue == null) { return null; } return decode(textValue); } @override void set(T value) { final el = node.node.findElements(name).singleWhere((x) => true, orElse: () { final el = XmlElement(XmlName(name)); node.node.children.add(el); return el; }); el.children.clear(); if (value == null) { return; } final stringValue = encode(value); if (stringValue == null) { return; } el.children.add(XmlText(stringValue)); } } class StringNode extends KdbxSubTextNode { StringNode(KdbxNode node, String name) : super(node, name); @override String decode(String value) => value; @override String encode(String value) => value; } class Base64Node extends KdbxSubTextNode { Base64Node(KdbxNode node, String name) : super(node, name); @override ByteBuffer decode(String value) => base64.decode(value).buffer; @override String encode(ByteBuffer value) => base64.encode(value.asUint8List()); } class UuidNode extends KdbxSubTextNode { UuidNode(KdbxNode node, String name) : super(node, name); @override KdbxUuid decode(String value) => KdbxUuid(value); @override String encode(KdbxUuid value) => value.uuid; } class IconNode extends KdbxSubTextNode { IconNode(KdbxNode node, String name) : super(node, name); @override KdbxIcon decode(String value) => KdbxIcon.values[int.tryParse(value)]; @override String encode(KdbxIcon value) => value.index.toString(); } class BooleanNode extends KdbxSubTextNode { BooleanNode(KdbxNode node, String name) : super(node, name); @override bool decode(String value) { switch (value) { case 'null': return null; case 'true': return true; case 'false': return false; } throw KdbxCorruptedFileException('Invalid boolean value $value for $name'); } @override String encode(bool value) => value ? 'true' : 'false'; }