X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=lib%2FFile%2FKDBX%2FLoader%2FXML.pm;h=68d1abeb1125dd71063fa6ffb4f31b6bd7e7cbbb;hb=700fa117555b87eda7227f9083c0fc0df052c64f;hp=806b261664b99605aab6d04d22d1910d2dce9737;hpb=05e0bcef1c2165c556b910314312866dc4a667b7;p=chaz%2Fp5-File-KDBX diff --git a/lib/File/KDBX/Loader/XML.pm b/lib/File/KDBX/Loader/XML.pm index 806b261..68d1abe 100644 --- a/lib/File/KDBX/Loader/XML.pm +++ b/lib/File/KDBX/Loader/XML.pm @@ -9,22 +9,19 @@ use Encode qw(decode); use File::KDBX::Constants qw(:version :time); use File::KDBX::Error; use File::KDBX::Safe; -use File::KDBX::Util qw(:text assert_64bit gunzip erase_scoped); +use File::KDBX::Util qw(:class :int :text gunzip erase_scoped); use Scalar::Util qw(looks_like_number); -use Time::Piece; +use Time::Piece 1.33; use XML::LibXML::Reader; use boolean; use namespace::clean; -use parent 'File::KDBX::Loader'; +extends 'File::KDBX::Loader'; our $VERSION = '999.999'; # VERSION -sub _reader { $_[0]->{_reader} } - -sub _binaries { $_[0]->{binaries} //= {} } - -sub _safe { $_[0]->{safe} //= File::KDBX::Safe->new(cipher => $_[0]->kdbx->random_stream) } +has '_reader', is => 'ro'; +has '_safe', is => 'ro', default => sub { File::KDBX::Safe->new(cipher => $_[0]->kdbx->random_stream) }; sub _read { my $self = shift; @@ -39,7 +36,7 @@ sub _read_inner_body { my $reader = $self->{_reader} = XML::LibXML::Reader->new(IO => $fh); - delete $self->{safe}; + delete $self->{_safe}; my $root_done; my $pattern = XML::LibXML::Pattern->new('/KeePassFile/Meta|/KeePassFile/Root'); @@ -63,7 +60,7 @@ sub _read_inner_body { throw 'Failed to parse KeePass XML'; } - $self->kdbx->_safe($self->_safe) if $self->{safe}; + $self->kdbx->_safe($self->_safe) if $self->{_safe}; $self->_resolve_binary_refs; } @@ -168,16 +165,15 @@ sub _read_xml_custom_data { sub _read_xml_custom_icons { my $self = shift; - return $self->_read_xml_element( + return $self->_read_xml_element([], Icon => sub { my $self = shift; - my $icon = $self->_read_xml_element( + $self->_read_xml_element( UUID => 'uuid', Data => 'binary', Name => 'text', # KDBX4.1 LastModificationTime => 'datetime', # KDBX4.1 ); - $icon->{uuid} => $icon; }, ); } @@ -371,10 +367,10 @@ sub _resolve_binary_refs { my $self = shift; my $kdbx = $self->kdbx; - my $entries = $kdbx->all_entries(history => 1); my $pool = $kdbx->binaries; - for my $entry (@$entries) { + my $entries = $kdbx->entries(history => 1); + while (my $entry = $entries->next) { while (my ($key, $binary) = each %{$entry->binaries}) { my $ref = $binary->{ref} // next; next if defined $binary->{value}; @@ -500,7 +496,7 @@ sub _read_xml_content { my $decoded = eval { _decode_primitive($content, $type) }; if (my $err = $@) { ref $err and $err->details(node => $reader->nodePath, line => $reader->lineNumber); - throw $err + throw $err; } return $decoded; @@ -537,14 +533,12 @@ sub _decode_datetime { throw 'Failed to parse binary datetime', text => $_, error => $err; } throw $@ if $@; - assert_64bit; $binary .= \0 x (8 - length($binary)) if length($binary) < 8; - my ($seconds_since_ad1) = unpack('Q<', $binary); + my ($seconds_since_ad1) = unpack_Ql($binary); my $epoch = $seconds_since_ad1 - TIME_SECONDS_AD1_TO_UNIX_EPOCH; - return Time::Piece->new($epoch); + return gmtime($epoch); } - my $dt = eval { Time::Piece->strptime($_, '%Y-%m-%dT%H:%M:%SZ') }; if (my $err = $@) { throw 'Failed to parse datetime', text => $_, error => $err;