use Encode qw(decode);
use File::KDBX::Constants qw(:header :inner_header :variant_map :compression);
use File::KDBX::Error;
-use File::KDBX::Util qw(:io assert_64bit erase_scoped);
-use PerlIO::via::File::KDBX::Crypt;
-use PerlIO::via::File::KDBX::HmacBlock;
+use File::KDBX::Util qw(:class :int :io :load erase_scoped);
+use File::KDBX::IO::Crypt;
+use File::KDBX::IO::HmacBlock;
use boolean;
use namespace::clean;
-use parent 'File::KDBX::Loader';
+extends 'File::KDBX::Loader';
our $VERSION = '999.999'; # VERSION
$buf .= $val;
}
- $type = KDBX_HEADER($type);
+ $type = to_header_constant($type);
if ($type == HEADER_END) {
# done
}
($val) = unpack('L<', $val);
}
elsif ($type == VMAP_TYPE_UINT64) {
- assert_64bit;
- ($val) = unpack('Q<', $val);
+ ($val) = unpack_Ql($val);
}
elsif ($type == VMAP_TYPE_BOOL) {
($val) = unpack('C', $val);
($val) = unpack('l<', $val);
}
elsif ($type == VMAP_TYPE_INT64) {
- assert_64bit;
- ($val) = unpack('q<', $val);
+ ($val) = unpack_ql($val);
}
elsif ($type == VMAP_TYPE_STRING) {
$val = decode('UTF-8', $val);
$kdbx->key($key);
- PerlIO::via::File::KDBX::HmacBlock->push($fh, $hmac_key);
+ $fh = File::KDBX::IO::HmacBlock->new($fh, key => $hmac_key);
my $final_key = digest_data('SHA256', $kdbx->headers->{master_seed}, $transformed_key);
push @cleanup, erase_scoped $final_key;
my $cipher = $kdbx->cipher(key => $final_key);
- PerlIO::via::File::KDBX::Crypt->push($fh, $cipher);
+ $fh = File::KDBX::IO::Crypt->new($fh, cipher => $cipher);
my $compress = $kdbx->headers->{+HEADER_COMPRESSION_FLAGS};
if ($compress == COMPRESSION_GZIP) {
- require PerlIO::via::File::KDBX::Compression;
- PerlIO::via::File::KDBX::Compression->push($fh);
+ load_optional('IO::Uncompress::Gunzip');
+ $fh = IO::Uncompress::Gunzip->new($fh)
+ or throw "Failed to initialize compression library: $IO::Uncompress::Gunzip::GunzipError",
+ error => $IO::Uncompress::Gunzip::GunzipError;
}
elsif ($compress != COMPRESSION_NONE) {
throw "Unsupported compression ($compress)\n", compression_flags => $compress;
$self->_read_inner_headers($fh);
$self->_read_inner_body($fh);
-
- binmode($fh, ':pop') if $compress;
- binmode($fh, ':pop:pop');
}
sub _read_inner_headers {
my $fh = shift;
my $kdbx = $self->kdbx;
- read_all $fh, my $buf, 1 or throw 'Expected inner header type';
- my ($type) = unpack('C', $buf);
-
- read_all $fh, $buf, 4 or throw 'Expected inner header size', type => $type;
- my ($size) = unpack('L<', $buf);
+ read_all $fh, my $buf, 5 or throw 'Expected inner header type and size';
+ my ($type, $size) = unpack('C L<', $buf);
my $val;
if (0 < $size) {
read_all $fh, $val, $size or throw 'Expected inner header value', type => $type, size => $size;
}
- $type = KDBX_INNER_HEADER($type);
-
+ $type = to_inner_header_constant($type) // $type;
if ($type == INNER_HEADER_END) {
# nothing
}
$flags & INNER_HEADER_BINARY_FLAG_PROTECT ? (protect => true) : (),
};
}
+ else {
+ alert "Ignoring unknown inner header type ($type)", type => $type, size => $size, value => $val;
+ return wantarray ? ($type => $val) : $type;
+ }
return wantarray ? ($type => $val) : $type;
}