]> Dogcows Code - chaz/p5-File-KDBX/blobdiff - lib/File/KDBX/Entry.pm
use functions moved to File::KDBX::XS module
[chaz/p5-File-KDBX] / lib / File / KDBX / Entry.pm
index c3ddcb95ead4d4fb03c623e60feef3f6900c4524..5e666bbb5fa1c4e5d88a4901a3a2cb28fbd28e2c 100644 (file)
@@ -10,9 +10,10 @@ use Encode qw(encode);
 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;
@@ -26,6 +27,8 @@ my $PLACEHOLDER_MAX_DEPTH = 10;
 my %PLACEHOLDERS;
 my %STANDARD_STRINGS = map { $_ => 1 } qw(Title UserName Password URL Notes);
 
+sub _parent_container { 'entries' }
+
 =attr uuid
 
 128-bit UUID identifying the entry within the database.
@@ -129,7 +132,7 @@ Boolean value indicating whether or not an entry is expired.
 
 =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
@@ -138,23 +141,23 @@ Date and time when the entry was last moved to a different group.
 
 =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
 
@@ -167,7 +170,7 @@ sub uuid {
         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);
         # }
     }
@@ -252,8 +255,6 @@ sub init {
     return $self;
 }
 
-sub label { shift->title(@_) }
-
 ##############################################################################
 
 =method string
@@ -269,10 +270,11 @@ structure. For example:
 
     $string = {
         value   => 'Password',
-        protect => true,
+        protect => true,    # optional
     };
 
-Every string should have a value and these optional flags which might exist:
+Every string should have a value (but might be C<undef> due to memory protection) and these optional flags
+which might exist:
 
 =for :list
 * C<protect> - Whether or not the string value should be memory-protected.
@@ -281,10 +283,6 @@ Every string should have a value and these optional flags which might exist:
 
 sub string {
     my $self = shift;
-    # use Data::Dumper;
-    # $self->{strings} = shift if @_ == 1 && is_plain_hashref($_[0]);
-    # return $self->{strings} //= {} if !@_;
-
     my %args = @_     == 2 ? (key => shift, value => shift)
              : @_ % 2 == 1 ? (key => shift, @_) : @_;
 
@@ -366,7 +364,7 @@ sub _expand_placeholder {
     }
     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 {
@@ -461,6 +459,11 @@ sub binary_value {
     return $binary->{value};
 }
 
+sub auto_type_enabled {
+    my $entry = shift;
+    # TODO
+}
+
 ##############################################################################
 
 =method hmac_otp
@@ -738,7 +741,10 @@ sub size {
 
 sub history {
     my $self = shift;
-    return [map { __PACKAGE__->wrap($_, $self->kdbx) } @{$self->{history} || []}];
+    my $entries = $self->{history} //= [];
+    # FIXME - Looping through entries on each access is too expensive.
+    @$entries = map { $self->_wrap_entry($_, $self->kdbx) } @$entries;
+    return $entries;
 }
 
 =method history_size
@@ -759,7 +765,7 @@ sub history_size {
     $entry->prune_history(%options);
 
 Remove as many older historical entries as necessary to get under the database limits. The limits are taken
-from the database or can be specified with C<%options>:
+from the associated database (if any) or can be overridden with C<%options>:
 
 =for :list
 * C<max_items> - Maximum number of historical entries to keep (default: 10, no limit: -1)
@@ -795,7 +801,7 @@ sub prune_history {
 sub add_history {
     my $self = shift;
     delete $_->{history} for @_;
-    push @{$self->{history} //= []}, @_;
+    push @{$self->{history} //= []}, map { $self->_wrap_entry($_) } @_;
 }
 
 ##############################################################################
@@ -813,7 +819,7 @@ sub _commit {
     $self->last_modification_time(gmtime);
 }
 
-sub TO_JSON { +{%{$_[0]}} }
+sub label { shift->expanded_title(@_) }
 
 1;
 __END__
@@ -825,11 +831,11 @@ called "files" or "attachments"). Every string and binary has a key or name. The
 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.
@@ -840,14 +846,14 @@ the attributes to see what's available.
 
 =head2 Placeholders
 
-Entry strings and auto-type key sequences can have placeholders or template tags that can be replaced by other
+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. The syntax for this is
-C<{PLACEHOLDER:ARGUMENT}>.
+Some placeholders take an argument, where the argument follows the tag after a colon but before the closing
+brace, like C<{PLACEHOLDER:ARGUMENT}>.
 
 Placeholders are documented in the L<KeePass Help Center|https://keepass.info/help/base/placeholders.html>.
 This software supports many (but not all) of the placeholders documented there.
@@ -872,7 +878,7 @@ This software supports many (but not all) of the placeholders documented there.
 * ☑ C<{URL:RMVSCM}> / C<{URL:WITHOUTSCHEME}>
 * ☑ C<{S:Name}> - Custom string where C<Name> is the name or key of the string
 * ☑ C<{UUID}> - Identifier (32 hexidecimal characters)
-* ☑ C<{HMACOTP}> - Generate an HMAC-based one-time password
+* ☑ C<{HMACOTP}> - Generate an HMAC-based one-time password (its counter B<will> be incremented)
 * ☑ C<{TIMEOTP}> - Generate a time-based one-time password
 * ☑ C<{GROUP_NOTES}> - Notes of the parent group
 * ☑ C<{GROUP_PATH}> - Full path of the parent group
@@ -956,7 +962,7 @@ C<{NUMPAD4}>, C<{NUMPAD5}>, C<{NUMPAD6}>, C<{NUMPAD7}>, C<{NUMPAD8}>, C<{NUMPAD9
 * ☒ 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}>
@@ -990,7 +996,7 @@ strings or auto-complete key sequences.
 
 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
This page took 0.030966 seconds and 4 git commands to generate.