From 63d73bf382edfb0089b36a45193fc2835cb58b6d Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Sat, 30 Apr 2022 23:24:08 -0600 Subject: [PATCH] Remove min_version and clean up a lot of pod --- Changes | 2 + lib/File/KDBX.pm | 29 ++++++------- lib/File/KDBX/Dumper.pm | 21 ++------- lib/File/KDBX/Dumper/XML.pm | 4 +- lib/File/KDBX/Entry.pm | 58 +------------------------ lib/File/KDBX/Group.pm | 57 +------------------------ lib/File/KDBX/Iterator.pm | 40 +++++++++-------- lib/File/KDBX/Key.pm | 10 ++--- lib/File/KDBX/Key/ChallengeResponse.pm | 6 +-- lib/File/KDBX/Key/File.pm | 2 +- lib/File/KDBX/Loader.pm | 17 +------- lib/File/KDBX/Object.pm | 59 ++++++++++++++++++++++++-- lib/File/KDBX/Util.pm | 2 +- 13 files changed, 115 insertions(+), 192 deletions(-) diff --git a/Changes b/Changes index 4dfa9e9..2dfa611 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for File-KDBX. {{$NEXT}} + * Remove min_version methods from dumper and loader + 0.800 2022-04-30 21:14:30-0600 * Initial release diff --git a/lib/File/KDBX.pm b/lib/File/KDBX.pm index 30f401e..d3e501a 100644 --- a/lib/File/KDBX.pm +++ b/lib/File/KDBX.pm @@ -1928,7 +1928,7 @@ password safe. See L 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 design of this software was influenced by the L +The design of this software was influenced by the L implementation of KeePass as well as the L module. B is an alternative module that works well in most cases but has a small backlog of bugs and security issues and also does not work with newer KDBX version 4 files. If you're coming here from the B world, you might be interested in @@ -1939,15 +1939,13 @@ minor changes up until a 1.0 release. Breaking changes will be noted in the F) * ☑ Unicode character strings * ☑ L Searching * ☑ L and L -* ☑ L +* ☑ L * ☑ L * ☑ L * ☑ Challenge-response key components, like L @@ -1967,7 +1965,7 @@ associated with each entry, group and the database as a whole. You can think of a KDBX database kind of like a file system, where groups are directories, entries are files, and strings and binaries make up a file's contents. -Databases are typically persisted as a encrypted, compressed files. They are usually accessed directly (i.e. +Databases are typically persisted as encrypted, compressed files. They are usually accessed directly (i.e. not over a network). The primary focus of this type of database is data security. It is ideal for storing relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as have the correct I. Even if the database file were to be "leaked" to the public Internet, it @@ -2392,17 +2390,16 @@ If you have a database tree like this: - Group3 - EntryC -IDS order of groups is: Root, Group1, Group2, Group3 -IDS order of entries is: EntryA, EntryB, EntryC -IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC - -DFS order of groups is: Group2, Group1, Group3, Root -DFS order of entries is: EntryB, EntryA, EntryC -DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root - -BFS order of groups is: Root, Group1, Group3, Group2 -BFS order of entries is: EntryA, EntryC, EntryB -BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB +=for :list +* IDS order of groups is: Root, Group1, Group2, Group3 +* IDS order of entries is: EntryA, EntryB, EntryC +* IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC +* DFS order of groups is: Group2, Group1, Group3, Root +* DFS order of entries is: EntryB, EntryA, EntryC +* DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root +* BFS order of groups is: Root, Group1, Group3, Group2 +* BFS order of entries is: EntryA, EntryC, EntryB +* BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB =head1 SYNCHRONIZING diff --git a/lib/File/KDBX/Dumper.pm b/lib/File/KDBX/Dumper.pm index 7e2741c..6f8d8bb 100644 --- a/lib/File/KDBX/Dumper.pm +++ b/lib/File/KDBX/Dumper.pm @@ -93,7 +93,7 @@ sub _rebless { $dumper = $dumper->reset; -Set a L to a blank state, ready to dumper another KDBX file. +Set a L to a blank state, ready to dump another KDBX file. =cut @@ -111,7 +111,7 @@ sub reset { Dump a KDBX file. -The C<$key> is either a L or a primitive that can be converted to a Key object. +The C<$key> is either a L or a primitive that can be cast to a Key object. =cut @@ -202,7 +202,7 @@ sub dump_file { $dumper->dump_handle($fh, $key); $dumper->dump_handle(*IO, $key); -Dump a KDBX file to an input stream / file handle. +Dump a KDBX file to an output stream / file handle. =cut @@ -289,19 +289,6 @@ has 'inner_format', is => 'ro', default => 'XML'; has 'allow_upgrade', is => 'ro', default => 1; has 'randomize_seeds', is => 'ro', default => 1; -=method min_version - - $min_version = File::KDBX::Dumper->min_version; - -Get the minimum KDBX file version supported, which is 3.0 or C<0x00030000> as -it is encoded. - -To generate older KDBX files unsupported by this module, try L. - -=cut - -sub min_version { KDBX_VERSION_OLDEST } - sub _fh { $_[0]->{fh} or throw 'IO handle not set' } sub _dump { @@ -358,7 +345,7 @@ sub _write_magic_numbers { my $kdbx = $self->kdbx; $kdbx->sig1 == KDBX_SIG1 or throw 'Invalid file signature', sig1 => $kdbx->sig1; - $kdbx->version < $self->min_version || KDBX_VERSION_LATEST < $kdbx->version + $kdbx->version < KDBX_VERSION_OLDEST || KDBX_VERSION_LATEST < $kdbx->version and throw 'Unsupported file version', version => $kdbx->version; my @magic = ($kdbx->sig1, $kdbx->sig2, $kdbx->version); diff --git a/lib/File/KDBX/Dumper/XML.pm b/lib/File/KDBX/Dumper/XML.pm index 5b376b9..7dd23d5 100644 --- a/lib/File/KDBX/Dumper/XML.pm +++ b/lib/File/KDBX/Dumper/XML.pm @@ -62,8 +62,8 @@ the authenticity of header data. This is unnecessary and should not be used with format uses HMAC-SHA256 to detect tampering. L automatically calculates the header hash an provides it to this module, and plain -XML files which don't have a KDBX wrapper don't have headers and so should have a header hash. Therefore there -is probably never any reason to set this manually. +XML files which don't have a KDBX wrapper don't have headers and so should not have a header hash. Therefore +there is probably never any reason to set this manually. =cut diff --git a/lib/File/KDBX/Entry.pm b/lib/File/KDBX/Entry.pm index 8bb30c4..e97e30a 100644 --- a/lib/File/KDBX/Entry.pm +++ b/lib/File/KDBX/Entry.pm @@ -27,18 +27,6 @@ my $PLACEHOLDER_MAX_DEPTH = 10; my %PLACEHOLDERS; my %STANDARD_STRINGS = map { $_ => 1 } qw(Title UserName Password URL Notes); -=attr uuid - -128-bit UUID identifying the entry within the database. - -=attr icon_id - -Integer representing a default icon. See L for valid values. - -=attr custom_icon_uuid - -128-bit UUID identifying a custom icon within the database. - =attr foreground_color Text color represented as a string of the form C<#000000>. @@ -51,10 +39,6 @@ Background color represented as a string of the form C<#FFFFFF>. TODO -=attr tags - -Text string with arbitrary tags which can be used to build a taxonomy. - =attr auto_type_enabled Whether or not the entry is eligible to be matched for auto-typing. @@ -78,10 +62,6 @@ An array of window title / keystroke sequence associations. Keystroke sequences can have , most commonly C<{USERNAME}> and C<{PASSWORD}>. -=attr previous_parent_group - -128-bit UUID identifying a group within the database. - =attr quality_check Boolean indicating whether the entry password should be tested for weakness and show up in reports. @@ -122,45 +102,11 @@ characters. There are methods available to provide more convenient access to binaries, including L and L. -=attr custom_data - -A set of key-value pairs used to store arbitrary data, usually used by software to keep track of state rather -than by end users (who typically work with the strings and binaries). - =attr history Array of historical entries. Historical entries are prior versions of the same entry so they all share the same UUID with the current entry. -=attr last_modification_time - -Date and time when the entry was last modified. - -=attr creation_time - -Date and time when the entry was created. - -=attr last_access_time - -Date and time when the entry was last accessed. - -=attr expiry_time - -Date and time when the entry expired or will expire. - -=attr expires - -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 B string has -been accessed. - -=attr location_changed - -Date and time when the entry was last moved to a different parent group. - =attr notes Alias for the B string value. @@ -1191,7 +1137,7 @@ This software supports many (but not all) of the placeholders documented there. * ☑ C<{DT_UTC_MINUTE}> Minute Year component of the current UTC time * ☑ C<{DT_UTC_SECOND}> - Second component of the current UTC time -If the current date and time is <2012-07-25 17:05:34>, the "simple" form would be C<20120725170534>. +If the current date and time is C<2012-07-25 17:05:34>, the "simple" form would be C<20120725170534>. =head3 Special Key Placeholders @@ -1254,7 +1200,7 @@ a placeholder, just set it in the C<%File::KDBX::PLACEHOLDERS> hash. For example If the placeholder is expanded in the context of an entry, C<$entry> is the B object in context. Otherwise it is C. An entry is in context if, for example, the placeholder is in an entry's -strings or auto-complete key sequences. +strings or auto-type key sequences. $File::KDBX::PLACEHOLDERS{'MY_PLACEHOLDER:'} = sub { my ($entry, $arg) = @_; # ^ Notice the colon here diff --git a/lib/File/KDBX/Group.pm b/lib/File/KDBX/Group.pm index 0e8f1ab..1af2c81 100644 --- a/lib/File/KDBX/Group.pm +++ b/lib/File/KDBX/Group.pm @@ -21,10 +21,6 @@ extends 'File::KDBX::Object'; our $VERSION = '999.999'; # VERSION -=attr uuid - -128-bit UUID identifying the group within the database. - =attr name The human-readable name of the group. @@ -33,18 +29,6 @@ The human-readable name of the group. Free form text string associated with the group. -=attr tags - -Text string with arbitrary tags which can be used to build a taxonomy. - -=attr icon_id - -Integer representing a default icon. See L for valid values. - -=attr custom_icon_uuid - -128-bit UUID identifying a custom icon within the database. - =attr is_expanded Whether or not subgroups are visible when listed for user selection. @@ -65,15 +49,6 @@ Whether or not entries within the group can show up in search results, inheritab The UUID of the entry visible at the top of the list. -=attr custom_data - -A set of key-value pairs used to store arbitrary data, usually used by software to keep track of state rather -than by end users (who typically work with the strings and binaries). - -=attr previous_parent_group - -128-bit UUID identifying a group within the database. - =attr entries Array of entries contained within the group. @@ -82,34 +57,6 @@ Array of entries contained within the group. Array of subgroups contained within the group. -=attr last_modification_time - -Date and time when the entry was last modified. - -=attr creation_time - -Date and time when the entry was created. - -=attr last_access_time - -Date and time when the entry was last accessed. - -=attr expiry_time - -Date and time when the entry expired or will expire. - -=attr expires - -Boolean value indicating whether or not an entry is expired. - -=attr usage_count - -TODO - -=attr location_changed - -Date and time when the entry was last moved to a different parent group. - =cut # has uuid => sub { generate_uuid(printable => 1) }; @@ -160,7 +107,7 @@ sub uuid { \@entries = $group->entries; -Get an array of direct entries within a group. +Get an array of direct child entries within a group. =cut @@ -561,7 +508,7 @@ sub is_recycle_bin { $bool = $group->is_entry_templates; -Get whether or not a group is the group containing entry template of its connected database. +Get whether or not a group is the group containing entry template in its connected database. =cut diff --git a/lib/File/KDBX/Iterator.pm b/lib/File/KDBX/Iterator.pm index dc07b40..d531697 100644 --- a/lib/File/KDBX/Iterator.pm +++ b/lib/File/KDBX/Iterator.pm @@ -20,7 +20,7 @@ our $VERSION = '999.999'; # VERSION \&iterator = File::KDBX::Iterator->new(\&iterator); -Blesses an iterator to augment it with buffering plus some useful utility methods. +Bless an iterator to augment it with buffering plus some useful utility methods. =cut @@ -54,7 +54,6 @@ sub new { $item = $iterator->(); $item = $iterator->next(\&query); - $item = $iterator->next([\'simple expression', @fields]); Get the next item or C if there are no more items. If a query is passed, get the next matching item, discarding any unmatching items before the matching item. Example: @@ -94,13 +93,17 @@ sub peek { =method unget + # Replace buffer: $iterator->unget(\@items); - $iterator->unget(...); # OR equivalently $iterator->(\@items); - $iterator->(...); -Replace the buffer or unshift one or more items to the current buffer. + # Unshift onto buffer: + $iterator->unget(@items); + # OR equivalently + $iterator->(@items); + +Replace the buffer (first form) or unshift one or more items to the current buffer (second form). See L. @@ -119,12 +122,13 @@ sub unget { $iterator->each($method_name, ...); -Get or act on the rest of the items. There are three forms: +Get or act on the rest of the items. This method has three forms: =for :list 1. Without arguments, C returns a list of the rest of the items. 2. Pass a coderef to be called once per item, in order. Arguments to the coderef are the item itself (also - C<$_>), its index number and then any extra arguments that were passed to C after the coderef. + available as C<$_>), its index number and then any extra arguments that were passed to C after the + coderef. 3. Pass a string that is the name of a method to be called on each object, in order. Any extra arguments passed to C after the method name are passed through to each method call. This form requires each item be an object that C the given method. @@ -152,10 +156,12 @@ sub each { =method where \&iterator = $iterator->grep(\&query); - \&iterator = $iterator->grep([\'simple expression', @fields]); Get a new iterator draining from an existing iterator but providing only items that pass a test or are matched -by a query. +by a query. In its basic form this method is very much like perl's built-in grep function, except for +iterators. + +There are many examples of the various forms of this method at L. =cut @@ -177,7 +183,8 @@ sub grep { \&iterator = $iterator->map(\&code); -Get a new iterator draining from an existing iterator but providing modified items. +Get a new iterator draining from an existing iterator but providing modified items. In its basic form this +method is very much like perl's built-in map function, except for iterators. =cut @@ -207,8 +214,6 @@ subroutine is called once for each item and should return a string value. Option * C - If true, use B (if available), otherwise use perl built-ins (default: true) * Any B option is also supported. -C and C are aliases. - B This method drains the iterator completely and places the sorted items onto the buffer. See L. @@ -274,8 +279,6 @@ each item and should return a numerical value. Options: =for :list * C - Order ascending if true, descending otherwise (default: true) -C and C are aliases. - B This method drains the iterator completely and places the sorted items onto the buffer. See L. @@ -316,7 +319,7 @@ sub nsort_by { shift->norder_by(@_) } Get a new iterator draining from an existing iterator but providing only a limited number of items. -C as an alias for Lhead($count)">. +C as an alias for L<< Iterator::Simple/"$iterator->head($count)" >>. =cut @@ -396,13 +399,14 @@ supported but this iterator that are not documented here, so consider that addit =head2 Buffer This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items -temporarily to be accessed later. This allows features like L and L which might be useful in the -context of KDBX databases which are normally pretty small so draining an iterator isn't cost-prohibitive. +temporarily to be accessed later. This allows features like L and L which might be useful in +the context of KDBX databases which are normally pretty small so draining an iterator completely isn't +cost-prohibitive in terms of memory usage. The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you call it with arguments, however, the arguments are added to the buffer. When called without arguments, the buffer is drained before the iterator function is. Using L is equivalent to calling the iterator with -arguments, and as L is equivalent to calling the iterator without arguments. +arguments, and L is equivalent to calling the iterator without arguments. =head1 CAVEATS diff --git a/lib/File/KDBX/Key.pm b/lib/File/KDBX/Key.pm index 8a57965..b44faca 100644 --- a/lib/File/KDBX/Key.pm +++ b/lib/File/KDBX/Key.pm @@ -160,8 +160,8 @@ sub _clear_raw_key { $key = $key->hide; -Put the raw key in L. Does nothing if the raw key is already in memory -protection. Returns itself to allow method chaining. +Put the raw key in L. Does nothing if the raw key is already +in memory protection. Returns itself to allow method chaining. =cut @@ -214,7 +214,7 @@ There are several different types of keys, each implemented as a subclass: =for :list * L - Password or passphrase, knowledge of a string of characters -* L - Possession of a file ("key file") with a secret. +* L - Possession of a file ("key file") with a secret * L - Possession of a device that responds correctly when challenged * L - Possession of a YubiKey hardware device (a type of challenge-response) * L - One or more keys combined as one @@ -227,11 +227,11 @@ password key by itself. (Of course it's much better to not have any weak compone B Most KeePass implementations are limited in the types and numbers of keys they support. B keys are pretty much universally supported. B keys are pretty well-supported. Many do not support challenge-response keys. If you are concerned about compatibility, you should stick with one of these -configurations: +well-supported configurations: =for :list * One password * One key file -* One password and one key file +* Composite of one password and one key file =cut diff --git a/lib/File/KDBX/Key/ChallengeResponse.pm b/lib/File/KDBX/Key/ChallengeResponse.pm index 2bbf368..ebf10b7 100644 --- a/lib/File/KDBX/Key/ChallengeResponse.pm +++ b/lib/File/KDBX/Key/ChallengeResponse.pm @@ -27,7 +27,7 @@ sub init { $raw_key = $key->raw_key($challenge); Get the raw key which is the response to a challenge. The response will be saved so that subsequent calls -(with or without the challenge) can provide the response without challenging the responder again. Only once +(with or without the challenge) can provide the response without challenging the responder again. Only one response is saved at a time; if you call this with a different challenge, the new response is saved over any previous response. @@ -78,8 +78,8 @@ __END__ A challenge-response key is kind of like multifactor authentication, except you don't really I to a KDBX database because it's not a service. Specifically it would be the "what you have" component. It -assumes there is some device that can store a key that is only known to the unlocker of a database. -A challenge is made to the device and the response generated based on the key is used as the raw key. +assumes there is some device that can store a key that is only known to the owner of a database. A challenge +is made to the device and the response generated based on the key is used as the raw key. Inherets methods and attributes from L. diff --git a/lib/File/KDBX/Key/File.pm b/lib/File/KDBX/Key/File.pm index fdf131a..335b31e 100644 --- a/lib/File/KDBX/Key/File.pm +++ b/lib/File/KDBX/Key/File.pm @@ -23,7 +23,7 @@ our $VERSION = '999.999'; # VERSION $type = $key->type; -Get the type of key file. Can be one of: +Get the type of key file. Can be one of from L: =for :list * C diff --git a/lib/File/KDBX/Loader.pm b/lib/File/KDBX/Loader.pm index 6d289be..628fe98 100644 --- a/lib/File/KDBX/Loader.pm +++ b/lib/File/KDBX/Loader.pm @@ -105,7 +105,7 @@ sub reset { Load a KDBX file. -The C<$key> is either a L or a primitive that can be converted to a Key object. +The C<$key> is either a L or a primitive that can be cast to a Key object. =cut @@ -230,26 +230,13 @@ formats: =for :list * C - Read the database groups and entries as XML (default) -* C - Read parsing and store the result in L +* C - Read and store the result in L without parsing =cut has format => undef, is => 'ro'; has inner_format => 'XML', is => 'ro'; -=method min_version - - $min_version = File::KDBX::Loader->min_version; - -Get the minimum KDBX file version supported, which is 3.0 or C<0x00030000> as -it is encoded. - -To read older KDBX files unsupported by this module, try L. - -=cut - -sub min_version { KDBX_VERSION_OLDEST } - =method read_magic_numbers $magic = File::KDBX::Loader->read_magic_numbers($fh); diff --git a/lib/File/KDBX/Object.pm b/lib/File/KDBX/Object.pm index 3a56c37..63eadcc 100644 --- a/lib/File/KDBX/Object.pm +++ b/lib/File/KDBX/Object.pm @@ -236,7 +236,9 @@ sub STORABLE_thaw { $kdbx = $object->kdbx; $object->kdbx($kdbx); -Get or set the L instance connected with this object. +Get or set the L instance connected with this object. Throws if the object is disconnected. Other +object methods might only work if the object is connected to a database and so they might also throw if the +object is disconnected. If you're not sure if an object is connected, try L. =cut @@ -368,7 +370,7 @@ sub lineage { $object = $object->remove(%options); Remove an object from its parent. If the object is a group, all contained objects stay with the object and so -are removed as well. Options: +are removed as well, just like cutting off a branch takes the leafs as well. Options: =for :list * C Whether or not to signal the removal to the connected database (default: true) @@ -484,7 +486,9 @@ sub custom_icon { $object->custom_data(%data); $object->custom_data(key => $value, %data); -Get and set custom data. Custom data is metadata associated with an object. +Get and set custom data. Custom data is metadata associated with an object. It is a set of key-value pairs +used to store arbitrary data, usually used by software like plug-ins to keep track of state rather than by end +users. Each data item can have a few attributes associated with it. @@ -834,4 +838,53 @@ Instead, do this: # OR move an existing entry from one database to another: $another_kdbx->add_entry($entry->remove); +=attr uuid + +128-bit UUID identifying the object within the connected database. + +=attr icon_id + +Integer representing a default icon. See L for valid values. + +=attr custom_icon_uuid + +128-bit UUID identifying a custom icon within the connected database. + +=attr tags + +Text string with arbitrary tags which can be used to build a taxonomy. + +=attr previous_parent_group + +128-bit UUID identifying a group within the connected database the previously contained the object. + +=attr last_modification_time + +Date and time when the entry was last modified. + +=attr creation_time + +Date and time when the entry was created. + +=attr last_access_time + +Date and time when the entry was last accessed. + +=attr expiry_time + +Date and time when the entry expired or will expire. + +=attr expires + +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 B string has +been accessed. + +=attr location_changed + +Date and time when the entry was last moved to a different parent group. + =cut diff --git a/lib/File/KDBX/Util.pm b/lib/File/KDBX/Util.pm index d36bcda..5645b4c 100644 --- a/lib/File/KDBX/Util.pm +++ b/lib/File/KDBX/Util.pm @@ -685,7 +685,7 @@ The logic can be specified in a manner similar to L for examples. +See L for examples. =cut -- 2.45.2