diff --git a/.idea/dictionaries/herbert.xml b/.idea/dictionaries/herbert.xml
index c96d2ea..c942ae1 100644
--- a/.idea/dictionaries/herbert.xml
+++ b/.idea/dictionaries/herbert.xml
@@ -6,6 +6,7 @@
encrypter
hmac
kdbx
+ keepass
\ No newline at end of file
diff --git a/lib/src/kdbx_header.dart b/lib/src/kdbx_header.dart
index 2cb7365..06454d0 100644
--- a/lib/src/kdbx_header.dart
+++ b/lib/src/kdbx_header.dart
@@ -227,18 +227,26 @@ class KdbxHeader {
_validateInner();
for (final field in InnerHeaderFields.values
.where((f) => f != InnerHeaderFields.EndOfHeader)) {
- _writeInnerField(writer, field);
+ _writeInnerFieldIfExist(writer, field);
+ }
+ // write attachments
+ for (final binary in innerHeader.binaries) {
+ _writeInnerField(writer, binary);
}
- // TODO write attachments
_setInnerHeaderField(InnerHeaderFields.EndOfHeader, Uint8List(0));
- _writeInnerField(writer, InnerHeaderFields.EndOfHeader);
+ _writeInnerFieldIfExist(writer, InnerHeaderFields.EndOfHeader);
}
- void _writeInnerField(WriterHelper writer, InnerHeaderFields field) {
+ void _writeInnerFieldIfExist(WriterHelper writer, InnerHeaderFields field) {
final value = innerHeader.fields[field];
if (value == null) {
return;
}
+ _writeInnerField(writer, value);
+ }
+
+ void _writeInnerField(WriterHelper writer, InnerHeaderField value) {
+ final field = value.field;
_logger.finer(
'Writing header $field (${field.index}) (${value.bytes.lengthInBytes})');
writer.writeUint8(field.index);
@@ -438,6 +446,11 @@ class KdbxCorruptedFileException implements KdbxException {
KdbxCorruptedFileException([this.message]);
final String message;
+
+ @override
+ String toString() {
+ return 'KdbxCorruptedFileException{message: $message}';
+ }
}
class KdbxUnsupportedException implements KdbxException {
diff --git a/test/internal/test_utils.dart b/test/internal/test_utils.dart
index 873d35b..8d788e4 100644
--- a/test/internal/test_utils.dart
+++ b/test/internal/test_utils.dart
@@ -1,6 +1,7 @@
//typedef HashStuff = Pointer Function(Pointer str);
import 'dart:ffi';
import 'dart:io';
+import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'package:kdbx/kdbx.dart';
@@ -55,4 +56,12 @@ class TestUtil {
data, Credentials(ProtectedValue.fromString(password)));
return file;
}
+
+ static Future readKdbxFileBytes(Uint8List data,
+ {String password = 'asdf'}) async {
+ final kdbxFormat = KdbxFormat(Argon2Test());
+ final file = await kdbxFormat.read(
+ data, Credentials(ProtectedValue.fromString(password)));
+ return file;
+ }
}
diff --git a/test/kdbx_binaries_test.dart b/test/kdbx_binaries_test.dart
index 1a92ee4..b05a8ab 100644
--- a/test/kdbx_binaries_test.dart
+++ b/test/kdbx_binaries_test.dart
@@ -8,14 +8,20 @@ import 'package:test/test.dart';
import 'internal/test_utils.dart';
+void expectBinary(KdbxEntry entry, String key, dynamic matcher) {
+ final binaries = entry.binaryEntries;
+ expect(binaries, hasLength(1));
+ final binary = binaries.first;
+ expect(binary.key.key, key);
+ expect(binary.value.value, matcher);
+}
+
void main() {
Logger.root.level = Level.ALL;
PrintAppender().attachToLogger(Logger.root);
group('kdbx3 attachment', () {
- test('read binary', () async {
- final file = await TestUtil.readKdbxFile('test/keepass2binaries.kdbx');
- final entry = file.body.rootGroup.entries.first;
+ void expectKeepass2binariesContents(KdbxEntry entry) {
final binaries = entry.binaryEntries;
expect(binaries, hasLength(3));
for (final binary in binaries) {
@@ -33,19 +39,26 @@ void main() {
fail('invalid key. ${binary.key}');
}
}
+ }
+
+ test('read binary', () async {
+ final file = await TestUtil.readKdbxFile('test/keepass2binaries.kdbx');
+ final entry = file.body.rootGroup.entries.first;
+ expectKeepass2binariesContents(entry);
+ });
+ test('read write read', () async {
+ final fileRead =
+ await TestUtil.readKdbxFile('test/keepass2binaries.kdbx');
+ final saved = await fileRead.save();
+ final file = await TestUtil.readKdbxFileBytes(saved);
+ final entry = file.body.rootGroup.entries.first;
+ expectKeepass2binariesContents(entry);
});
});
group('kdbx4 attachment', () {
test('read binary', () async {
final file =
await TestUtil.readKdbxFile('test/keepass2kdbx4binaries.kdbx');
- void expectBinary(KdbxEntry entry, String key, dynamic matcher) {
- final binaries = entry.binaryEntries;
- expect(binaries, hasLength(1));
- final binary = binaries.first;
- expect(binary.key.key, key);
- expect(binary.value.value, matcher);
- }
expect(file.body.rootGroup.entries, hasLength(2));
expectBinary(file.body.rootGroup.entries.first, 'example2.txt',
@@ -54,6 +67,17 @@ void main() {
hasLength(7092));
});
});
+ test('read, write, read', () async {
+ final fileRead =
+ await TestUtil.readKdbxFile('test/keepass2kdbx4binaries.kdbx');
+ final saved = await fileRead.save();
+ final file = await TestUtil.readKdbxFileBytes(saved);
+ expect(file.body.rootGroup.entries, hasLength(2));
+ expectBinary(file.body.rootGroup.entries.first, 'example2.txt',
+ IsUtf8String('content2 example\n\n'));
+ expectBinary(
+ file.body.rootGroup.entries.last, 'keepasslogo.jpeg', hasLength(7092));
+ });
}
class IsUtf8String extends CustomMatcher {