]> Dogcows Code - chaz/p5-File-KDBX/blobdiff - lib/File/KDBX.pm
Fix documentation typos
[chaz/p5-File-KDBX] / lib / File / KDBX.pm
index d3e501af1e8c562c781c82750a0e4f6bf5b1938a..75de8998988edb9de3da360d10c8329da7395321 100644 (file)
@@ -1,6 +1,7 @@
 package File::KDBX;
 # ABSTRACT: Encrypted database to store secret text and files
 
+use 5.010;
 use warnings;
 use strict;
 
@@ -15,7 +16,7 @@ use Hash::Util::FieldHash qw(fieldhashes);
 use List::Util qw(any first);
 use Ref::Util qw(is_ref is_arrayref is_plain_hashref);
 use Scalar::Util qw(blessed);
-use Time::Piece;
+use Time::Piece 1.33;
 use boolean;
 use namespace::clean;
 
@@ -264,7 +265,7 @@ has 'meta.database_description'             => '',                          coer
 has 'meta.database_description_changed'     => sub { gmtime },              coerce => \&to_time;
 has 'meta.default_username'                 => '',                          coerce => \&to_string;
 has 'meta.default_username_changed'         => sub { gmtime },              coerce => \&to_time;
-has 'meta.maintenance_history_days'         => 0,                           coerce => \&to_number;
+has 'meta.maintenance_history_days'         => HISTORY_DEFAULT_MAX_AGE,     coerce => \&to_number;
 has 'meta.color'                            => '',                          coerce => \&to_string;
 has 'meta.master_key_changed'               => sub { gmtime },              coerce => \&to_time;
 has 'meta.master_key_change_rec'            => -1,                          coerce => \&to_number;
@@ -341,7 +342,7 @@ might increase this value. For example, setting the KDF to Argon2 will increase
 least C<KDBX_VERSION_4_0> (i.e. C<0x00040000>) because Argon2 was introduced with KDBX4.
 
 This method never returns less than C<KDBX_VERSION_3_1> (i.e. C<0x00030001>). That file version is so
-ubiquitious and well-supported, there are seldom reasons to dump in a lesser format nowadays.
+ubiquitous and well-supported, there are seldom reasons to dump in a lesser format nowadays.
 
 B<WARNING:> If you dump a database with a minimum version higher than the current L</version>, the dumper will
 typically issue a warning and automatically upgrade the database. This seems like the safest behavior in order
@@ -398,8 +399,9 @@ because it autovivifies when adding entries and groups to the database.
 Every database has only a single root group at a time. Some old KDB files might have multiple root groups.
 When reading such files, a single implicit root group is created to contain the actual root groups. When
 writing to such a format, if the root group looks like it was implicitly created then it won't be written and
-the resulting file might have multiple root groups. This allows working with older files without changing
-their written internal structure while still adhering to modern semantics while the database is opened.
+the resulting file might have multiple root groups, as it was before loading. This allows working with older
+files without changing their written internal structure while still adhering to modern semantics while the
+database is opened.
 
 The root group of a KDBX database contains all of the database's entries and other groups. If you replace the
 root group, you are essentially replacing the entire database contents with something else.
@@ -592,7 +594,7 @@ Add a group to a database. This is equivalent to identifying a parent group and
 L<File::KDBX::Group/add_group> on the parent group, forwarding the arguments. Available options:
 
 =for :list
-* C<group> (aka C<parent>) - Group object or group UUID to add the group to (default: root group)
+* C<group> - Group object or group UUID to add the group to (default: root group)
 
 =cut
 
@@ -602,7 +604,7 @@ sub add_group {
     my %args    = @_;
 
     # find the right group to add the group to
-    my $parent = delete $args{group} // delete $args{parent} // $self->root;
+    my $parent = delete $args{group} // $self->root;
     $parent = $self->groups->grep({uuid => $parent})->next if !ref $parent;
     $parent or throw 'Invalid group';
 
@@ -635,7 +637,7 @@ sub groups {
     my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
     my $base = delete $args{base} // $self->root;
 
-    return $base->groups_deeply(%args);
+    return $base->all_groups(%args);
 }
 
 ##############################################################################
@@ -649,7 +651,7 @@ Add a entry to a database. This is equivalent to identifying a parent group and
 L<File::KDBX::Group/add_entry> on the parent group, forwarding the arguments. Available options:
 
 =for :list
-* C<group> (aka C<parent>) - Group object or group UUID to add the entry to (default: root group)
+* C<group> - Group object or group UUID to add the entry to (default: root group)
 
 =cut
 
@@ -659,7 +661,7 @@ sub add_entry {
     my %args    = @_;
 
     # find the right group to add the entry to
-    my $parent = delete $args{group} // delete $args{parent} // $self->root;
+    my $parent = delete $args{group} // $self->root;
     $parent = $self->groups->grep({uuid => $parent})->next if !ref $parent;
     $parent or throw 'Invalid group';
 
@@ -693,7 +695,7 @@ sub entries {
     my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
     my $base = delete $args{base} // $self->root;
 
-    return $base->entries_deeply(%args);
+    return $base->all_entries(%args);
 }
 
 ##############################################################################
@@ -714,7 +716,7 @@ sub objects {
     my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
     my $base = delete $args{base} // $self->root;
 
-    return $base->objects_deeply(%args);
+    return $base->all_objects(%args);
 }
 
 sub __iter__ { $_[0]->objects }
@@ -1154,11 +1156,11 @@ our %PLACEHOLDERS = (
 
     $kdbx->lock;
 
-Encrypt all protected binaries strings in a database. The encrypted strings are stored in
-a L<File::KDBX::Safe> associated with the database and the actual strings will be replaced with C<undef> to
+Encrypt all protected strings and binaries in a database. The encrypted data is stored in
+a L<File::KDBX::Safe> associated with the database and the actual values will be replaced with C<undef> to
 indicate their protected state. Returns itself to allow method chaining.
 
-You can call C<code> on an already-locked database to memory-protect any unprotected strings and binaries
+You can call C<lock> on an already-locked database to memory-protect any unprotected strings and binaries
 added after the last time the database was locked.
 
 =cut
@@ -1191,8 +1193,8 @@ sub lock {
 
     $kdbx->unlock;
 
-Decrypt all protected strings in a database, replacing C<undef> placeholders with unprotected values. Returns
-itself to allow method chaining.
+Decrypt all protected strings and binaries in a database, replacing C<undef> value placeholders with their
+actual, unprotected values. Returns itself to allow method chaining.
 
 =cut
 
@@ -1215,6 +1217,14 @@ C<undef> if the database is already unlocked.
 
 See L</lock> and L</unlock>.
 
+Example:
+
+    {
+        my $guard = $kdbx->unlock_scoped;
+        ...;
+    }
+    # $kdbx is now memory-locked
+
 =cut
 
 sub unlock_scoped {
@@ -1248,13 +1258,13 @@ sub peek {
 
     $bool = $kdbx->is_locked;
 
-Get whether or not a database's strings are memory-protected. If this is true, then some or all of the
-protected strings within the database will be unavailable (literally have C<undef> values) until L</unlock> is
-called.
+Get whether or not a database's contents are in a locked (i.e. memory-protected) state. If this is true, then
+some or all of the protected strings and binaries within the database will be unavailable (literally have
+C<undef> values) until L</unlock> is called.
 
 =cut
 
-sub is_locked { $_[0]->_safe ? 1 : 0 }
+sub is_locked { !!$_[0]->_safe }
 
 ##############################################################################
 
@@ -1368,7 +1378,7 @@ sub prune_history {
 
     my $max_items = $args{max_items} // $self->history_max_items // HISTORY_DEFAULT_MAX_ITEMS;
     my $max_size  = $args{max_size}  // $self->history_max_size  // HISTORY_DEFAULT_MAX_SIZE;
-    my $max_age   = $args{max_age}   // HISTORY_DEFAULT_MAX_AGE;
+    my $max_age   = $args{max_age}   // $self->maintenance_history_days // HISTORY_DEFAULT_MAX_AGE;
 
     my @removed;
     $self->entries->each(sub {
@@ -1418,7 +1428,8 @@ sub randomize_seeds {
     $key = $kdbx->key($primitive);
 
 Get or set a L<File::KDBX::Key>. This is the master key (e.g. a password or a key file that can decrypt
-a database). See L<File::KDBX::Key/new> for an explanation of what the primitive can be.
+a database). You can also pass a primitive castable to a B<Key>. See L<File::KDBX::Key/new> for an explanation
+of what the primitive can be.
 
 You generally don't need to call this directly because you can provide the key directly to the loader or
 dumper when loading or dumping a KDBX file.
@@ -1436,10 +1447,11 @@ sub key {
     $key = $kdbx->composite_key($key);
     $key = $kdbx->composite_key($primitive);
 
-Construct a L<File::KDBX::Key::Composite> from a primitive. See L<File::KDBX::Key/new> for an explanation of
-what the primitive can be. If the primitive does not represent a composite key, it will be wrapped.
+Construct a L<File::KDBX::Key::Composite> from a B<Key> or primitive. See L<File::KDBX::Key/new> for an
+explanation of what the primitive can be. If the primitive does not represent a composite key, it will be
+wrapped.
 
-You generally don't need to call this directly. The parser and writer use it to transform a master key into
+You generally don't need to call this directly. The loader and dumper use it to transform a master key into
 a raw encryption key.
 
 =cut
@@ -1522,7 +1534,7 @@ cipher), not a L<File::KDBX::Key> or primitive.
 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
 C<< $kdbx->headers->{encryption_iv} >>.
 
-You generally don't need to call this directly. The parser and writer use it to decrypt and encrypt KDBX
+You generally don't need to call this directly. The loader and dumper use it to decrypt and encrypt KDBX
 files.
 
 =cut
@@ -1550,7 +1562,7 @@ C<< $kdbx->headers->{inner_random_stream_key} >> (respectively) for KDBX3 files
 C<< $kdbx->inner_headers->{inner_random_stream_key} >> and
 C<< $kdbx->inner_headers->{inner_random_stream_id} >> (respectively) for KDBX4 files.
 
-You generally don't need to call this directly. The parser and writer use it to scramble protected strings.
+You generally don't need to call this directly. The loader and dumper use it to scramble protected strings.
 
 =cut
 
@@ -1705,7 +1717,7 @@ A text string associated with the database. Often unset.
 
 The UUID of a cipher used to encrypt the database when stored as a file.
 
-See L</File::KDBX::Cipher>.
+See L<File::KDBX::Cipher>.
 
 =attr compression_flags
 
@@ -1792,10 +1804,6 @@ When a new entry is created, the I<UserName> string will be populated with this
 
 Timestamp indicating when the default username was last changed.
 
-=attr maintenance_history_days
-
-TODO... not really sure what this is. ðŸ˜€
-
 =attr color
 
 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
@@ -1814,7 +1822,7 @@ Number of days until the agent should prompt to recommend changing the master ke
 Number of days until the agent should prompt to force changing the master key.
 
 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
-C<File::KDBX> does NOT enforce it.
+B<File::KDBX> does NOT enforce it.
 
 =attr custom_icons
 
@@ -1832,7 +1840,7 @@ The UUID of a group used to store thrown-away groups and entries.
 
 =attr recycle_bin_changed
 
-Timestamp indicating when the recycle bin was last changed.
+Timestamp indicating when the recycle bin group was last changed.
 
 =attr entry_templates_group
 
@@ -1852,11 +1860,15 @@ The UUID of the group visible at the top of the list.
 
 =attr history_max_items
 
-The maximum number of historical entries allowed to be saved for each entry.
+The maximum number of historical entries that should be kept for each entry. Default is 10.
 
 =attr history_max_size
 
-The maximum total size (in bytes) that each individual entry's history is allowed to grow.
+The maximum total size (in bytes) that each individual entry's history is allowed to grow. Default is 6 MiB.
+
+=attr maintenance_history_days
+
+The maximum age (in days) historical entries should be kept. Default it 365.
 
 =attr settings_changed
 
@@ -1897,23 +1909,27 @@ __END__
 
     use File::KDBX;
 
+    # Create a new database from scratch
     my $kdbx = File::KDBX->new;
 
+    # Add some objects to the database
     my $group = $kdbx->add_group(
         name => 'Passwords',
     );
-
     my $entry = $group->add_entry(
         title    => 'My Bank',
+        username => 'mreynolds',
         password => 's3cr3t',
     );
 
-    $kdbx->dump_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
+    # Save the database to the filesystem
+    $kdbx->dump_file('passwords.kdbx', 'masterpw changeme');
 
-    $kdbx = File::KDBX->load_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
+    # Load the database from the filesystem into a new database instance
+    my $kdbx2 = File::KDBX->load_file('passwords.kdbx', 'masterpw changeme');
 
-    $kdbx->entries->each(sub {
-        my ($entry) = @_;
+    # Iterate over database entries, print entry titles
+    $kdbx2->entries->each(sub($entry, @) {
         say 'Entry: ', $entry->title;
     });
 
@@ -1921,12 +1937,12 @@ See L</RECIPES> for more examples.
 
 =head1 DESCRIPTION
 
-B<File::KDBX> provides everything you need to work with a KDBX database. A KDBX database is a hierarchical
+B<File::KDBX> provides everything you need to work with KDBX databases. A KDBX database is a hierarchical
 object database which is commonly used to store secret information securely. It was developed for the KeePass
 password safe. See L</"Introduction to KDBX"> for more information about KDBX.
 
-This module lets you query entries, create new entries, delete entries and modify entries. The distribution
-also includes various parsers and generators for serializing and persisting databases.
+This module lets you query entries, create new entries, delete entries, modify entries and more. The
+distribution also includes various parsers and generators for serializing and persisting databases.
 
 The design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
@@ -1995,8 +2011,7 @@ across different websites. See L</SECURITY> for an overview of security consider
     my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
     $kdbx->unlock;  # cause $entry->password below to be defined
 
-    $kdbx->entries->each(sub {
-        my ($entry) = @_;
+    $kdbx->entries->each(sub($entry, @) {
         say 'Found password for: ', $entry->title;
         say '  Username: ', $entry->username;
         say '  Password: ', $entry->password;
@@ -2148,9 +2163,9 @@ unfortunately not portable.
 To find things in a KDBX database, you should use a filtered iterator. If you have an iterator, such as
 returned by L</entries>, L</groups> or even L</objects> you can filter it using L<File::KDBX::Iterator/where>.
 
-    my $filtered_entries = $kdbx->entries->where($query);
+    my $filtered_entries = $kdbx->entries->where(\&query);
 
-A C<$query> is just a subroutine that you can either write yourself or have generated for you from either
+A C<\&query> is just a subroutine that you can either write yourself or have generated for you from either
 a L</"Simple Expression"> or L</"Declarative Syntax">. It's easier to have your query generated, so I'll cover
 that first.
 
@@ -2261,7 +2276,7 @@ operators are:
 * C<==> - Number equal
 * C<!=> - Number not equal
 * C<< < >> - Number less than
-* C<< > >>> - Number greater than
+* C<< > >> - Number greater than
 * C<< <= >> - Number less than or equal
 * C<< >= >> - Number less than or equal
 * C<=~> - String match regular expression
@@ -2369,7 +2384,7 @@ your own query logic, like this:
 
 Iterators are the built-in way to navigate or walk the database tree. You get an iterator from L</entries>,
 L</groups> and L</objects>. You can specify the search algorithm to iterate over objects in different orders
-using the C<algorith> option, which can be one of these L<constants|File::KDBX::Constants/":iteration">:
+using the C<algorithm> option, which can be one of these L<constants|File::KDBX::Constants/":iteration">:
 
 =for :list
 * C<ITERATION_IDS> - Iterative deepening search (default)
@@ -2408,12 +2423,12 @@ B<TODO> - This is a planned feature, not yet implemented.
 =head1 ERRORS
 
 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
-mechanisms. Fatal errors are propagated using L<functions/die> and non-fatal errors (a.k.a. warnings) are
-propagated using L<functions/warn> while adhering to perl's L<warnings> system. If you're already familiar
-with these mechanisms, you can skip this section.
+mechanisms. Fatal errors are propagated using L<perlfunc/"die LIST"> and non-fatal errors (a.k.a. warnings)
+are propagated using L<perlfunc/"warn LIST"> while adhering to perl's L<warnings> system. If you're already
+familiar with these mechanisms, you can skip this section.
 
-You can catch fatal errors using L<functions/eval> (or something like L<Try::Tiny>) and non-fatal errors using
-C<$SIG{__WARN__}> (see L<variables/%SIG>). Examples:
+You can catch fatal errors using L<perlfunc/"eval BLOCK"> (or something like L<Try::Tiny>) and non-fatal
+errors using C<$SIG{__WARN__}> (see L<perlvar/%SIG>). Examples:
 
     use File::KDBX::Error qw(error);
 
@@ -2474,13 +2489,6 @@ This software will alter its behavior depending on the value of certain environm
 * C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
 * C<NO_FORK> - Do not fork if true (default: false)
 
-=head1 CAVEATS
-
-Some features (e.g. parsing) require 64-bit perl. It should be possible and actually pretty easy to make it
-work using L<Math::BigInt>, but I need to build a 32-bit perl in order to test it and frankly I'm still
-figuring out how. I'm sure it's simple so I'll mark this one "TODO", but for now an exception will be thrown
-when trying to use such features with undersized IVs.
-
 =head1 SEE ALSO
 
 =for :list
This page took 0.036658 seconds and 4 git commands to generate.