use File::KDBX::Constants qw(:history :icon);
use File::KDBX::Error;
use File::KDBX::Util qw(:function :uri generate_uuid load_optional);
+use Hash::Util::FieldHash;
use List::Util qw(sum0);
-use Ref::Util qw(is_plain_hashref is_ref);
-use Scalar::Util qw(looks_like_number refaddr);
+use Ref::Util qw(is_plain_hashref);
+use Scalar::Util qw(looks_like_number);
use Storable qw(dclone);
use Time::Piece;
use boolean;
=attr usage_count
-The number of times an entry has been used, which typically means how many times the C<Password> string has
+The number of times an entry has been used, which typically means how many times the B<Password> string has
been accessed.
=attr location_changed
=attr notes
-Alias for the C<Notes> string value.
+Alias for the B<Notes> string value.
=attr password
-Alias for the C<Password> string value.
+Alias for the B<Password> string value.
=attr title
-Alias for the C<Title> string value.
+Alias for the B<Title> string value.
=attr url
-Alias for the C<URL> string value.
+Alias for the B<URL> string value.
=attr username
-Aliases for the C<UserName> string value.
+Aliases for the B<UserName> string value.
=cut
for my $entry (@{$self->history}) {
$entry->{uuid} = $uuid;
}
- # if (defined $old_uuid and my $kdbx = $KDBX{refaddr($self)}) {
+ # if (defined $old_uuid and my $kdbx = $KDBX{$self}) {
# $kdbx->_update_entry_uuid($old_uuid, $uuid, $self);
# }
}
}
return if !defined $File::KDBX::PLACEHOLDERS{$placeholder_key};
- my $local_key = join('/', refaddr($self), $placeholder_key);
+ my $local_key = join('/', Hash::Util::FieldHash::id($self), $placeholder_key);
local $PLACEHOLDERS{$local_key} = my $handler = $PLACEHOLDERS{$local_key} // do {
my $handler = $File::KDBX::PLACEHOLDERS{$placeholder_key} or next;
memoize recurse_limit($handler, $PLACEHOLDER_MAX_DEPTH, sub {
that every entry has:
=for :list
-* C<Title>
-* C<UserName>
-* C<Password>
-* C<URL>
-* C<Notes>
+* B<Title>
+* B<UserName>
+* B<Password>
+* B<URL>
+* B<Notes>
Beyond this, you can store any number of other strings and any number of binaries that you can use for
whatever purpose you want.
Entry string and auto-type key sequences can have placeholders or template tags that can be replaced by other
values. Placeholders can appear like C<{PLACEHOLDER}>. For example, a B<URL> string might have a value of
C<http://example.com?user={USERNAME}>. C<{USERNAME}> is a placeholder for the value of the B<UserName> string
-of the same entry. If the C<UserName> string had a value of "batman", the B<URL> string would expand to
+of the same entry. If the B<UserName> string had a value of "batman", the B<URL> string would expand to
C<http://example.com?user=batman>.
Some placeholders take an argument, where the argument follows the tag after a colon but before the closing
* ☒ C<{CLIPBOARD}>
* ☒ C<{CMD:/CommandLine/Options/}>
* ☑ C<{C:Comment}> - Comments are simply replaced by nothing
-* ☑ C<{ENV:} and C<%ENV%> - Environment variables
+* ☑ C<{ENV:}> and C<%ENV%> - Environment variables
* ☒ C<{GROUP_SEL_NOTES}>
* ☒ C<{GROUP_SEL_PATH}>
* ☒ C<{GROUP_SEL}>
If the name of the placeholder ends in a colon, then it is expected to receive an argument. During expansion,
everything after the colon and before the end of the placeholder is passed to your placeholder handler
-subroutine. So if the placeholder is C<{MY_PLACEHOLDER:whatever}>, C<$arg> will have the value C<whatever>.
+subroutine. So if the placeholder is C<{MY_PLACEHOLDER:whatever}>, C<$arg> will have the value B<whatever>.
An argument is required for placeholders than take one. I.e. The placeholder handler won't be called if there
is no argument. If you want a placeholder to support an optional argument, you'll need to set the placeholder