From 0e1dcc712d831d2e529610aa1e35fa6aeffca4e1 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Sun, 1 May 2022 12:56:45 -0600 Subject: [PATCH] Version 0.900 --- Changes | 9 +++ META.json | 79 +++++++++--------- META.yml | 79 +++++++++--------- Makefile.PL | 4 +- README | 107 ++++++++++++++----------- lib/File/KDBX.pm | 97 ++++++++++++++-------- lib/File/KDBX/Cipher.pm | 4 +- lib/File/KDBX/Cipher/CBC.pm | 4 +- lib/File/KDBX/Cipher/Stream.pm | 4 +- lib/File/KDBX/Constants.pm | 4 +- lib/File/KDBX/Dumper.pm | 24 ++---- lib/File/KDBX/Dumper/KDB.pm | 4 +- lib/File/KDBX/Dumper/Raw.pm | 4 +- lib/File/KDBX/Dumper/V3.pm | 4 +- lib/File/KDBX/Dumper/V4.pm | 4 +- lib/File/KDBX/Dumper/XML.pm | 8 +- lib/File/KDBX/Entry.pm | 64 ++------------- lib/File/KDBX/Error.pm | 4 +- lib/File/KDBX/Group.pm | 61 +------------- lib/File/KDBX/IO.pm | 4 +- lib/File/KDBX/IO/Crypt.pm | 4 +- lib/File/KDBX/IO/HashBlock.pm | 4 +- lib/File/KDBX/IO/HmacBlock.pm | 4 +- lib/File/KDBX/Iterator.pm | 43 +++++----- lib/File/KDBX/KDF.pm | 4 +- lib/File/KDBX/KDF/AES.pm | 4 +- lib/File/KDBX/KDF/Argon2.pm | 4 +- lib/File/KDBX/Key.pm | 14 ++-- lib/File/KDBX/Key/ChallengeResponse.pm | 10 +-- lib/File/KDBX/Key/Composite.pm | 4 +- lib/File/KDBX/Key/File.pm | 6 +- lib/File/KDBX/Key/Password.pm | 4 +- lib/File/KDBX/Key/YubiKey.pm | 4 +- lib/File/KDBX/Loader.pm | 20 +---- lib/File/KDBX/Loader/KDB.pm | 4 +- lib/File/KDBX/Loader/Raw.pm | 4 +- lib/File/KDBX/Loader/V3.pm | 4 +- lib/File/KDBX/Loader/V4.pm | 4 +- lib/File/KDBX/Loader/XML.pm | 4 +- lib/File/KDBX/Object.pm | 63 +++++++++++++-- lib/File/KDBX/Safe.pm | 4 +- lib/File/KDBX/Transaction.pm | 4 +- lib/File/KDBX/Util.pm | 6 +- t/00-report-prereqs.dd | 1 - 44 files changed, 384 insertions(+), 415 deletions(-) diff --git a/Changes b/Changes index 9612e3c..6475c06 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,14 @@ Revision history for File-KDBX. +0.900 2022-05-01 12:55:59-0600 + + * Removed the min_version methods from dumper and loader because it was + unused and unnecessary. + * Now use the database maintenance_history_days value as the default + "max_age" value in prune_history method. + * Fixed distribution prereq issues. + * Clean up a lot of pod typos and other inaccuracies. + 0.800 2022-04-30 21:14:30-0600 * Initial release diff --git a/META.json b/META.json index a1eb8ad..995a8d9 100644 --- a/META.json +++ b/META.json @@ -118,7 +118,6 @@ "IO::Handle" : "0", "IPC::Cmd" : "0.52", "Iterator::Simple" : "0", - "Iterator::Simple::Iterator" : "0", "List::Util" : "1.33", "Module::Load" : "0", "Module::Loaded" : "0", @@ -167,155 +166,155 @@ "provides" : { "File::KDBX" : { "file" : "lib/File/KDBX.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Cipher" : { "file" : "lib/File/KDBX/Cipher.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Cipher::CBC" : { "file" : "lib/File/KDBX/Cipher/CBC.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Cipher::Stream" : { "file" : "lib/File/KDBX/Cipher/Stream.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Constants" : { "file" : "lib/File/KDBX/Constants.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper" : { "file" : "lib/File/KDBX/Dumper.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper::KDB" : { "file" : "lib/File/KDBX/Dumper/KDB.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper::Raw" : { "file" : "lib/File/KDBX/Dumper/Raw.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper::V3" : { "file" : "lib/File/KDBX/Dumper/V3.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper::V4" : { "file" : "lib/File/KDBX/Dumper/V4.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Dumper::XML" : { "file" : "lib/File/KDBX/Dumper/XML.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Entry" : { "file" : "lib/File/KDBX/Entry.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Error" : { "file" : "lib/File/KDBX/Error.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Group" : { "file" : "lib/File/KDBX/Group.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::IO" : { "file" : "lib/File/KDBX/IO.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::IO::Crypt" : { "file" : "lib/File/KDBX/IO/Crypt.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::IO::HashBlock" : { "file" : "lib/File/KDBX/IO/HashBlock.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::IO::HmacBlock" : { "file" : "lib/File/KDBX/IO/HmacBlock.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Iterator" : { "file" : "lib/File/KDBX/Iterator.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::KDF" : { "file" : "lib/File/KDBX/KDF.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::KDF::AES" : { "file" : "lib/File/KDBX/KDF/AES.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::KDF::Argon2" : { "file" : "lib/File/KDBX/KDF/Argon2.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key" : { "file" : "lib/File/KDBX/Key.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key::ChallengeResponse" : { "file" : "lib/File/KDBX/Key/ChallengeResponse.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key::Composite" : { "file" : "lib/File/KDBX/Key/Composite.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key::File" : { "file" : "lib/File/KDBX/Key/File.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key::Password" : { "file" : "lib/File/KDBX/Key/Password.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Key::YubiKey" : { "file" : "lib/File/KDBX/Key/YubiKey.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader" : { "file" : "lib/File/KDBX/Loader.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader::KDB" : { "file" : "lib/File/KDBX/Loader/KDB.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader::Raw" : { "file" : "lib/File/KDBX/Loader/Raw.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader::V3" : { "file" : "lib/File/KDBX/Loader/V3.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader::V4" : { "file" : "lib/File/KDBX/Loader/V4.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Loader::XML" : { "file" : "lib/File/KDBX/Loader/XML.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Object" : { "file" : "lib/File/KDBX/Object.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Safe" : { "file" : "lib/File/KDBX/Safe.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Transaction" : { "file" : "lib/File/KDBX/Transaction.pm", - "version" : "0.800" + "version" : "0.900" }, "File::KDBX::Util" : { "file" : "lib/File/KDBX/Util.pm", - "version" : "0.800" + "version" : "0.900" } }, "release_status" : "stable", @@ -330,7 +329,7 @@ "web" : "https://github.com/chazmcgarvey/File-KDBX" } }, - "version" : "0.800", + "version" : "0.900", "x_authority" : "cpan:CCM", "x_generated_by_perl" : "v5.34.1", "x_serialization_backend" : "Cpanel::JSON::XS version 4.27", diff --git a/META.yml b/META.yml index 20edc2c..5f0f5ca 100644 --- a/META.yml +++ b/META.yml @@ -50,118 +50,118 @@ optional_features: provides: File::KDBX: file: lib/File/KDBX.pm - version: '0.800' + version: '0.900' File::KDBX::Cipher: file: lib/File/KDBX/Cipher.pm - version: '0.800' + version: '0.900' File::KDBX::Cipher::CBC: file: lib/File/KDBX/Cipher/CBC.pm - version: '0.800' + version: '0.900' File::KDBX::Cipher::Stream: file: lib/File/KDBX/Cipher/Stream.pm - version: '0.800' + version: '0.900' File::KDBX::Constants: file: lib/File/KDBX/Constants.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper: file: lib/File/KDBX/Dumper.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper::KDB: file: lib/File/KDBX/Dumper/KDB.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper::Raw: file: lib/File/KDBX/Dumper/Raw.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper::V3: file: lib/File/KDBX/Dumper/V3.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper::V4: file: lib/File/KDBX/Dumper/V4.pm - version: '0.800' + version: '0.900' File::KDBX::Dumper::XML: file: lib/File/KDBX/Dumper/XML.pm - version: '0.800' + version: '0.900' File::KDBX::Entry: file: lib/File/KDBX/Entry.pm - version: '0.800' + version: '0.900' File::KDBX::Error: file: lib/File/KDBX/Error.pm - version: '0.800' + version: '0.900' File::KDBX::Group: file: lib/File/KDBX/Group.pm - version: '0.800' + version: '0.900' File::KDBX::IO: file: lib/File/KDBX/IO.pm - version: '0.800' + version: '0.900' File::KDBX::IO::Crypt: file: lib/File/KDBX/IO/Crypt.pm - version: '0.800' + version: '0.900' File::KDBX::IO::HashBlock: file: lib/File/KDBX/IO/HashBlock.pm - version: '0.800' + version: '0.900' File::KDBX::IO::HmacBlock: file: lib/File/KDBX/IO/HmacBlock.pm - version: '0.800' + version: '0.900' File::KDBX::Iterator: file: lib/File/KDBX/Iterator.pm - version: '0.800' + version: '0.900' File::KDBX::KDF: file: lib/File/KDBX/KDF.pm - version: '0.800' + version: '0.900' File::KDBX::KDF::AES: file: lib/File/KDBX/KDF/AES.pm - version: '0.800' + version: '0.900' File::KDBX::KDF::Argon2: file: lib/File/KDBX/KDF/Argon2.pm - version: '0.800' + version: '0.900' File::KDBX::Key: file: lib/File/KDBX/Key.pm - version: '0.800' + version: '0.900' File::KDBX::Key::ChallengeResponse: file: lib/File/KDBX/Key/ChallengeResponse.pm - version: '0.800' + version: '0.900' File::KDBX::Key::Composite: file: lib/File/KDBX/Key/Composite.pm - version: '0.800' + version: '0.900' File::KDBX::Key::File: file: lib/File/KDBX/Key/File.pm - version: '0.800' + version: '0.900' File::KDBX::Key::Password: file: lib/File/KDBX/Key/Password.pm - version: '0.800' + version: '0.900' File::KDBX::Key::YubiKey: file: lib/File/KDBX/Key/YubiKey.pm - version: '0.800' + version: '0.900' File::KDBX::Loader: file: lib/File/KDBX/Loader.pm - version: '0.800' + version: '0.900' File::KDBX::Loader::KDB: file: lib/File/KDBX/Loader/KDB.pm - version: '0.800' + version: '0.900' File::KDBX::Loader::Raw: file: lib/File/KDBX/Loader/Raw.pm - version: '0.800' + version: '0.900' File::KDBX::Loader::V3: file: lib/File/KDBX/Loader/V3.pm - version: '0.800' + version: '0.900' File::KDBX::Loader::V4: file: lib/File/KDBX/Loader/V4.pm - version: '0.800' + version: '0.900' File::KDBX::Loader::XML: file: lib/File/KDBX/Loader/XML.pm - version: '0.800' + version: '0.900' File::KDBX::Object: file: lib/File/KDBX/Object.pm - version: '0.800' + version: '0.900' File::KDBX::Safe: file: lib/File/KDBX/Safe.pm - version: '0.800' + version: '0.900' File::KDBX::Transaction: file: lib/File/KDBX/Transaction.pm - version: '0.800' + version: '0.900' File::KDBX::Util: file: lib/File/KDBX/Util.pm - version: '0.800' + version: '0.900' recommends: Compress::Raw::Zlib: '0' File::KDBX::XS: '0' @@ -187,7 +187,6 @@ requires: IO::Handle: '0' IPC::Cmd: '0.52' Iterator::Simple: '0' - Iterator::Simple::Iterator: '0' List::Util: '1.33' Module::Load: '0' Module::Loaded: '0' @@ -210,7 +209,7 @@ resources: bugtracker: https://github.com/chazmcgarvey/File-KDBX/issues homepage: https://github.com/chazmcgarvey/File-KDBX repository: https://github.com/chazmcgarvey/File-KDBX.git -version: '0.800' +version: '0.900' x_authority: cpan:CCM x_generated_by_perl: v5.34.1 x_serialization_backend: 'YAML::Tiny version 1.73' diff --git a/Makefile.PL b/Makefile.PL index 83053fc..40792ca 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -34,7 +34,6 @@ my %WriteMakefileArgs = ( "IO::Handle" => 0, "IPC::Cmd" => "0.52", "Iterator::Simple" => 0, - "Iterator::Simple::Iterator" => 0, "List::Util" => "1.33", "Module::Load" => 0, "Module::Loaded" => 0, @@ -68,7 +67,7 @@ my %WriteMakefileArgs = ( "lib" => 0, "utf8" => 0 }, - "VERSION" => "0.800", + "VERSION" => "0.900", "test" => { "TESTS" => "t/*.t" } @@ -98,7 +97,6 @@ my %FallbackPrereqs = ( "IPC::Cmd" => "0.52", "IPC::Open3" => 0, "Iterator::Simple" => 0, - "Iterator::Simple::Iterator" => 0, "List::Util" => "1.33", "Module::Load" => 0, "Module::Loaded" => 0, diff --git a/README b/README index 800d034..42cd205 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ NAME VERSION - version 0.800 + version 0.900 SYNOPSIS @@ -34,17 +34,17 @@ SYNOPSIS DESCRIPTION - File::KDBX provides everything you need to work with a KDBX database. A + 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 "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. - This design of this software was influenced by the KeePassXC + The design of this software was influenced by the KeePassXC implementation of KeePass as well as the File::KeePass module. File::KeePass is an alternative module that works well in most cases but has a small backlog of bugs @@ -59,8 +59,6 @@ DESCRIPTION Features - This implementation of KDBX supports a lot of features: - * ☑ Read and write KDBX version 3 - version 4.1 * ☑ Read and write KDB files (requires File::KeePass) @@ -103,11 +101,11 @@ DESCRIPTION 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. 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 + 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 master key. Even if the database file were to be "leaked" to the public Internet, it should be virtually impossible to crack with a strong key. The KDBX format is most often used by password managers to store @@ -248,10 +246,6 @@ ATTRIBUTES Timestamp indicating when the default username was last changed. - maintenance_history_days - - TODO... not really sure what this is. 😀 - color A color associated with the database (in the form #ffffff where "f" is @@ -293,7 +287,7 @@ ATTRIBUTES recycle_bin_changed - Timestamp indicating when the recycle bin was last changed. + Timestamp indicating when the recycle bin group was last changed. entry_templates_group @@ -314,13 +308,18 @@ ATTRIBUTES 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. history_max_size The maximum total size (in bytes) that each individual entry's history - is allowed to grow. + is allowed to grow. Default is 6 MiB. + + maintenance_history_days + + The maximum age (in days) historical entries should be kept. Default it + 365. settings_changed @@ -491,9 +490,10 @@ METHODS 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. + 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 @@ -550,8 +550,8 @@ METHODS group and calling "add_group" in File::KDBX::Group on the parent group, forwarding the arguments. Available options: - * group (aka parent) - Group object or group UUID to add the group to - (default: root group) + * group - Group object or group UUID to add the group to (default: + root group) groups @@ -576,8 +576,8 @@ METHODS group and calling "add_entry" in File::KDBX::Group on the parent group, forwarding the arguments. Available options: - * group (aka parent) - Group object or group UUID to add the entry to - (default: root group) + * group - Group object or group UUID to add the entry to (default: + root group) entries @@ -895,8 +895,9 @@ METHODS $key = $kdbx->key($primitive); Get or set a File::KDBX::Key. This is the master key (e.g. a password - or a key file that can decrypt a database). See "new" in - File::KDBX::Key for an explanation of what the primitive can be. + or a key file that can decrypt a database). You can also pass a + primitive that can be cast to a Key. See "new" in File::KDBX::Key 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 @@ -907,11 +908,12 @@ METHODS $key = $kdbx->composite_key($key); $key = $kdbx->composite_key($primitive); - Construct a File::KDBX::Key::Composite from a primitive. See "new" in - File::KDBX::Key for an explanation of what the primitive can be. If the - primitive does not represent a composite key, it will be wrapped. + Construct a File::KDBX::Key::Composite from a Key or primitive. See + "new" in File::KDBX::Key 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 + 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. kdf @@ -941,7 +943,7 @@ METHODS If not passed, the UUID comes from $kdbx->headers->{cipher_id} and the encryption IV comes from $kdbx->headers->{encryption_iv}. - You generally don't need to call this directly. The parser and writer + You generally don't need to call this directly. The loader and dumper use it to decrypt and encrypt KDBX files. random_stream @@ -959,7 +961,7 @@ METHODS $kdbx->inner_headers->{inner_random_stream_id} (respectively) for KDBX4 files. - You generally don't need to call this directly. The parser and writer + You generally don't need to call this directly. The loader and dumper use it to scramble protected strings. RECIPES @@ -1171,9 +1173,9 @@ QUERY If you have an iterator, such as returned by "entries", "groups" or even "objects" you can filter it using "where" in File::KDBX::Iterator. - my $filtered_entries = $kdbx->entries->where($query); + my $filtered_entries = $kdbx->entries->where(\&query); - A $query is just a subroutine that you can either write yourself or + A \&query is just a subroutine that you can either write yourself or have generated for you from either a "Simple Expression" or "Declarative Syntax". It's easier to have your query generated, so I'll cover that first. @@ -1311,7 +1313,7 @@ QUERY * < - Number less than - * >> - Number greater than + * > - Number greater than * <= - Number less than or equal @@ -1469,17 +1471,26 @@ QUERY - 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 + * 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 - 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 entries is: EntryA, EntryC, EntryB - 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 + * BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, + Group2, EntryB SYNCHRONIZING diff --git a/lib/File/KDBX.pm b/lib/File/KDBX.pm index d7b0d31..d2dc04f 100644 --- a/lib/File/KDBX.pm +++ b/lib/File/KDBX.pm @@ -19,7 +19,7 @@ use Time::Piece; use boolean; use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our $WARNINGS = 1; fieldhashes \my (%SAFE, %KEYS); @@ -170,7 +170,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; @@ -399,7 +399,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'; @@ -431,7 +431,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'; @@ -875,7 +875,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 { @@ -1120,7 +1120,7 @@ File::KDBX - Encrypted database to store secret text and files =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS @@ -1150,14 +1150,14 @@ See L for more examples. =head1 DESCRIPTION -B provides everything you need to work with a KDBX database. A KDBX database is a hierarchical +B 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 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. -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 @@ -1168,8 +1168,6 @@ minor changes up until a 1.0 release. Breaking changes will be noted in the F +☑ L =item * @@ -1240,7 +1238,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 @@ -1368,10 +1366,6 @@ When a new entry is created, the I string will be populated with this Timestamp indicating when the default username was last changed. -=head2 maintenance_history_days - -TODO... not really sure what this is. 😀 - =head2 color A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents @@ -1408,7 +1402,7 @@ The UUID of a group used to store thrown-away groups and entries. =head2 recycle_bin_changed -Timestamp indicating when the recycle bin was last changed. +Timestamp indicating when the recycle bin group was last changed. =head2 entry_templates_group @@ -1428,11 +1422,15 @@ The UUID of the group visible at the top of the list. =head2 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. =head2 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. + +=head2 maintenance_history_days + +The maximum age (in days) historical entries should be kept. Default it 365. =head2 settings_changed @@ -1590,8 +1588,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. @@ -1648,7 +1647,7 @@ L on the parent group, forwarding the arguments. Av =item * -C (aka C) - Group object or group UUID to add the group to (default: root group) +C - Group object or group UUID to add the group to (default: root group) =back @@ -1687,7 +1686,7 @@ L on the parent group, forwarding the arguments. Av =item * -C (aka C) - Group object or group UUID to add the entry to (default: root group) +C - Group object or group UUID to add the entry to (default: root group) =back @@ -2054,7 +2053,8 @@ You normally do not need to call this method explicitly because the dumper does $key = $kdbx->key($primitive); Get or set a L. This is the master key (e.g. a password or a key file that can decrypt -a database). See L for an explanation of what the primitive can be. +a database). You can also pass a primitive that can be cast to a B. See L 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. @@ -2064,10 +2064,11 @@ dumper when loading or dumping a KDBX file. $key = $kdbx->composite_key($key); $key = $kdbx->composite_key($primitive); -Construct a L from a primitive. See L 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 from a B or primitive. See L 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. =head2 kdf @@ -2100,7 +2101,7 @@ cipher), not a L 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. =head2 random_stream @@ -2115,7 +2116,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. =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON @@ -2331,9 +2332,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, L or even L you can filter it using L. - 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 or L. It's easier to have your query generated, so I'll cover that first. @@ -2474,7 +2475,7 @@ C<< < >> - Number less than =item * -C<< > >>> - Number greater than +C<< > >> - Number greater than =item * @@ -2663,18 +2664,46 @@ If you have a database tree like this: - Group3 - EntryC +=over 4 + +=item * + IDS order of groups is: Root, Group1, Group2, Group3 + +=item * + IDS order of entries is: EntryA, EntryB, EntryC + +=item * + IDS order of objects is: Root, Group1, EntryA, Group2, EntryB, Group3, EntryC +=item * + DFS order of groups is: Group2, Group1, Group3, Root + +=item * + DFS order of entries is: EntryB, EntryA, EntryC + +=item * + DFS order of objects is: Group2, EntryB, Group1, EntryA, Group3, EntryC, Root +=item * + BFS order of groups is: Root, Group1, Group3, Group2 + +=item * + BFS order of entries is: EntryA, EntryC, EntryB + +=item * + BFS order of objects is: Root, Group1, EntryA, Group3, EntryC, Group2, EntryB +=back + =head1 SYNCHRONIZING B - This is a planned feature, not yet implemented. diff --git a/lib/File/KDBX/Cipher.pm b/lib/File/KDBX/Cipher.pm index 0253376..fd335a3 100644 --- a/lib/File/KDBX/Cipher.pm +++ b/lib/File/KDBX/Cipher.pm @@ -12,7 +12,7 @@ use Module::Load; use Scalar::Util qw(looks_like_number); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION my %CIPHERS; @@ -158,7 +158,7 @@ File::KDBX::Cipher - A block cipher mode or cipher stream =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Cipher/CBC.pm b/lib/File/KDBX/Cipher/CBC.pm index e1d7cf3..0dbdc6c 100644 --- a/lib/File/KDBX/Cipher/CBC.pm +++ b/lib/File/KDBX/Cipher/CBC.pm @@ -11,7 +11,7 @@ use namespace::clean; extends 'File::KDBX::Cipher'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has key_size => 32; sub iv_size { 16 } @@ -63,7 +63,7 @@ File::KDBX::Cipher::CBC - A CBC block cipher mode encrypter/decrypter =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Cipher/Stream.pm b/lib/File/KDBX/Cipher/Stream.pm index d25a869..2cd4033 100644 --- a/lib/File/KDBX/Cipher/Stream.pm +++ b/lib/File/KDBX/Cipher/Stream.pm @@ -14,7 +14,7 @@ use namespace::clean; extends 'File::KDBX::Cipher'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has 'counter', is => 'ro', default => 0; @@ -123,7 +123,7 @@ File::KDBX::Cipher::Stream - A cipher stream encrypter/decrypter =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Constants.pm b/lib/File/KDBX/Constants.pm index c109ace..a3d5baa 100644 --- a/lib/File/KDBX/Constants.pm +++ b/lib/File/KDBX/Constants.pm @@ -13,7 +13,7 @@ use Exporter qw(import); use Scalar::Util qw(dualvar); use namespace::clean -except => 'import'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION BEGIN { my %CONSTANTS = ( @@ -346,7 +346,7 @@ File::KDBX::Constants - All the KDBX-related constants you could ever want =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Dumper.pm b/lib/File/KDBX/Dumper.pm index db13dd4..3b3d311 100644 --- a/lib/File/KDBX/Dumper.pm +++ b/lib/File/KDBX/Dumper.pm @@ -15,7 +15,7 @@ use Ref::Util qw(is_ref is_scalarref); use Scalar::Util qw(looks_like_number openhandle); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub new { @@ -177,9 +177,6 @@ has 'inner_format', is => 'ro', default => 'XML'; has 'allow_upgrade', is => 'ro', default => 1; has 'randomize_seeds', is => 'ro', default => 1; - -sub min_version { KDBX_VERSION_OLDEST } - sub _fh { $_[0]->{fh} or throw 'IO handle not set' } sub _dump { @@ -236,7 +233,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); @@ -276,7 +273,7 @@ File::KDBX::Dumper - Write KDBX files =head1 VERSION -version 0.800 +version 0.900 =head1 ATTRIBUTES @@ -378,7 +375,7 @@ This is called by L. $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. =head2 dump @@ -388,7 +385,7 @@ Set a L to a blank state, ready to dumper another KDBX file. 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. =head2 dump_string @@ -408,16 +405,7 @@ Dump a KDBX file to a filesystem. $dumper->dump_handle($fh, $key); $dumper->dump_handle(*IO, $key); -Dump a KDBX file to an input stream / file handle. - -=head2 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. +Dump a KDBX file to an output stream / file handle. =head1 BUGS diff --git a/lib/File/KDBX/Dumper/KDB.pm b/lib/File/KDBX/Dumper/KDB.pm index 0350a39..39ab4f6 100644 --- a/lib/File/KDBX/Dumper/KDB.pm +++ b/lib/File/KDBX/Dumper/KDB.pm @@ -14,7 +14,7 @@ use namespace::clean; extends 'File::KDBX::Dumper'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _write_magic_numbers { '' } sub _write_headers { '' } @@ -138,7 +138,7 @@ File::KDBX::Dumper::KDB - Write KDB files =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/Dumper/Raw.pm b/lib/File/KDBX/Dumper/Raw.pm index 3507c45..1153fcc 100644 --- a/lib/File/KDBX/Dumper/Raw.pm +++ b/lib/File/KDBX/Dumper/Raw.pm @@ -9,7 +9,7 @@ use namespace::clean; extends 'File::KDBX::Dumper'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _dump { my $self = shift; @@ -48,7 +48,7 @@ File::KDBX::Dumper::Raw - A no-op dumper that dumps content as-is =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Dumper/V3.pm b/lib/File/KDBX/Dumper/V3.pm index 2fe585c..394dce3 100644 --- a/lib/File/KDBX/Dumper/V3.pm +++ b/lib/File/KDBX/Dumper/V3.pm @@ -16,7 +16,7 @@ use namespace::clean; extends 'File::KDBX::Dumper'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _write_headers { my $self = shift; @@ -189,7 +189,7 @@ File::KDBX::Dumper::V3 - Dump KDBX3 files =head1 VERSION -version 0.800 +version 0.900 =head1 BUGS diff --git a/lib/File/KDBX/Dumper/V4.pm b/lib/File/KDBX/Dumper/V4.pm index ac5487f..061bd08 100644 --- a/lib/File/KDBX/Dumper/V4.pm +++ b/lib/File/KDBX/Dumper/V4.pm @@ -19,7 +19,7 @@ use namespace::clean; extends 'File::KDBX::Dumper'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has _binaries_written => {}, is => 'ro'; @@ -377,7 +377,7 @@ File::KDBX::Dumper::V4 - Dump KDBX4 files =head1 VERSION -version 0.800 +version 0.900 =head1 BUGS diff --git a/lib/File/KDBX/Dumper/XML.pm b/lib/File/KDBX/Dumper/XML.pm index e47c629..f5b62f0 100644 --- a/lib/File/KDBX/Dumper/XML.pm +++ b/lib/File/KDBX/Dumper/XML.pm @@ -19,7 +19,7 @@ use namespace::clean; extends 'File::KDBX::Dumper'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has allow_protection => 1; @@ -564,7 +564,7 @@ File::KDBX::Dumper::XML - Dump unencrypted XML KeePass files =head1 VERSION -version 0.800 +version 0.900 =head1 ATTRIBUTES @@ -620,8 +620,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. =head1 BUGS diff --git a/lib/File/KDBX/Entry.pm b/lib/File/KDBX/Entry.pm index d8acc70..be4a6a3 100644 --- a/lib/File/KDBX/Entry.pm +++ b/lib/File/KDBX/Entry.pm @@ -21,7 +21,7 @@ use namespace::clean; extends 'File::KDBX::Object'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION my $PLACEHOLDER_MAX_DEPTH = 10; my %PLACEHOLDERS; @@ -538,7 +538,7 @@ sub prune_history { my $max_items = $args{max_items} // eval { $self->kdbx->history_max_items } // HISTORY_DEFAULT_MAX_ITEMS; my $max_size = $args{max_size} // eval { $self->kdbx->history_max_size } // HISTORY_DEFAULT_MAX_SIZE; - my $max_age = $args{max_age} // HISTORY_DEFAULT_MAX_AGE; + my $max_age = $args{max_age} // eval { $self->kdbx->maintenance_history_days } // HISTORY_DEFAULT_MAX_AGE; # history is ordered oldest to newest my $history = $self->history; @@ -681,7 +681,7 @@ File::KDBX::Entry - A KDBX database entry =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION @@ -960,7 +960,7 @@ This software supports many (but not all) of the placeholders documented there. =back -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 @@ -1106,7 +1106,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 @@ -1235,18 +1235,6 @@ Here's a basic example: =head1 ATTRIBUTES -=head2 uuid - -128-bit UUID identifying the entry within the database. - -=head2 icon_id - -Integer representing a default icon. See L for valid values. - -=head2 custom_icon_uuid - -128-bit UUID identifying a custom icon within the database. - =head2 foreground_color Text color represented as a string of the form C<#000000>. @@ -1259,10 +1247,6 @@ Background color represented as a string of the form C<#FFFFFF>. TODO -=head2 tags - -Text string with arbitrary tags which can be used to build a taxonomy. - =head2 auto_type_enabled Whether or not the entry is eligible to be matched for auto-typing. @@ -1286,10 +1270,6 @@ An array of window title / keystroke sequence associations. Keystroke sequences can have , most commonly C<{USERNAME}> and C<{PASSWORD}>. -=head2 previous_parent_group - -128-bit UUID identifying a group within the database. - =head2 quality_check Boolean indicating whether the entry password should be tested for weakness and show up in reports. @@ -1330,45 +1310,11 @@ characters. There are methods available to provide more convenient access to binaries, including L and L. -=head2 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). - =head2 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. -=head2 last_modification_time - -Date and time when the entry was last modified. - -=head2 creation_time - -Date and time when the entry was created. - -=head2 last_access_time - -Date and time when the entry was last accessed. - -=head2 expiry_time - -Date and time when the entry expired or will expire. - -=head2 expires - -Boolean value indicating whether or not an entry is expired. - -=head2 usage_count - -The number of times an entry has been used, which typically means how many times the B string has -been accessed. - -=head2 location_changed - -Date and time when the entry was last moved to a different parent group. - =head2 notes Alias for the B string value. diff --git a/lib/File/KDBX/Error.pm b/lib/File/KDBX/Error.pm index fc182af..f902f79 100644 --- a/lib/File/KDBX/Error.pm +++ b/lib/File/KDBX/Error.pm @@ -8,7 +8,7 @@ use Exporter qw(import); use Scalar::Util qw(blessed looks_like_number); use namespace::clean -except => 'import'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our @EXPORT = qw(alert error throw); @@ -166,7 +166,7 @@ File::KDBX::Error - Represents something bad that happened =head1 VERSION -version 0.800 +version 0.900 =head1 ATTRIBUTES diff --git a/lib/File/KDBX/Group.pm b/lib/File/KDBX/Group.pm index d0bd9d7..fe087d2 100644 --- a/lib/File/KDBX/Group.pm +++ b/lib/File/KDBX/Group.pm @@ -19,7 +19,7 @@ use namespace::clean; extends 'File::KDBX::Object'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION # has uuid => sub { generate_uuid(printable => 1) }; @@ -398,7 +398,7 @@ File::KDBX::Group - A KDBX database group =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION @@ -410,10 +410,6 @@ the attributes to see what's available. =head1 ATTRIBUTES -=head2 uuid - -128-bit UUID identifying the group within the database. - =head2 name The human-readable name of the group. @@ -422,18 +418,6 @@ The human-readable name of the group. Free form text string associated with the group. -=head2 tags - -Text string with arbitrary tags which can be used to build a taxonomy. - -=head2 icon_id - -Integer representing a default icon. See L for valid values. - -=head2 custom_icon_uuid - -128-bit UUID identifying a custom icon within the database. - =head2 is_expanded Whether or not subgroups are visible when listed for user selection. @@ -454,15 +438,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. -=head2 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). - -=head2 previous_parent_group - -128-bit UUID identifying a group within the database. - =head2 entries Array of entries contained within the group. @@ -471,41 +446,13 @@ Array of entries contained within the group. Array of subgroups contained within the group. -=head2 last_modification_time - -Date and time when the entry was last modified. - -=head2 creation_time - -Date and time when the entry was created. - -=head2 last_access_time - -Date and time when the entry was last accessed. - -=head2 expiry_time - -Date and time when the entry expired or will expire. - -=head2 expires - -Boolean value indicating whether or not an entry is expired. - -=head2 usage_count - -TODO - -=head2 location_changed - -Date and time when the entry was last moved to a different parent group. - =head1 METHODS =head2 entries \@entries = $group->entries; -Get an array of direct entries within a group. +Get an array of direct child entries within a group. =head2 entries_deeply @@ -651,7 +598,7 @@ Get whether or not a group is the recycle bin of its connected database. $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. =head2 is_last_selected diff --git a/lib/File/KDBX/IO.pm b/lib/File/KDBX/IO.pm index 3239a2c..6dc5c9b 100644 --- a/lib/File/KDBX/IO.pm +++ b/lib/File/KDBX/IO.pm @@ -14,7 +14,7 @@ use namespace::clean; extends 'IO::Handle'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _croak { require Carp; goto &Carp::croak } @@ -390,7 +390,7 @@ File::KDBX::IO - Base IO class for KDBX-related streams =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/IO/Crypt.pm b/lib/File/KDBX/IO/Crypt.pm index 44670e8..0d59723 100644 --- a/lib/File/KDBX/IO/Crypt.pm +++ b/lib/File/KDBX/IO/Crypt.pm @@ -11,7 +11,7 @@ use namespace::clean; extends 'File::KDBX::IO'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our $BUFFER_SIZE = 16384; our $ERROR; @@ -139,7 +139,7 @@ File::KDBX::IO::Crypt - Encrypter/decrypter IO handle =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/IO/HashBlock.pm b/lib/File/KDBX/IO/HashBlock.pm index 0030957..21e8a10 100644 --- a/lib/File/KDBX/IO/HashBlock.pm +++ b/lib/File/KDBX/IO/HashBlock.pm @@ -13,7 +13,7 @@ use namespace::clean; extends 'File::KDBX::IO'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our $ALGORITHM = 'SHA256'; our $BLOCK_SIZE = 1048576; # 1MiB our $ERROR; @@ -208,7 +208,7 @@ File::KDBX::IO::HashBlock - Hash block stream IO handle =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/IO/HmacBlock.pm b/lib/File/KDBX/IO/HmacBlock.pm index 26209fb..650d681 100644 --- a/lib/File/KDBX/IO/HmacBlock.pm +++ b/lib/File/KDBX/IO/HmacBlock.pm @@ -13,7 +13,7 @@ use namespace::clean; extends 'File::KDBX::IO'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our $BLOCK_SIZE = 1048576; # 1MiB our $ERROR; @@ -214,7 +214,7 @@ File::KDBX::IO::HmacBlock - HMAC block stream IO handle =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/Iterator.pm b/lib/File/KDBX/Iterator.pm index 5a93f72..3f0124d 100644 --- a/lib/File/KDBX/Iterator.pm +++ b/lib/File/KDBX/Iterator.pm @@ -14,7 +14,7 @@ use namespace::clean; BEGIN { mark_as_loaded('Iterator::Simple::Iterator') } extends 'Iterator::Simple::Iterator'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub new { @@ -221,7 +221,7 @@ File::KDBX::Iterator - KDBX database iterator =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS @@ -244,13 +244,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 METHODS @@ -258,7 +259,7 @@ arguments, and as L is equivalent to calling the iterator without argumen \&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. =head2 next @@ -267,7 +268,6 @@ Blesses an iterator to augment it with buffering plus some useful utility method $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: @@ -283,13 +283,17 @@ without draining it from the iterator. The same item will be returned the next t =head2 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. @@ -301,7 +305,7 @@ See L. $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: =over 4 @@ -311,7 +315,7 @@ Without arguments, C returns a list of the rest of the items. =item 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. +Pass a coderef to be called once per item, in order. Arguments to the coderef are the item itself (also available as C<$_>), its index number and then any extra arguments that were passed to C after the coderef. =item 3 @@ -326,16 +330,19 @@ B This method drains the iterator completely, leaving it empty. See Lgrep(\&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. =head2 map \&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. =head2 order_by @@ -366,8 +373,6 @@ Any B option is also supported. =back -C and C are aliases. - B This method drains the iterator completely and places the sorted items onto the buffer. See L. @@ -392,8 +397,6 @@ C - Order ascending if true, descending otherwise (default: true) =back -C and C are aliases. - B This method drains the iterator completely and places the sorted items onto the buffer. See L. @@ -407,7 +410,7 @@ Alias for L. 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)" >>. =head2 to_array diff --git a/lib/File/KDBX/KDF.pm b/lib/File/KDBX/KDF.pm index 19677c2..4b7c920 100644 --- a/lib/File/KDBX/KDF.pm +++ b/lib/File/KDBX/KDF.pm @@ -12,7 +12,7 @@ use Module::Load; use Scalar::Util qw(blessed); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION my %KDFS; @@ -120,7 +120,7 @@ File::KDBX::KDF - A key derivation function =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/KDF/AES.pm b/lib/File/KDBX/KDF/AES.pm index b2ed0bd..07ff122 100644 --- a/lib/File/KDBX/KDF/AES.pm +++ b/lib/File/KDBX/KDF/AES.pm @@ -13,7 +13,7 @@ use namespace::clean; extends 'File::KDBX::KDF'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION # Rounds higher than this are eligible for forking: my $FORK_OPTIMIZATION_THRESHOLD = 100_000; @@ -111,7 +111,7 @@ File::KDBX::KDF::AES - Using the AES cipher as a key derivation function =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/KDF/Argon2.pm b/lib/File/KDBX/KDF/Argon2.pm index b41c5e4..9951473 100644 --- a/lib/File/KDBX/KDF/Argon2.pm +++ b/lib/File/KDBX/KDF/Argon2.pm @@ -12,7 +12,7 @@ use namespace::clean; extends 'File::KDBX::KDF'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub salt { $_[0]->{+KDF_PARAM_ARGON2_SALT} or throw 'Salt is not set' } @@ -69,7 +69,7 @@ File::KDBX::KDF::Argon2 - The Argon2 family of key derivation functions =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/Key.pm b/lib/File/KDBX/Key.pm index c7bb2b3..9333072 100644 --- a/lib/File/KDBX/Key.pm +++ b/lib/File/KDBX/Key.pm @@ -14,7 +14,7 @@ use Ref::Util qw(is_arrayref is_coderef is_hashref is_ref is_scalarref); use Scalar::Util qw(blessed openhandle); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION fieldhashes \my %SAFE; @@ -140,7 +140,7 @@ File::KDBX::Key - A credential that can protect a KDBX file =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION @@ -159,7 +159,7 @@ L - Password or passphrase, knowledge of a string of =item * -L - Possession of a file ("key file") with a secret. +L - Possession of a file ("key file") with a secret =item * @@ -183,7 +183,7 @@ 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: =over 4 @@ -197,7 +197,7 @@ One key file =item * -One password and one key file +Composite of one password and one key file =back @@ -254,8 +254,8 @@ access it, you should memzero or L it when you're done. $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. =head2 show diff --git a/lib/File/KDBX/Key/ChallengeResponse.pm b/lib/File/KDBX/Key/ChallengeResponse.pm index 8f9dbde..1dd88ee 100644 --- a/lib/File/KDBX/Key/ChallengeResponse.pm +++ b/lib/File/KDBX/Key/ChallengeResponse.pm @@ -10,7 +10,7 @@ use namespace::clean; extends 'File::KDBX::Key'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub init { my $self = shift; @@ -56,7 +56,7 @@ File::KDBX::Key::ChallengeResponse - A challenge-response key =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS @@ -73,8 +73,8 @@ version 0.800 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. @@ -89,7 +89,7 @@ also L which is a subclass that allows YubiKeys to be $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. diff --git a/lib/File/KDBX/Key/Composite.pm b/lib/File/KDBX/Key/Composite.pm index a1d173a..9ecc0f1 100644 --- a/lib/File/KDBX/Key/Composite.pm +++ b/lib/File/KDBX/Key/Composite.pm @@ -13,7 +13,7 @@ use namespace::clean; extends 'File::KDBX::Key'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub init { my $self = shift; @@ -92,7 +92,7 @@ File::KDBX::Key::Composite - A composite key made up of component keys =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Key/File.pm b/lib/File/KDBX/Key/File.pm index efbbbd2..6e4173e 100644 --- a/lib/File/KDBX/Key/File.pm +++ b/lib/File/KDBX/Key/File.pm @@ -17,7 +17,7 @@ use namespace::clean; extends 'File::KDBX::Key'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has 'type', is => 'ro'; @@ -256,7 +256,7 @@ File::KDBX::Key::File - A file key =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS @@ -297,7 +297,7 @@ There are multiple types of key files supported. See L. This module can r $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: =over 4 diff --git a/lib/File/KDBX/Key/Password.pm b/lib/File/KDBX/Key/Password.pm index 24568a3..d7aa7d5 100644 --- a/lib/File/KDBX/Key/Password.pm +++ b/lib/File/KDBX/Key/Password.pm @@ -12,7 +12,7 @@ use namespace::clean; extends 'File::KDBX::Key'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub init { my $self = shift; @@ -37,7 +37,7 @@ File::KDBX::Key::Password - A password key =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Key/YubiKey.pm b/lib/File/KDBX/Key/YubiKey.pm index f29df01..949f348 100644 --- a/lib/File/KDBX/Key/YubiKey.pm +++ b/lib/File/KDBX/Key/YubiKey.pm @@ -14,7 +14,7 @@ use namespace::clean; extends 'File::KDBX::Key::ChallengeResponse'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION # It can take some time for the USB device to be ready again, so we can retry a few times. our $RETRY_COUNT = 5; @@ -296,7 +296,7 @@ File::KDBX::Key::YubiKey - A Yubico challenge-response key =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Loader.pm b/lib/File/KDBX/Loader.pm index 209a2a6..dd0caff 100644 --- a/lib/File/KDBX/Loader.pm +++ b/lib/File/KDBX/Loader.pm @@ -14,7 +14,7 @@ use Ref::Util qw(is_ref is_scalarref); use Scalar::Util qw(looks_like_number openhandle); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub new { @@ -146,9 +146,6 @@ has format => undef, is => 'ro'; has inner_format => 'XML', is => 'ro'; -sub min_version { KDBX_VERSION_OLDEST } - - sub read_magic_numbers { my $self = shift; my $fh = shift; @@ -252,7 +249,7 @@ File::KDBX::Loader - Load KDBX files =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION @@ -308,7 +305,7 @@ C - Read the database groups and entries as XML (default) =item * -C - Read parsing and store the result in L +C - Read and store the result in L without parsing =back @@ -343,7 +340,7 @@ Set a L to a blank state, ready to load another KDBX file. 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. =head2 load_string @@ -368,15 +365,6 @@ Read a KDBX file from a filesystem. Read a KDBX file from an input stream / file handle. -=head2 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. - =head2 read_magic_numbers $magic = File::KDBX::Loader->read_magic_numbers($fh); diff --git a/lib/File/KDBX/Loader/KDB.pm b/lib/File/KDBX/Loader/KDB.pm index 6ab093b..3e1e35e 100644 --- a/lib/File/KDBX/Loader/KDB.pm +++ b/lib/File/KDBX/Loader/KDB.pm @@ -17,7 +17,7 @@ use namespace::clean; extends 'File::KDBX::Loader'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION my $DEFAULT_EXPIRATION = Time::Piece->new(32503677839); # 2999-12-31 23:59:59 @@ -397,7 +397,7 @@ File::KDBX::Loader::KDB - Read KDB files =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION diff --git a/lib/File/KDBX/Loader/Raw.pm b/lib/File/KDBX/Loader/Raw.pm index 5409578..d86b782 100644 --- a/lib/File/KDBX/Loader/Raw.pm +++ b/lib/File/KDBX/Loader/Raw.pm @@ -9,7 +9,7 @@ use namespace::clean; extends 'File::KDBX::Loader'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _read { my $self = shift; @@ -47,7 +47,7 @@ File::KDBX::Loader::Raw - A no-op loader that doesn't do any parsing =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Loader/V3.pm b/lib/File/KDBX/Loader/V3.pm index 4d10a75..8d2047c 100644 --- a/lib/File/KDBX/Loader/V3.pm +++ b/lib/File/KDBX/Loader/V3.pm @@ -27,7 +27,7 @@ use namespace::clean; extends 'File::KDBX::Loader'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _read_header { my $self = shift; @@ -175,7 +175,7 @@ File::KDBX::Loader::V3 - Load KDBX3 files =head1 VERSION -version 0.800 +version 0.900 =head1 BUGS diff --git a/lib/File/KDBX/Loader/V4.pm b/lib/File/KDBX/Loader/V4.pm index 4db30e7..3cf1a15 100644 --- a/lib/File/KDBX/Loader/V4.pm +++ b/lib/File/KDBX/Loader/V4.pm @@ -30,7 +30,7 @@ use namespace::clean; extends 'File::KDBX::Loader'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub _read_header { my $self = shift; @@ -275,7 +275,7 @@ File::KDBX::Loader::V4 - Load KDBX4 files =head1 VERSION -version 0.800 +version 0.900 =head1 BUGS diff --git a/lib/File/KDBX/Loader/XML.pm b/lib/File/KDBX/Loader/XML.pm index 1243114..89234b5 100644 --- a/lib/File/KDBX/Loader/XML.pm +++ b/lib/File/KDBX/Loader/XML.pm @@ -18,7 +18,7 @@ use namespace::clean; extends 'File::KDBX::Loader'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION has '_reader', is => 'ro'; has '_safe', is => 'ro', default => sub { File::KDBX::Safe->new(cipher => $_[0]->kdbx->random_stream) }; @@ -591,7 +591,7 @@ File::KDBX::Loader::XML - Load unencrypted XML KeePass files =head1 VERSION -version 0.800 +version 0.900 =head1 BUGS diff --git a/lib/File/KDBX/Object.pm b/lib/File/KDBX/Object.pm index cdf0ca4..bdf86a8 100644 --- a/lib/File/KDBX/Object.pm +++ b/lib/File/KDBX/Object.pm @@ -14,7 +14,7 @@ use Ref::Util qw(is_arrayref is_plain_arrayref is_plain_hashref is_ref); use Scalar::Util qw(blessed weaken); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION fieldhashes \my (%KDBX, %PARENT, %TXNS, %REFS, %SIGNALS); @@ -526,7 +526,7 @@ File::KDBX::Object - A KDBX database object =head1 VERSION -version 0.800 +version 0.900 =head1 DESCRIPTION @@ -608,7 +608,58 @@ Instead, do this: $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. + +=head2 uuid + +128-bit UUID identifying the object within the connected database. + +=head2 icon_id + +Integer representing a default icon. See L for valid values. + +=head2 custom_icon_uuid + +128-bit UUID identifying a custom icon within the connected database. + +=head2 tags + +Text string with arbitrary tags which can be used to build a taxonomy. + +=head2 previous_parent_group + +128-bit UUID identifying a group within the connected database the previously contained the object. + +=head2 last_modification_time + +Date and time when the entry was last modified. + +=head2 creation_time + +Date and time when the entry was created. + +=head2 last_access_time + +Date and time when the entry was last accessed. + +=head2 expiry_time + +Date and time when the entry expired or will expire. + +=head2 expires + +Boolean value indicating whether or not an entry is expired. + +=head2 usage_count + +The number of times an entry has been used, which typically means how many times the B string has +been accessed. + +=head2 location_changed + +Date and time when the entry was last moved to a different parent group. =head1 METHODS @@ -753,7 +804,7 @@ structure. Returns an empty arrayref is the object itself is a root group. $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: =over 4 @@ -820,7 +871,9 @@ C - Just what it says (datetime) $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. diff --git a/lib/File/KDBX/Safe.pm b/lib/File/KDBX/Safe.pm index 5bd55a9..ea0c402 100644 --- a/lib/File/KDBX/Safe.pm +++ b/lib/File/KDBX/Safe.pm @@ -14,7 +14,7 @@ use Ref::Util qw(is_arrayref is_coderef is_hashref is_scalarref); use Scalar::Util qw(refaddr); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub new { @@ -217,7 +217,7 @@ File::KDBX::Safe - Keep strings encrypted while in memory =head1 VERSION -version 0.800 +version 0.900 =head1 SYNOPSIS diff --git a/lib/File/KDBX/Transaction.pm b/lib/File/KDBX/Transaction.pm index 8cf88e6..d33a48f 100644 --- a/lib/File/KDBX/Transaction.pm +++ b/lib/File/KDBX/Transaction.pm @@ -8,7 +8,7 @@ use Devel::GlobalDestruction; use File::KDBX::Util qw(:class); use namespace::clean; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION sub new { @@ -59,7 +59,7 @@ File::KDBX::Transaction - Make multiple database edits atomically =head1 VERSION -version 0.800 +version 0.900 =head1 ATTRIBUTES diff --git a/lib/File/KDBX/Util.pm b/lib/File/KDBX/Util.pm index 6905691..948cf16 100644 --- a/lib/File/KDBX/Util.pm +++ b/lib/File/KDBX/Util.pm @@ -17,7 +17,7 @@ use Time::Piece; use boolean; use namespace::clean -except => 'import'; -our $VERSION = '0.800'; # VERSION +our $VERSION = '0.900'; # VERSION our %EXPORT_TAGS = ( assert => [qw(DEBUG assert assert_64bit)], @@ -803,7 +803,7 @@ File::KDBX::Util - Utility functions for working with KDBX files =head1 VERSION -version 0.800 +version 0.900 =head1 FUNCTIONS @@ -1043,7 +1043,7 @@ The logic can be specified in a manner similar to L for examples. +See L for examples. =head2 query_any diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd index b8f2057..b34f59d 100644 --- a/t/00-report-prereqs.dd +++ b/t/00-report-prereqs.dd @@ -60,7 +60,6 @@ do { my $x = { 'IO::Handle' => '0', 'IPC::Cmd' => '0.52', 'Iterator::Simple' => '0', - 'Iterator::Simple::Iterator' => '0', 'List::Util' => '1.33', 'Module::Load' => '0', 'Module::Loaded' => '0', -- 2.44.0