From 6a044919f8af7dba1dc8af337b1946c3be16a334 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 09:56:55 -0500 Subject: [PATCH 01/20] Update .gitignore and get make manifest working --- .gitignore | 11 +++++++---- MANIFEST | 4 ++-- MANIFEST.SKIP | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 09d1765..af811f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ +*~ +/*.tar.gz /Makefile -/MYMETA.yml -/blib/ +/*.old /pm_to_blib -*.old -*.tar.gz +/blib +/MYMETA.* +/META.* +/MANIFEST.bak diff --git a/MANIFEST b/MANIFEST index 2ffedf0..bf3d040 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,10 +1,10 @@ Changes +digest-bench Digest.pm Digest/base.pm Digest/file.pm -digest-bench -MANIFEST Makefile.PL +MANIFEST This list of files README t/base.t t/digest.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index fa0a818..62a3677 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,13 +1,22 @@ ^blib/ -^.git/ -^.gitignore$ \.old$ \.bak$ -\.tar.gz$ Makefile$ -^MYMETA.yml$ ^MANIFEST.SKIP$ ^# /# ~$ +\b(RCS|CVS)/[^/]+$ +\.cvsignore$ pm_to_blib$ +\.o$ +\.c$ +\.bs$ +^Digest-.*\.tar\.gz$ +^other/ +^.git/ +^\.github/ +^cpanfile$ +^\.gitignore$ +^\.travis.yml$ +^MYMETA\. From 26b2c8ed2f49c8256141715877c72dc6684b2dac Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 10:04:45 -0500 Subject: [PATCH 02/20] CI Workflow --- .github/workflows/testsuite.yml | 105 ++++++++++++++++++++++++++++++++ cpanfile | 10 +++ 2 files changed, 115 insertions(+) create mode 100644 .github/workflows/testsuite.yml create mode 100644 cpanfile diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml new file mode 100644 index 0000000..3cd0e3e --- /dev/null +++ b/.github/workflows/testsuite.yml @@ -0,0 +1,105 @@ +name: testsuite + +on: + push: + branches: + - "*" + tags-ignore: + - "*" + pull_request: + +jobs: + ubuntu: + env: + PERL_USE_UNSAFE_INC: 0 + AUTHOR_TESTING: 1 + AUTOMATED_TESTING: 1 + RELEASE_TESTING: 1 + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - run: perl -V + - name: install dependencies + uses: perl-actions/install-with-cpm@v1 + with: + cpanfile: "cpanfile" + - name: Makefile.PL + run: perl -I$(pwd) Makefile.PL + - name: make test + run: make test + + linux: + name: "linux ${{ matrix.perl-version }}" + needs: [ubuntu] + env: + PERL_USE_UNSAFE_INC: 0 + AUTHOR_TESTING: 1 + AUTOMATED_TESTING: 1 + RELEASE_TESTING: 1 + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + perl-version: + [ + "5.32", + "5.30", + "5.28", + "5.26", + "5.24", + "5.22", + "5.20", + "5.18", + "5.16", + "5.14", + "5.12", + "5.10", + "5.8", + ] + + container: + image: perl:${{ matrix.perl-version }} + + steps: + - uses: actions/checkout@v2 + - run: perl -V + - name: install dependencies + uses: perl-actions/install-with-cpm@v1 + with: + sudo: false + cpanfile: "cpanfile" + - name: Makefile.PL + run: perl -I$(pwd) Makefile.PL + - name: make test + run: make test + + macOS: + needs: [ubuntu] + env: + PERL_USE_UNSAFE_INC: 0 + AUTHOR_TESTING: 1 + AUTOMATED_TESTING: 1 + RELEASE_TESTING: 1 + + runs-on: macOS-latest + + strategy: + fail-fast: false + matrix: + perl-version: [latest] + + steps: + - uses: actions/checkout@v2 + - run: perl -V + - name: install dependencies + uses: perl-actions/install-with-cpm@v1 + with: + cpanfile: "cpanfile" + - name: Makefile.PL + run: perl -I$(pwd) Makefile.PL + - name: make test + run: make test diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..25ee0ee --- /dev/null +++ b/cpanfile @@ -0,0 +1,10 @@ +requires "strict" => "0"; +requires "warnings" => "0"; +requires "Exporter" => "0"; +requires "Carp" => "0"; +requires "Digest::MD5" => "0"; + +on 'test' => sub { + requires 'Test::More' => '0'; +}; + From e5c4fa9396c8039f06dedb8b148b9447474709f3 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 11:35:35 -0500 Subject: [PATCH 03/20] Move Digest to a more modern directory tree layout --- MANIFEST | 6 ++-- Makefile.PL | 60 +++++++++++++++------------------- Digest.pm => lib/Digest.pm | 0 {Digest => lib/Digest}/base.pm | 0 {Digest => lib/Digest}/file.pm | 0 5 files changed, 29 insertions(+), 37 deletions(-) rename Digest.pm => lib/Digest.pm (100%) rename {Digest => lib/Digest}/base.pm (100%) rename {Digest => lib/Digest}/file.pm (100%) diff --git a/MANIFEST b/MANIFEST index bf3d040..7664f70 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,8 +1,8 @@ Changes digest-bench -Digest.pm -Digest/base.pm -Digest/file.pm +lib/Digest.pm +lib/Digest/base.pm +lib/Digest/file.pm Makefile.PL MANIFEST This list of files README diff --git a/Makefile.PL b/Makefile.PL index 5da801f..62606d0 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,43 +1,35 @@ -require 5.004; +require 5.006; +use strict; +use warnings; use ExtUtils::MakeMaker; WriteMakefile( - 'NAME' => 'Digest', - 'VERSION_FROM' => 'Digest.pm', - ($] >= 5.008 ? ('INSTALLDIRS' => 'perl') : ()), - ABSTRACT_FROM => 'Digest.pm', - AUTHOR => 'Gisle Aas ', - LICENSE => 'perl', - MIN_PERL_VERSION => '5.004', - 'PREREQ_PM' => { + 'NAME' => 'Digest', + 'AUTHOR' => 'Gisle Aas ', + 'VERSION_FROM' => 'lib/Digest.pm', + 'ABSTRACT_FROM' => 'lib/Digest.pm', + 'LICENSE' => 'perl', + 'MIN_PERL_VERSION' => '5.006', + 'CONFIGURE_REQUIRES' => { + 'ExtUtils::MakeMaker' => '0', + }, + 'PREREQ_PM' => { 'MIME::Base64' => 0, 'Test::More' => '0.47' }, - META_MERGE => { - resources => { - repository => 'http://github.com/gisle/digest', - } + 'TEST_REQUIRES' => { + 'Test::More' => '0', }, -); + 'INSTALLDIRS' => ( ( $] >= '5.009005' && $] < '5.012' ) ? 'perl' : 'site' ), + 'dist' => { 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, + 'clean' => { 'FILES' => 'Digest-*' }, + + 'META_MERGE' => { + 'resources' => { + 'license' => 'http://dev.perl.org/licenses/', + 'bugtracker' => 'https://github.com/Dual-Life/digest/issues', + 'repository' => 'https://github.com/dual-Life/digest/', -BEGIN { - # compatibility with older versions of MakeMaker - my $developer = -f ".gitignore"; - my %mm_req = ( - LICENCE => 6.31, - META_MERGE => 6.45, - META_ADD => 6.45, - MIN_PERL_VERSION => 6.48, - ); - undef(*WriteMakefile); - *WriteMakefile = sub { - my %arg = @_; - for (keys %mm_req) { - unless (eval { ExtUtils::MakeMaker->VERSION($mm_req{$_}) }) { - warn "$_ $@" if $developer; - delete $arg{$_}; - } } - ExtUtils::MakeMaker::WriteMakefile(%arg); - }; -} + }, +); diff --git a/Digest.pm b/lib/Digest.pm similarity index 100% rename from Digest.pm rename to lib/Digest.pm diff --git a/Digest/base.pm b/lib/Digest/base.pm similarity index 100% rename from Digest/base.pm rename to lib/Digest/base.pm diff --git a/Digest/file.pm b/lib/Digest/file.pm similarity index 100% rename from Digest/file.pm rename to lib/Digest/file.pm From 2840efea94e26f324381e85a0cec2e4dbbb413e7 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 11:36:59 -0500 Subject: [PATCH 04/20] Ignore dist dirs --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index af811f2..132fccc 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /MYMETA.* /META.* /MANIFEST.bak +/Digest-[0-9]* \ No newline at end of file From 1cd2105dd390559b39b126180644c9c96e24f1d9 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 11:52:06 -0500 Subject: [PATCH 05/20] Enable strict/warnings for code and tests Drop use vars --- lib/Digest.pm | 7 ++++--- lib/Digest/base.pm | 5 +++-- lib/Digest/file.pm | 9 ++++----- t/base.t | 6 ++++-- t/digest.t | 2 ++ t/file.t | 19 +++++++++++-------- t/lib/Digest/Dummy.pm | 7 ++++--- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/Digest.pm b/lib/Digest.pm index 2ae6eec..ad5a937 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -1,11 +1,11 @@ package Digest; use strict; -use vars qw($VERSION %MMAP $AUTOLOAD); +use warnings; -$VERSION = "1.17"; +our $VERSION = "1.17"; -%MMAP = ( +our %MMAP = ( "SHA-1" => [["Digest::SHA", 1], "Digest::SHA1", ["Digest::SHA2", 1]], "SHA-224" => [["Digest::SHA", 224]], "SHA-256" => [["Digest::SHA", 256], ["Digest::SHA2", 256]], @@ -53,6 +53,7 @@ sub new die $err; } +our $AUTOLOAD; sub AUTOLOAD { my $class = shift; diff --git a/lib/Digest/base.pm b/lib/Digest/base.pm index 2535901..8d7b151 100644 --- a/lib/Digest/base.pm +++ b/lib/Digest/base.pm @@ -1,8 +1,9 @@ package Digest::base; use strict; -use vars qw($VERSION); -$VERSION = "1.16"; +use warnings; + +our $VERSION = "1.16"; # subclass is supposed to implement at least these sub new; diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 3b86e63..5024baf 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -1,16 +1,15 @@ package Digest::file; use strict; +use warnings; use Exporter (); use Carp qw(croak); use Digest (); -use vars qw($VERSION @ISA @EXPORT_OK); - -$VERSION = "1.16"; -@ISA = qw(Exporter); -@EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); +our $VERSION = "1.16"; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); sub digest_file_ctx { my $file = shift; diff --git a/t/base.t b/t/base.t index 9fc861e..b2bc52e 100644 --- a/t/base.t +++ b/t/base.t @@ -1,12 +1,14 @@ #!perl -w +use strict; +use warnings; + use Test::More tests => 13; { package LenDigest; require Digest::base; - use vars qw(@ISA); - @ISA = qw(Digest::base); + our @ISA = qw(Digest::base); sub new { my $class = shift; diff --git a/t/digest.t b/t/digest.t index 8126027..c2dfe1a 100644 --- a/t/digest.t +++ b/t/digest.t @@ -1,6 +1,8 @@ #!/usr/bin/env perl use strict; +use warnings; + use Test::More tests => 4; # To find Digest::Dummy diff --git a/t/file.t b/t/file.t index 79f32de..7c14351 100644 --- a/t/file.t +++ b/t/file.t @@ -1,12 +1,15 @@ #!perl -w +use strict; +use warnings; + use Test::More tests => 5; { package Digest::Foo; + $INC{'Digest/Foo.pm'} = "local"; require Digest::base; - use vars qw(@ISA $VERSION); - @ISA = qw(Digest::base); + our @ISA = qw(Digest::base); sub new { my $class = shift; @@ -30,10 +33,10 @@ use Digest::file qw(digest_file digest_file_hex digest_file_base64); my $file = "test-$$"; die if -f $file; -open(F, ">$file") || die "Can't create '$file': $!"; -binmode(F); -print F "foo\0\n"; -close(F) || die "Can't write '$file': $!"; +open(my $fh, ">$file") || die "Can't create '$file': $!"; +binmode($fh); +print $fh "foo\0\n"; +close($fh) || die "Can't write '$file': $!"; is(digest_file($file, "Foo"), "0005"); @@ -45,7 +48,7 @@ if (ord('A') == 193) { # EBCDIC. is(digest_file_base64($file, "Foo"), "MDAwNQ"); } -unlink($file) || warn "Can't unlink '$file': $!"; - ok !eval { digest_file("not-there.txt", "Foo") }; ok $@; + +END { unlink "$file"; } diff --git a/t/lib/Digest/Dummy.pm b/t/lib/Digest/Dummy.pm index b3db0db..5216932 100644 --- a/t/lib/Digest/Dummy.pm +++ b/t/lib/Digest/Dummy.pm @@ -1,11 +1,12 @@ package Digest::Dummy; use strict; -use vars qw($VERSION @ISA); -$VERSION = 1; +use warnings; + +our $VERSION = 1; +our @ISA = qw(Digest::base); require Digest::base; -@ISA = qw(Digest::base); sub new { my $class = shift; From 5232b0f6d4c9be53c84afdb98dd66bda02f23948 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 11:54:08 -0500 Subject: [PATCH 06/20] Provide a consistent tidy to the code base --- .perltidyrc | 8 ++++ MANIFEST.SKIP | 1 + digest-bench | 19 ++++---- lib/Digest.pm | 57 ++++++++++++------------ lib/Digest/base.pm | 36 +++++++-------- lib/Digest/file.pm | 6 +-- t/base.t | 100 +++++++++++++++++++++--------------------- t/digest.t | 2 +- t/file.t | 62 +++++++++++++------------- t/lib/Digest/Dummy.pm | 6 +-- 10 files changed, 153 insertions(+), 144 deletions(-) create mode 100644 .perltidyrc diff --git a/.perltidyrc b/.perltidyrc new file mode 100644 index 0000000..3403898 --- /dev/null +++ b/.perltidyrc @@ -0,0 +1,8 @@ +-l=400 +-i=4 +-dt=4 +-it=4 +-bar +-nsfs +-nolq +--break-at-old-comma-breakpoints diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 62a3677..1f5a709 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -20,3 +20,4 @@ pm_to_blib$ ^\.gitignore$ ^\.travis.yml$ ^MYMETA\. +^\.perltidyrc$ diff --git a/digest-bench b/digest-bench index 909e5eb..f828b2b 100755 --- a/digest-bench +++ b/digest-bench @@ -3,26 +3,27 @@ use strict; die unless @ARGV; -my($mod, @args) = @ARGV; +my ( $mod, @args ) = @ARGV; -eval "require $mod"; die $@ if $@; +eval "require $mod"; +die $@ if $@; -$a = substr(join("", "a" .. "z",) x 800, 0, 8 * 1024); -my $count = 4*1024; +$a = substr( join( "", "a" .. "z", ) x 800, 0, 8 * 1024 ); +my $count = 4 * 1024; use Time::HiRes qw(time); my $before = time; -my $ctx = $mod->new(@args); -for (1 .. $count) { +my $ctx = $mod->new(@args); +for ( 1 .. $count ) { $ctx->add($a); } print $ctx->hexdigest, "\n"; -my $sec = time - $before; +my $sec = time - $before; my $bytes = length($a) * $count; print "$bytes/$sec\n"; -my $vers = do { no strict 'refs'; ${$mod . '::VERSION'} }; -printf "$mod $vers\t%.2f MB/s\n", $bytes/(1024*1024*$sec) +my $vers = do { no strict 'refs'; ${ $mod . '::VERSION' } }; +printf "$mod $vers\t%.2f MB/s\n", $bytes / ( 1024 * 1024 * $sec ) diff --git a/lib/Digest.pm b/lib/Digest.pm index ad5a937..55bb548 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -6,40 +6,39 @@ use warnings; our $VERSION = "1.17"; our %MMAP = ( - "SHA-1" => [["Digest::SHA", 1], "Digest::SHA1", ["Digest::SHA2", 1]], - "SHA-224" => [["Digest::SHA", 224]], - "SHA-256" => [["Digest::SHA", 256], ["Digest::SHA2", 256]], - "SHA-384" => [["Digest::SHA", 384], ["Digest::SHA2", 384]], - "SHA-512" => [["Digest::SHA", 512], ["Digest::SHA2", 512]], - "SHA3-224" => [["Digest::SHA3", 224]], - "SHA3-256" => [["Digest::SHA3", 256]], - "SHA3-384" => [["Digest::SHA3", 384]], - "SHA3-512" => [["Digest::SHA3", 512]], - "HMAC-MD5" => "Digest::HMAC_MD5", - "HMAC-SHA-1" => "Digest::HMAC_SHA1", - "CRC-16" => [["Digest::CRC", type => "crc16"]], - "CRC-32" => [["Digest::CRC", type => "crc32"]], - "CRC-CCITT" => [["Digest::CRC", type => "crcccitt"]], - "RIPEMD-160" => "Crypt::RIPEMD160", + "SHA-1" => [ [ "Digest::SHA", 1 ], "Digest::SHA1", [ "Digest::SHA2", 1 ] ], + "SHA-224" => [ [ "Digest::SHA", 224 ] ], + "SHA-256" => [ [ "Digest::SHA", 256 ], [ "Digest::SHA2", 256 ] ], + "SHA-384" => [ [ "Digest::SHA", 384 ], [ "Digest::SHA2", 384 ] ], + "SHA-512" => [ [ "Digest::SHA", 512 ], [ "Digest::SHA2", 512 ] ], + "SHA3-224" => [ [ "Digest::SHA3", 224 ] ], + "SHA3-256" => [ [ "Digest::SHA3", 256 ] ], + "SHA3-384" => [ [ "Digest::SHA3", 384 ] ], + "SHA3-512" => [ [ "Digest::SHA3", 512 ] ], + "HMAC-MD5" => "Digest::HMAC_MD5", + "HMAC-SHA-1" => "Digest::HMAC_SHA1", + "CRC-16" => [ [ "Digest::CRC", type => "crc16" ] ], + "CRC-32" => [ [ "Digest::CRC", type => "crc32" ] ], + "CRC-CCITT" => [ [ "Digest::CRC", type => "crcccitt" ] ], + "RIPEMD-160" => "Crypt::RIPEMD160", ); -sub new -{ - shift; # class ignored +sub new { + shift; # class ignored my $algorithm = shift; - my $impl = $MMAP{$algorithm} || do { + my $impl = $MMAP{$algorithm} || do { $algorithm =~ s/\W+//g; "Digest::$algorithm"; }; $impl = [$impl] unless ref($impl); - local $@; # don't clobber it for our caller + local $@; # don't clobber it for our caller my $err; - for (@$impl) { + for (@$impl) { my $class = $_; my @args; - ($class, @args) = @$class if ref($class); + ( $class, @args ) = @$class if ref($class); no strict 'refs'; - unless (exists ${"$class\::"}{"VERSION"}) { + unless ( exists ${"$class\::"}{"VERSION"} ) { my $pm_file = $class . ".pm"; $pm_file =~ s{::}{/}g; eval { require $pm_file }; @@ -48,17 +47,17 @@ sub new next; } } - return $class->new(@args, @_); + return $class->new( @args, @_ ); } die $err; } our $AUTOLOAD; -sub AUTOLOAD -{ - my $class = shift; - my $algorithm = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2); - $class->new($algorithm, @_); + +sub AUTOLOAD { + my $class = shift; + my $algorithm = substr( $AUTOLOAD, rindex( $AUTOLOAD, '::' ) + 2 ); + $class->new( $algorithm, @_ ); } 1; diff --git a/lib/Digest/base.pm b/lib/Digest/base.pm index 8d7b151..bd86e56 100644 --- a/lib/Digest/base.pm +++ b/lib/Digest/base.pm @@ -13,21 +13,21 @@ sub digest; sub reset { my $self = shift; - $self->new(@_); # ugly + $self->new(@_); # ugly } sub addfile { - my ($self, $handle) = @_; + my ( $self, $handle ) = @_; my $n; my $buf = ""; - while (($n = read($handle, $buf, 4*1024))) { + while ( ( $n = read( $handle, $buf, 4 * 1024 ) ) ) { $self->add($buf); } - unless (defined $n) { - require Carp; - Carp::croak("Read failed: $!"); + unless ( defined $n ) { + require Carp; + Carp::croak("Read failed: $!"); } $self; @@ -37,29 +37,29 @@ sub add_bits { my $self = shift; my $bits; my $nbits; - if (@_ == 1) { - my $arg = shift; - $bits = pack("B*", $arg); - $nbits = length($arg); + if ( @_ == 1 ) { + my $arg = shift; + $bits = pack( "B*", $arg ); + $nbits = length($arg); } else { - ($bits, $nbits) = @_; + ( $bits, $nbits ) = @_; } - if (($nbits % 8) != 0) { - require Carp; - Carp::croak("Number of bits must be multiple of 8 for this algorithm"); + if ( ( $nbits % 8 ) != 0 ) { + require Carp; + Carp::croak("Number of bits must be multiple of 8 for this algorithm"); } - return $self->add(substr($bits, 0, $nbits/8)); + return $self->add( substr( $bits, 0, $nbits / 8 ) ); } sub hexdigest { my $self = shift; - return unpack("H*", $self->digest(@_)); + return unpack( "H*", $self->digest(@_) ); } sub b64digest { my $self = shift; - my $b64 = $self->base64_padded_digest; + my $b64 = $self->base64_padded_digest; $b64 =~ s/=+$//; return $b64; } @@ -67,7 +67,7 @@ sub b64digest { sub base64_padded_digest { my $self = shift; require MIME::Base64; - return MIME::Base64::encode($self->digest(@_), ""); + return MIME::Base64::encode( $self->digest(@_), "" ); } 1; diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 5024baf..c0c0c3e 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -7,15 +7,15 @@ use Exporter (); use Carp qw(croak); use Digest (); -our $VERSION = "1.16"; -our @ISA = qw(Exporter); +our $VERSION = "1.16"; +our @ISA = qw(Exporter); our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); sub digest_file_ctx { my $file = shift; croak("No digest algorithm specified") unless @_; local *F; - open(F, "<", $file) || croak("Can't open '$file': $!"); + open( F, "<", $file ) || croak("Can't open '$file': $!"); binmode(F); my $ctx = Digest->new(@_); $ctx->addfile(*F); diff --git a/t/base.t b/t/base.t index b2bc52e..0990316 100644 --- a/t/base.t +++ b/t/base.t @@ -6,82 +6,80 @@ use warnings; use Test::More tests => 13; { - package LenDigest; - require Digest::base; - our @ISA = qw(Digest::base); - - sub new { - my $class = shift; - my $str = ""; - bless \$str, $class; - } - - sub add { - my $self = shift; - $$self .= join("", @_); - return $self; - } - - sub digest { - my $self = shift; - my $len = length($$self); - my $first = ($len > 0) ? substr($$self, 0, 1) : "X"; - $$self = ""; - return sprintf "$first%04d", $len; - } + + package LenDigest; + require Digest::base; + our @ISA = qw(Digest::base); + + sub new { + my $class = shift; + my $str = ""; + bless \$str, $class; + } + + sub add { + my $self = shift; + $$self .= join( "", @_ ); + return $self; + } + + sub digest { + my $self = shift; + my $len = length($$self); + my $first = ( $len > 0 ) ? substr( $$self, 0, 1 ) : "X"; + $$self = ""; + return sprintf "$first%04d", $len; + } } my $ctx = LenDigest->new; -is($ctx->digest, "X0000"); +is( $ctx->digest, "X0000" ); my $EBCDIC = ord('A') == 193; if ($EBCDIC) { - is($ctx->hexdigest, "e7f0f0f0f0"); - is($ctx->b64digest, "5/Dw8PA"); - is($ctx->base64_padded_digest, "5/Dw8PA="); -} else { - is($ctx->hexdigest, "5830303030"); - is($ctx->b64digest, "WDAwMDA"); - is($ctx->base64_padded_digest, "WDAwMDA="); + is( $ctx->hexdigest, "e7f0f0f0f0" ); + is( $ctx->b64digest, "5/Dw8PA" ); + is( $ctx->base64_padded_digest, "5/Dw8PA=" ); +} +else { + is( $ctx->hexdigest, "5830303030" ); + is( $ctx->b64digest, "WDAwMDA" ); + is( $ctx->base64_padded_digest, "WDAwMDA=" ); } $ctx->add("foo"); -is($ctx->digest, "f0003"); +is( $ctx->digest, "f0003" ); $ctx->add("foo"); -is($ctx->hexdigest, $EBCDIC ? "86f0f0f0f3" : "6630303033"); +is( $ctx->hexdigest, $EBCDIC ? "86f0f0f0f3" : "6630303033" ); $ctx->add("foo"); -is($ctx->b64digest, $EBCDIC ? "hvDw8PM" : "ZjAwMDM"); +is( $ctx->b64digest, $EBCDIC ? "hvDw8PM" : "ZjAwMDM" ); -open(F, ">xxtest$$") || die; +open( F, ">xxtest$$" ) || die; binmode(F); print F "abc" x 100, "\n"; close(F) || die; -open(F, "xxtest$$") || die; +open( F, "xxtest$$" ) || die; $ctx->addfile(*F); close(F); unlink("xxtest$$") || warn; -is($ctx->digest, "a0301"); +is( $ctx->digest, "a0301" ); -eval { - $ctx->add_bits("1010"); -}; -like($@, '/^Number of bits must be multiple of 8/'); +eval { $ctx->add_bits("1010"); }; +like( $@, '/^Number of bits must be multiple of 8/' ); -$ctx->add_bits($EBCDIC ? "11100100" : "01010101"); -is($ctx->digest, "U0001"); +$ctx->add_bits( $EBCDIC ? "11100100" : "01010101" ); +is( $ctx->digest, "U0001" ); -eval { - $ctx->add_bits("abc", 12); -}; -like($@, '/^Number of bits must be multiple of 8/'); +eval { $ctx->add_bits( "abc", 12 ); }; +like( $@, '/^Number of bits must be multiple of 8/' ); -$ctx->add_bits("abc", 16); -is($ctx->digest, "a0002"); +$ctx->add_bits( "abc", 16 ); +is( $ctx->digest, "a0002" ); -$ctx->add_bits("abc", 32); -is($ctx->digest, "a0003"); +$ctx->add_bits( "abc", 32 ); +is( $ctx->digest, "a0003" ); diff --git a/t/digest.t b/t/digest.t index c2dfe1a..941f21d 100644 --- a/t/digest.t +++ b/t/digest.t @@ -19,6 +19,6 @@ is $d->digest, "ooo"; $d = Digest->Dummy; is $d->digest, "ooo"; -$Digest::MMAP{"Dummy-24"} = [["NotThere"], "NotThereEither", ["Digest::Dummy", 24]]; +$Digest::MMAP{"Dummy-24"} = [ ["NotThere"], "NotThereEither", [ "Digest::Dummy", 24 ] ]; $d = Digest->new("Dummy-24"); is $d->digest, "24"; diff --git a/t/file.t b/t/file.t index 7c14351..f554898 100644 --- a/t/file.t +++ b/t/file.t @@ -6,49 +6,51 @@ use warnings; use Test::More tests => 5; { - package Digest::Foo; - $INC{'Digest/Foo.pm'} = "local"; - require Digest::base; - our @ISA = qw(Digest::base); - - sub new { - my $class = shift; - my $str = ""; - bless \$str, $class; - } - - sub add { - my $self = shift; - $$self .= join("", @_); - return $self; - } - - sub digest { - my $self = shift; - return sprintf "%04d", length($$self); - } + + package Digest::Foo; + $INC{'Digest/Foo.pm'} = "local"; + require Digest::base; + our @ISA = qw(Digest::base); + + sub new { + my $class = shift; + my $str = ""; + bless \$str, $class; + } + + sub add { + my $self = shift; + $$self .= join( "", @_ ); + return $self; + } + + sub digest { + my $self = shift; + return sprintf "%04d", length($$self); + } } use Digest::file qw(digest_file digest_file_hex digest_file_base64); my $file = "test-$$"; die if -f $file; -open(my $fh, ">$file") || die "Can't create '$file': $!"; +open( my $fh, ">$file" ) || die "Can't create '$file': $!"; binmode($fh); print $fh "foo\0\n"; close($fh) || die "Can't write '$file': $!"; -is(digest_file($file, "Foo"), "0005"); +is( digest_file( $file, "Foo" ), "0005" ); -if (ord('A') == 193) { # EBCDIC. - is(digest_file_hex($file, "Foo"), "f0f0f0f5"); - is(digest_file_base64($file, "Foo"), "8PDw9Q"); -} else { - is(digest_file_hex($file, "Foo"), "30303035"); - is(digest_file_base64($file, "Foo"), "MDAwNQ"); +if ( ord('A') == 193 ) { # EBCDIC. + is( digest_file_hex( $file, "Foo" ), "f0f0f0f5" ); + is( digest_file_base64( $file, "Foo" ), "8PDw9Q" ); +} +else { + is( digest_file_hex( $file, "Foo" ), "30303035" ); + is( digest_file_base64( $file, "Foo" ), "MDAwNQ" ); } -ok !eval { digest_file("not-there.txt", "Foo") }; +ok !eval { digest_file( "not-there.txt", "Foo" ) }; ok $@; END { unlink "$file"; } diff --git a/t/lib/Digest/Dummy.pm b/t/lib/Digest/Dummy.pm index 5216932..018e12c 100644 --- a/t/lib/Digest/Dummy.pm +++ b/t/lib/Digest/Dummy.pm @@ -4,17 +4,17 @@ use strict; use warnings; our $VERSION = 1; -our @ISA = qw(Digest::base); +our @ISA = qw(Digest::base); require Digest::base; sub new { my $class = shift; - my $d = shift || "ooo"; + my $d = shift || "ooo"; bless { d => $d }, $class; } -sub add {} +sub add { } sub digest { shift->{d} } 1; From c5f564a21a6393b9ef1b20e96c96fdd638422881 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 11:56:36 -0500 Subject: [PATCH 07/20] Get rid of bareword file handles --- lib/Digest/file.pm | 9 ++++----- t/base.t | 16 ++++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index c0c0c3e..29ef78c 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -14,12 +14,11 @@ our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base sub digest_file_ctx { my $file = shift; croak("No digest algorithm specified") unless @_; - local *F; - open( F, "<", $file ) || croak("Can't open '$file': $!"); - binmode(F); + open( my $fh, "<", $file ) || croak("Can't open '$file': $!"); + binmode($fh); my $ctx = Digest->new(@_); - $ctx->addfile(*F); - close(F); + $ctx->addfile($fh); + close($fh); return $ctx; } diff --git a/t/base.t b/t/base.t index 0990316..8bd9bdc 100644 --- a/t/base.t +++ b/t/base.t @@ -57,14 +57,14 @@ is( $ctx->hexdigest, $EBCDIC ? "86f0f0f0f3" : "6630303033" ); $ctx->add("foo"); is( $ctx->b64digest, $EBCDIC ? "hvDw8PM" : "ZjAwMDM" ); -open( F, ">xxtest$$" ) || die; -binmode(F); -print F "abc" x 100, "\n"; -close(F) || die; - -open( F, "xxtest$$" ) || die; -$ctx->addfile(*F); -close(F); +open( my $fh, ">xxtest$$" ) || die; +binmode($fh); +print $fh "abc" x 100, "\n"; +close($fh) || die; + +open( my $fh2, "xxtest$$" ) || die; +$ctx->addfile($fh2); +close($fh2); unlink("xxtest$$") || warn; is( $ctx->digest, "a0301" ); From 218c33fe7931236bd16b8fe21e0c2e6a8df5595e Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 12:14:46 -0500 Subject: [PATCH 08/20] Modernize the changelog --- Changes | 266 +++++++++++++++++--------------------------------------- 1 file changed, 81 insertions(+), 185 deletions(-) diff --git a/Changes b/Changes index d91cb35..7e789ce 100644 --- a/Changes +++ b/Changes @@ -1,185 +1,81 @@ -2011-10-02 Gisle Aas - - Release 1.17. - - Gisle Aas (6): - Less noisy 'git status' output - Merge pull request #1 from schwern/bug/require_eval - Don't clobber $@ in Digest->new [RT#50663] - More meta info added to Makefile.PL - Fix typo in RIPEMD160 [RT#50629] - Add schwern's test files - - Michael G. Schwern (5): - Turn on strict. - Convert tests to use Test::More - Untabify - Turn Digest::Dummy into a real file which exercises the Digest->new() require logic. - Close the eval "require $module" security hole in Digest->new($algorithm) - - - -2009-06-09 Gisle Aas - - Release 1.16. - - Gisle Aas (3): - For SHA-1 try Digest::SHA before tryign Digest::SHA1 as suggested by Adam Trickett - Support Digest->new("RIPEMD-160") as suggested by Zefram - Use 3-arg open for fewer surprises - - Jarkko Hietaniemi (1): - Sync up with EBCDIC changes from core perl. - - - -2006-03-20 Gisle Aas - - Release 1.15. - - Improved documentation. - - - -2005-11-26 Gisle Aas - - Release 1.14 - - Documentation tweaks. - - - -2005-10-18 Gisle Aas - - Release 1.13 - - Fixed documentation typo. - - - -2005-09-29 Gisle Aas - - Release 1.12 - - Fix documentation typo. Patch by . - - - -2005-09-11 Gisle Aas - - Release 1.11 - - Make Digest->new("SHA-224") work. Patch by Mark Shelor - . - - - -2004-11-08 Gisle Aas - - Release 1.10 - - Added Digest::file module which provide convenience functions - that calculate digests of files. - - - -2004-11-05 Gisle Aas - - Release 1.09 - - Fix trivial documentation typo. - - - -2004-04-29 Gisle Aas - - Release 1.08 - - Make Digest->new("CRC-16"), Digest->new("CRC-32") and - Digest->new("CRC-CCITT") work. - Patch by Oliver Maul . - - - -2004-04-25 Gisle Aas - - Release 1.07 - - Updated benchmark. - - - -2004-04-01 Gisle Aas - - Release 1.06 - - Added MIME::Base64 dependency. - - Minor doc tweak. - - - -2003-12-01 Gisle Aas - - Release 1.05 - - Drop Digest::MD5 dependency. Avoids circular dependency - now that Digest::MD5 depend on this package to inherit - Digest::base. - - Included a section about digest speed with benchmark - results for some implementations of this API. - - - -2003-11-29 Gisle Aas - - Release 1.04 - - Doc tweaks to unconfuse search.cpan.org. - - - -2003-11-28 Gisle Aas - - Release 1.03 - - Added add_bits() method as requested by the - Digest::SHA author Mark Shelor. - - Added Digest::base class that Digest implementations - can use to get default implementations of addfile(), - add_bits(), hexdigest() and b64digest(). - - Digest->new("SHA-256") and similar should work now - given that you have either Digest::SHA or Digest::SHA2 - installed. - - - -2003-01-18 Gisle Aas - - Release 1.02 - - Sync up with version bundled with perl-5.8. - Patch by Jarkko Hietaniemi . - - Override INSTALLDIRS for 5.8 as suggested by - Guido Ostkamp . - - - -2003-01-04 Gisle Aas - - Release 1.01 - - Document the clone() method. - - - -2001-03-13 Gisle Aas - - Release 1.00 - - Broken out of the Digest-MD5-2.12 distribution and made into - a separate dist. +1.17 Sun 2011-10-02 +- Less noisy 'git status' output - Gisle Aas +- Merge pull request #1 from schwern/bug/require_eval - Gisle Aas +- Don't clobber $@ in Digest->new [RT#50663] - Gisle Aas +- More meta info added to Makefile.PL - Gisle Aas +- Fix typo in RIPEMD160 [RT#50629] - Gisle Aas +- Add schwern's test files - Gisle Aas +- Turn on strict. - Michael G. Schwern +- Convert tests to use Test::More - Michael G. Schwern +- Untabify - Michael G. Schwern +- Turn Digest::Dummy into a real file which exercises the Digest->new() require logic. - Michael G. Schwern +- Close the eval "require $module" security hole in Digest->new($algorithm) - Michael G. Schwern + +1.16 Tue 2009-06-09 +- For SHA-1 try Digest::SHA before tryign Digest::SHA1 as suggested by Adam Trickett - Gisle Aas +- Support Digest->new("RIPEMD-160") as suggested by Zefram - Gisle Aas +- Use 3-arg open for fewer surprises - Gisle Aas +- Sync up with EBCDIC changes from core perl - Jarkko Hietaniemi + +1.15 Mon 2006-03-20 +- Improved documentation. + +1.14 Sat 2005-11-26 +- Documentation tweaks. + +1.13 Tue 2005-10-18 +- Fixed documentation typo. + +1.12 Thu 2005-09-29 +- Fix documentation typo. Patch by . + +1.11 Sun 2005-09-11 +- Make Digest->new("SHA-224") work. Patch by Mark Shelor . + +1.10 Mon 2004-11-08 +- Added Digest::file module which provide convenience functions that calculate digests of files. + +1.09 Fri 2004-11-05 +- Fix trivial documentation typo. + +1.08 Thu 2004-04-29 +- Make Digest->new("CRC-16"), Digest->new("CRC-32") and +- Digest->new("CRC-CCITT") work. + Patch by Oliver Maul . + +1.07 Sun 2004-04-25 +- Updated benchmark. + +1.06 Thu 2004-04-01 +- Added MIME::Base64 dependency. +- Minor doc tweak. + +1.05 Mon 2003-12-01 +- Drop Digest::MD5 dependency. Avoids circular dependency + now that Digest::MD5 depend on this package to inherit + Digest::base. +- Included a section about digest speed with benchmark + results for some implementations of this API. + +1.04 Sat 2003-11-29 +- Doc tweaks to unconfuse search.cpan.org. + +1.03 Fri 2003-11-28 +- Added add_bits() method as requested by the Digest::SHA author Mark Shelor. +- Added Digest::base class that Digest implementations + can use to get default implementations of addfile(), + add_bits(), hexdigest() and b64digest(). +- Digest->new("SHA-256") and similar should work now + given that you have either Digest::SHA or Digest::SHA2 + installed. + +1.02 Sat 2003-01-18 +- Sync up with version bundled with perl-5.8. Patch by Jarkko Hietaniemi . +- Override INSTALLDIRS for 5.8 as suggested by Guido Ostkamp . + +1.01 Sat 2003-01-04 +- Document the clone() method. + +1.00 Tue 2001-03-13 +- Broken out of the Digest-MD5-2.12 distribution and made into + a separate dist. From 90e28dac96011985790e3fd03928ea124df8357b Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 6 Oct 2020 12:25:23 -0500 Subject: [PATCH 09/20] Pending changes updated --- Changes | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Changes b/Changes index 7e789ce..cce4010 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,17 @@ +1.18 XXX 2020-10-XX +- correct documentation for add_bits +- Explain $args,... in constructor prototypes +- Add base64_padded_digest method +- Add support for the SHA3 digests +- Update .gitignore and get make manifest working +- Github CI +- Move Digest to a more modern directory tree layout +- Enable strict/warnings for code and tests +- Drop use vars +- Provide a consistent tidy to the code base +- Get rid of the use of bareword file handles +- Modernize the changelog + 1.17 Sun 2011-10-02 - Less noisy 'git status' output - Gisle Aas - Merge pull request #1 from schwern/bug/require_eval - Gisle Aas From 10dcd677f229654f1afc944af6d8a9532db34723 Mon Sep 17 00:00:00 2001 From: Dan Book Date: Tue, 6 Oct 2020 22:32:36 -0400 Subject: [PATCH 10/20] Makefile.PL - use meta-spec 2, fix prereqs, compatibility with old EUMM - meta-spec 2 resources format - dependencies are static, set dynamic_config 0 - EUMM will set configure_requires on itself - Test::More only used in tests - boilerplate to clean out unsupported keys if installed with old EUMM --- Makefile.PL | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 62606d0..3b63f4d 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -3,33 +3,47 @@ use strict; use warnings; use ExtUtils::MakeMaker; -WriteMakefile( +my %WriteMakefile_args = ( 'NAME' => 'Digest', 'AUTHOR' => 'Gisle Aas ', 'VERSION_FROM' => 'lib/Digest.pm', 'ABSTRACT_FROM' => 'lib/Digest.pm', 'LICENSE' => 'perl', 'MIN_PERL_VERSION' => '5.006', - 'CONFIGURE_REQUIRES' => { - 'ExtUtils::MakeMaker' => '0', - }, 'PREREQ_PM' => { 'MIME::Base64' => 0, - 'Test::More' => '0.47' }, 'TEST_REQUIRES' => { - 'Test::More' => '0', + 'Test::More' => '0.47', }, 'INSTALLDIRS' => ( ( $] >= '5.009005' && $] < '5.012' ) ? 'perl' : 'site' ), 'dist' => { 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, 'clean' => { 'FILES' => 'Digest-*' }, 'META_MERGE' => { + 'meta-spec' => { 'version' => 2 }, + 'dynamic_config' => 0, 'resources' => { - 'license' => 'http://dev.perl.org/licenses/', - 'bugtracker' => 'https://github.com/Dual-Life/digest/issues', - 'repository' => 'https://github.com/dual-Life/digest/', - + 'license' => [ 'http://dev.perl.org/licenses/' ], + 'bugtracker' => { 'web' => 'https://github.com/Dual-Life/digest/issues' }, + 'repository' => { + 'type' => 'git', + 'url' => 'https://github.com/Dual-Life/digest.git', + 'web' => 'https://github.com/Dual-Life/digest', + }, } }, ); + +delete $WriteMakefile_args{LICENSE} + unless eval { ExtUtils::MakeMaker->VERSION('6.31') }; +delete $WriteMakefile_args{META_MERGE} + unless eval { ExtUtils::MakeMaker->VERSION('6.46') }; +delete $WriteMakefile_args{MIN_PERL_VERSION} + unless eval { ExtUtils::MakeMaker->VERSION('6.48') }; +unless (eval { ExtUtils::MakeMaker->VERSION('6.64') }) { + my $test_requires = delete $WriteMakefile_args{TEST_REQUIRES}; + $WriteMakefile_args{PREREQ_PM}{$_} = $test_requires->{$_} for keys %$test_requires; +} + +WriteMakefile(%WriteMakefile_args); From cb8f7c31b1c5bc9569c44d71bcceb8eae1a73343 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Wed, 7 Oct 2020 02:19:35 -0500 Subject: [PATCH 11/20] Github readme --- .github/README.md | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 .github/README.md diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..dabe000 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,247 @@ +# NAME + +Digest - Modules that calculate message digests + +# SYNOPSIS + + $md5 = Digest->new("MD5"); + $sha1 = Digest->new("SHA-1"); + $sha256 = Digest->new("SHA-256"); + $sha384 = Digest->new("SHA-384"); + $sha512 = Digest->new("SHA-512"); + + $hmac = Digest->HMAC_MD5($key); + +# DESCRIPTION + +The `Digest::` modules calculate digests, also called "fingerprints" +or "hashes", of some data, called a message. The digest is (usually) +some small/fixed size string. The actual size of the digest depend of +the algorithm used. The message is simply a sequence of arbitrary +bytes or bits. + +An important property of the digest algorithms is that the digest is +_likely_ to change if the message change in some way. Another +property is that digest functions are one-way functions, that is it +should be _hard_ to find a message that correspond to some given +digest. Algorithms differ in how "likely" and how "hard", as well as +how efficient they are to compute. + +Note that the properties of the algorithms change over time, as the +algorithms are analyzed and machines grow faster. If your application +for instance depends on it being "impossible" to generate the same +digest for a different message it is wise to make it easy to plug in +stronger algorithms as the one used grow weaker. Using the interface +documented here should make it easy to change algorithms later. + +All `Digest::` modules provide the same programming interface. A +functional interface for simple use, as well as an object oriented +interface that can handle messages of arbitrary length and which can +read files directly. + +The digest can be delivered in three formats: + +- _binary_ + + This is the most compact form, but it is not well suited for printing + or embedding in places that can't handle arbitrary data. + +- _hex_ + + A twice as long string of lowercase hexadecimal digits. + +- _base64_ + + A string of portable printable characters. This is the base64 encoded + representation of the digest with any trailing padding removed. The + string will be about 30% longer than the binary version. + [MIME::Base64](https://metacpan.org/pod/MIME::Base64) tells you more about this encoding. + +The functional interface is simply importable functions with the same +name as the algorithm. The functions take the message as argument and +return the digest. Example: + + use Digest::MD5 qw(md5); + $digest = md5($message); + +There are also versions of the functions with "\_hex" or "\_base64" +appended to the name, which returns the digest in the indicated form. + +# OO INTERFACE + +The following methods are available for all `Digest::` modules: + +- $ctx = Digest->XXX($arg,...) +- $ctx = Digest->new(XXX => $arg,...) +- $ctx = Digest::XXX->new($arg,...) + + The constructor returns some object that encapsulate the state of the + message-digest algorithm. You can add data to the object and finally + ask for the digest. The "XXX" should of course be replaced by the proper + name of the digest algorithm you want to use. + + The two first forms are simply syntactic sugar which automatically + load the right module on first use. The second form allow you to use + algorithm names which contains letters which are not legal perl + identifiers, e.g. "SHA-1". If no implementation for the given algorithm + can be found, then an exception is raised. + + To know what arguments (if any) the constructor takes (the `$args,...` above) + consult the docs for the specific digest implementation. + + If new() is called as an instance method (i.e. $ctx->new) it will just + reset the state the object to the state of a newly created object. No + new object is created in this case, and the return value is the + reference to the object (i.e. $ctx). + +- $other\_ctx = $ctx->clone + + The clone method creates a copy of the digest state object and returns + a reference to the copy. + +- $ctx->reset + + This is just an alias for $ctx->new. + +- $ctx->add( $data ) +- $ctx->add( $chunk1, $chunk2, ... ) + + The string value of the $data provided as argument is appended to the + message we calculate the digest for. The return value is the $ctx + object itself. + + If more arguments are provided then they are all appended to the + message, thus all these lines will have the same effect on the state + of the $ctx object: + + $ctx->add("a"); $ctx->add("b"); $ctx->add("c"); + $ctx->add("a")->add("b")->add("c"); + $ctx->add("a", "b", "c"); + $ctx->add("abc"); + + Most algorithms are only defined for strings of bytes and this method + might therefore croak if the provided arguments contain chars with + ordinal number above 255. + +- $ctx->addfile( $io\_handle ) + + The $io\_handle is read until EOF and the content is appended to the + message we calculate the digest for. The return value is the $ctx + object itself. + + The addfile() method will croak() if it fails reading data for some + reason. If it croaks it is unpredictable what the state of the $ctx + object will be in. The addfile() method might have been able to read + the file partially before it failed. It is probably wise to discard + or reset the $ctx object if this occurs. + + In most cases you want to make sure that the $io\_handle is in + "binmode" before you pass it as argument to the addfile() method. + +- $ctx->add\_bits( $data, $nbits ) +- $ctx->add\_bits( $bitstring ) + + The add\_bits() method is an alternative to add() that allow partial + bytes to be appended to the message. Most users can just ignore + this method since typical applications involve only whole-byte data. + + The two argument form of add\_bits() will add the first $nbits bits + from $data. For the last potentially partial byte only the high order + `$nbits % 8` bits are used. If $nbits is greater than `length($data) * 8`, then this method would do the same as `$ctx->add($data)`. + + The one argument form of add\_bits() takes a $bitstring of "1" and "0" + chars as argument. It's a shorthand for `$ctx->add_bits(pack("B*", + $bitstring), length($bitstring))`. + + The return value is the $ctx object itself. + + This example shows two calls that should have the same effect: + + $ctx->add_bits("111100001010"); + $ctx->add_bits("\xF0\xA0", 12); + + Most digest algorithms are byte based and for these it is not possible + to add bits that are not a multiple of 8, and the add\_bits() method + will croak if you try. + +- $ctx->digest + + Return the binary digest for the message. + + Note that the `digest` operation is effectively a destructive, + read-once operation. Once it has been performed, the $ctx object is + automatically `reset` and can be used to calculate another digest + value. Call $ctx->clone->digest if you want to calculate the digest + without resetting the digest state. + +- $ctx->hexdigest + + Same as $ctx->digest, but will return the digest in hexadecimal form. + +- $ctx->b64digest + + Same as $ctx->digest, but will return the digest as a base64 encoded + string without padding. + +- $ctx->base64\_padded\_digest + + Same as $ctx->digest, but will return the digest as a base64 encoded + string. + +# Digest speed + +This table should give some indication on the relative speed of +different algorithms. It is sorted by throughput based on a benchmark +done with of some implementations of this API: + + Algorithm Size Implementation MB/s + + MD4 128 Digest::MD4 v1.3 165.0 + MD5 128 Digest::MD5 v2.33 98.8 + SHA-256 256 Digest::SHA2 v1.1.0 66.7 + SHA-1 160 Digest::SHA v4.3.1 58.9 + SHA-1 160 Digest::SHA1 v2.10 48.8 + SHA-256 256 Digest::SHA v4.3.1 41.3 + Haval-256 256 Digest::Haval256 v1.0.4 39.8 + SHA-384 384 Digest::SHA2 v1.1.0 19.6 + SHA-512 512 Digest::SHA2 v1.1.0 19.3 + SHA-384 384 Digest::SHA v4.3.1 19.2 + SHA-512 512 Digest::SHA v4.3.1 19.2 + Whirlpool 512 Digest::Whirlpool v1.0.2 13.0 + MD2 128 Digest::MD2 v2.03 9.5 + + Adler-32 32 Digest::Adler32 v0.03 1.3 + CRC-16 16 Digest::CRC v0.05 1.1 + CRC-32 32 Digest::CRC v0.05 1.1 + MD5 128 Digest::Perl::MD5 v1.5 1.0 + CRC-CCITT 16 Digest::CRC v0.05 0.8 + +These numbers was achieved Apr 2004 with ActivePerl-5.8.3 running +under Linux on a P4 2.8 GHz CPU. The last 5 entries differ by being +pure perl implementations of the algorithms, which explains why they +are so slow. + +# SEE ALSO + +[Digest::Adler32](https://metacpan.org/pod/Digest::Adler32), [Digest::CRC](https://metacpan.org/pod/Digest::CRC), [Digest::Haval256](https://metacpan.org/pod/Digest::Haval256), +[Digest::HMAC](https://metacpan.org/pod/Digest::HMAC), [Digest::MD2](https://metacpan.org/pod/Digest::MD2), [Digest::MD4](https://metacpan.org/pod/Digest::MD4), [Digest::MD5](https://metacpan.org/pod/Digest::MD5), +[Digest::SHA](https://metacpan.org/pod/Digest::SHA), [Digest::SHA1](https://metacpan.org/pod/Digest::SHA1), [Digest::SHA2](https://metacpan.org/pod/Digest::SHA2), [Digest::Whirlpool](https://metacpan.org/pod/Digest::Whirlpool) + +New digest implementations should consider subclassing from [Digest::base](https://metacpan.org/pod/Digest::base). + +[MIME::Base64](https://metacpan.org/pod/MIME::Base64) + +http://en.wikipedia.org/wiki/Cryptographic\_hash\_function + +# AUTHOR + +Gisle Aas + +The `Digest::` interface is based on the interface originally +developed by Neil Winton for his `MD5` module. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + + Copyright 1998-2006 Gisle Aas. + Copyright 1995,1996 Neil Winton. From 6422aaf1a6e18a61054f8cec98eeea0a2382d476 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Wed, 7 Oct 2020 02:20:18 -0500 Subject: [PATCH 12/20] Update README --- README | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 229 insertions(+), 8 deletions(-) diff --git a/README b/README index 1c062a1..9712b64 100644 --- a/README +++ b/README @@ -1,11 +1,232 @@ -This is just a simple frontend module for autoloading of various -Digest:: modules. It also provide documentation of the interface that -all Digest:: modules should provide. +NAME + Digest - Modules that calculate message digests -You will need perl version 5.004 or better to install this module. +SYNOPSIS + $md5 = Digest->new("MD5"); + $sha1 = Digest->new("SHA-1"); + $sha256 = Digest->new("SHA-256"); + $sha384 = Digest->new("SHA-384"); + $sha512 = Digest->new("SHA-512"); -Copyright 1998-2006 Gisle Aas. -Copyright 1995-1996 Neil Winton. + $hmac = Digest->HMAC_MD5($key); + +DESCRIPTION + The "Digest::" modules calculate digests, also called "fingerprints" or + "hashes", of some data, called a message. The digest is (usually) some + small/fixed size string. The actual size of the digest depend of the + algorithm used. The message is simply a sequence of arbitrary bytes or + bits. + + An important property of the digest algorithms is that the digest is + *likely* to change if the message change in some way. Another property + is that digest functions are one-way functions, that is it should be + *hard* to find a message that correspond to some given digest. + Algorithms differ in how "likely" and how "hard", as well as how + efficient they are to compute. + + Note that the properties of the algorithms change over time, as the + algorithms are analyzed and machines grow faster. If your application + for instance depends on it being "impossible" to generate the same + digest for a different message it is wise to make it easy to plug in + stronger algorithms as the one used grow weaker. Using the interface + documented here should make it easy to change algorithms later. + + All "Digest::" modules provide the same programming interface. A + functional interface for simple use, as well as an object oriented + interface that can handle messages of arbitrary length and which can + read files directly. + + The digest can be delivered in three formats: + + *binary* + This is the most compact form, but it is not well suited for + printing or embedding in places that can't handle arbitrary + data. + + *hex* A twice as long string of lowercase hexadecimal digits. + + *base64* + A string of portable printable characters. This is the base64 + encoded representation of the digest with any trailing padding + removed. The string will be about 30% longer than the binary + version. MIME::Base64 tells you more about this encoding. + + The functional interface is simply importable functions with the same + name as the algorithm. The functions take the message as argument and + return the digest. Example: + + use Digest::MD5 qw(md5); + $digest = md5($message); + + There are also versions of the functions with "_hex" or "_base64" + appended to the name, which returns the digest in the indicated form. + +OO INTERFACE + The following methods are available for all "Digest::" modules: + + $ctx = Digest->XXX($arg,...) + $ctx = Digest->new(XXX => $arg,...) + $ctx = Digest::XXX->new($arg,...) + The constructor returns some object that encapsulate the state of + the message-digest algorithm. You can add data to the object and + finally ask for the digest. The "XXX" should of course be replaced + by the proper name of the digest algorithm you want to use. + + The two first forms are simply syntactic sugar which automatically + load the right module on first use. The second form allow you to use + algorithm names which contains letters which are not legal perl + identifiers, e.g. "SHA-1". If no implementation for the given + algorithm can be found, then an exception is raised. + + To know what arguments (if any) the constructor takes (the + "$args,..." above) consult the docs for the specific digest + implementation. + + If new() is called as an instance method (i.e. $ctx->new) it will + just reset the state the object to the state of a newly created + object. No new object is created in this case, and the return value + is the reference to the object (i.e. $ctx). + + $other_ctx = $ctx->clone + The clone method creates a copy of the digest state object and + returns a reference to the copy. + + $ctx->reset + This is just an alias for $ctx->new. + + $ctx->add( $data ) + $ctx->add( $chunk1, $chunk2, ... ) + The string value of the $data provided as argument is appended to + the message we calculate the digest for. The return value is the + $ctx object itself. + + If more arguments are provided then they are all appended to the + message, thus all these lines will have the same effect on the state + of the $ctx object: + + $ctx->add("a"); $ctx->add("b"); $ctx->add("c"); + $ctx->add("a")->add("b")->add("c"); + $ctx->add("a", "b", "c"); + $ctx->add("abc"); + + Most algorithms are only defined for strings of bytes and this + method might therefore croak if the provided arguments contain chars + with ordinal number above 255. + + $ctx->addfile( $io_handle ) + The $io_handle is read until EOF and the content is appended to the + message we calculate the digest for. The return value is the $ctx + object itself. + + The addfile() method will croak() if it fails reading data for some + reason. If it croaks it is unpredictable what the state of the $ctx + object will be in. The addfile() method might have been able to read + the file partially before it failed. It is probably wise to discard + or reset the $ctx object if this occurs. + + In most cases you want to make sure that the $io_handle is in + "binmode" before you pass it as argument to the addfile() method. + + $ctx->add_bits( $data, $nbits ) + $ctx->add_bits( $bitstring ) + The add_bits() method is an alternative to add() that allow partial + bytes to be appended to the message. Most users can just ignore this + method since typical applications involve only whole-byte data. + + The two argument form of add_bits() will add the first $nbits bits + from $data. For the last potentially partial byte only the high + order "$nbits % 8" bits are used. If $nbits is greater than + "length($data) * 8", then this method would do the same as + "$ctx->add($data)". + + The one argument form of add_bits() takes a $bitstring of "1" and + "0" chars as argument. It's a shorthand for + "$ctx->add_bits(pack("B*", $bitstring), length($bitstring))". + + The return value is the $ctx object itself. + + This example shows two calls that should have the same effect: + + $ctx->add_bits("111100001010"); + $ctx->add_bits("\xF0\xA0", 12); + + Most digest algorithms are byte based and for these it is not + possible to add bits that are not a multiple of 8, and the + add_bits() method will croak if you try. + + $ctx->digest + Return the binary digest for the message. + + Note that the "digest" operation is effectively a destructive, + read-once operation. Once it has been performed, the $ctx object is + automatically "reset" and can be used to calculate another digest + value. Call $ctx->clone->digest if you want to calculate the digest + without resetting the digest state. + + $ctx->hexdigest + Same as $ctx->digest, but will return the digest in hexadecimal + form. + + $ctx->b64digest + Same as $ctx->digest, but will return the digest as a base64 encoded + string without padding. + + $ctx->base64_padded_digest + Same as $ctx->digest, but will return the digest as a base64 encoded + string. + +Digest speed + This table should give some indication on the relative speed of + different algorithms. It is sorted by throughput based on a benchmark + done with of some implementations of this API: + + Algorithm Size Implementation MB/s + + MD4 128 Digest::MD4 v1.3 165.0 + MD5 128 Digest::MD5 v2.33 98.8 + SHA-256 256 Digest::SHA2 v1.1.0 66.7 + SHA-1 160 Digest::SHA v4.3.1 58.9 + SHA-1 160 Digest::SHA1 v2.10 48.8 + SHA-256 256 Digest::SHA v4.3.1 41.3 + Haval-256 256 Digest::Haval256 v1.0.4 39.8 + SHA-384 384 Digest::SHA2 v1.1.0 19.6 + SHA-512 512 Digest::SHA2 v1.1.0 19.3 + SHA-384 384 Digest::SHA v4.3.1 19.2 + SHA-512 512 Digest::SHA v4.3.1 19.2 + Whirlpool 512 Digest::Whirlpool v1.0.2 13.0 + MD2 128 Digest::MD2 v2.03 9.5 + + Adler-32 32 Digest::Adler32 v0.03 1.3 + CRC-16 16 Digest::CRC v0.05 1.1 + CRC-32 32 Digest::CRC v0.05 1.1 + MD5 128 Digest::Perl::MD5 v1.5 1.0 + CRC-CCITT 16 Digest::CRC v0.05 0.8 + + These numbers was achieved Apr 2004 with ActivePerl-5.8.3 running under + Linux on a P4 2.8 GHz CPU. The last 5 entries differ by being pure perl + implementations of the algorithms, which explains why they are so slow. + +SEE ALSO + Digest::Adler32, Digest::CRC, Digest::Haval256, Digest::HMAC, + Digest::MD2, Digest::MD4, Digest::MD5, Digest::SHA, Digest::SHA1, + Digest::SHA2, Digest::Whirlpool + + New digest implementations should consider subclassing from + Digest::base. + + MIME::Base64 + + http://en.wikipedia.org/wiki/Cryptographic_hash_function + +AUTHOR + Gisle Aas + + The "Digest::" interface is based on the interface originally developed + by Neil Winton for his "MD5" module. + + This library is free software; you can redistribute it and/or modify it + under the same terms as Perl itself. + + Copyright 1998-2006 Gisle Aas. + Copyright 1995,1996 Neil Winton. -This library is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. From 2d9adf482fbc646bd90b983006d75dfdf7993416 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Wed, 7 Oct 2020 10:18:37 -0500 Subject: [PATCH 13/20] Use File::Temp for temporary test files --- Makefile.PL | 31 ++++++++++++++++--------------- cpanfile | 1 + t/base.t | 21 ++++++++++++--------- t/file.t | 32 ++++++++++++++++---------------- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 3b63f4d..08ca4ec 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -4,32 +4,33 @@ use warnings; use ExtUtils::MakeMaker; my %WriteMakefile_args = ( - 'NAME' => 'Digest', - 'AUTHOR' => 'Gisle Aas ', - 'VERSION_FROM' => 'lib/Digest.pm', - 'ABSTRACT_FROM' => 'lib/Digest.pm', - 'LICENSE' => 'perl', - 'MIN_PERL_VERSION' => '5.006', - 'PREREQ_PM' => { + 'NAME' => 'Digest', + 'AUTHOR' => 'Gisle Aas ', + 'VERSION_FROM' => 'lib/Digest.pm', + 'ABSTRACT_FROM' => 'lib/Digest.pm', + 'LICENSE' => 'perl', + 'MIN_PERL_VERSION' => '5.006', + 'PREREQ_PM' => { 'MIME::Base64' => 0, }, 'TEST_REQUIRES' => { 'Test::More' => '0.47', + 'File::Temp' => '0', }, 'INSTALLDIRS' => ( ( $] >= '5.009005' && $] < '5.012' ) ? 'perl' : 'site' ), 'dist' => { 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, 'clean' => { 'FILES' => 'Digest-*' }, 'META_MERGE' => { - 'meta-spec' => { 'version' => 2 }, + 'meta-spec' => { 'version' => 2 }, 'dynamic_config' => 0, - 'resources' => { - 'license' => [ 'http://dev.perl.org/licenses/' ], + 'resources' => { + 'license' => ['http://dev.perl.org/licenses/'], 'bugtracker' => { 'web' => 'https://github.com/Dual-Life/digest/issues' }, 'repository' => { 'type' => 'git', - 'url' => 'https://github.com/Dual-Life/digest.git', - 'web' => 'https://github.com/Dual-Life/digest', + 'url' => 'https://github.com/Dual-Life/digest.git', + 'web' => 'https://github.com/Dual-Life/digest', }, } }, @@ -41,9 +42,9 @@ delete $WriteMakefile_args{META_MERGE} unless eval { ExtUtils::MakeMaker->VERSION('6.46') }; delete $WriteMakefile_args{MIN_PERL_VERSION} unless eval { ExtUtils::MakeMaker->VERSION('6.48') }; -unless (eval { ExtUtils::MakeMaker->VERSION('6.64') }) { - my $test_requires = delete $WriteMakefile_args{TEST_REQUIRES}; - $WriteMakefile_args{PREREQ_PM}{$_} = $test_requires->{$_} for keys %$test_requires; +unless ( eval { ExtUtils::MakeMaker->VERSION('6.64') } ) { + my $test_requires = delete $WriteMakefile_args{TEST_REQUIRES}; + $WriteMakefile_args{PREREQ_PM}{$_} = $test_requires->{$_} for keys %$test_requires; } WriteMakefile(%WriteMakefile_args); diff --git a/cpanfile b/cpanfile index 25ee0ee..30651e1 100644 --- a/cpanfile +++ b/cpanfile @@ -6,5 +6,6 @@ requires "Digest::MD5" => "0"; on 'test' => sub { requires 'Test::More' => '0'; + requires 'File::Temp' => '0'; }; diff --git a/t/base.t b/t/base.t index 8bd9bdc..dca4d5a 100644 --- a/t/base.t +++ b/t/base.t @@ -5,6 +5,8 @@ use warnings; use Test::More tests => 13; +use File::Temp 'tempfile'; + { package LenDigest; @@ -57,17 +59,18 @@ is( $ctx->hexdigest, $EBCDIC ? "86f0f0f0f3" : "6630303033" ); $ctx->add("foo"); is( $ctx->b64digest, $EBCDIC ? "hvDw8PM" : "ZjAwMDM" ); -open( my $fh, ">xxtest$$" ) || die; -binmode($fh); -print $fh "abc" x 100, "\n"; -close($fh) || die; +{ + my ( $fh, $tempfile ) = tempfile(); + binmode($fh); + print $fh "abc" x 100, "\n"; + close($fh) || die; -open( my $fh2, "xxtest$$" ) || die; -$ctx->addfile($fh2); -close($fh2); -unlink("xxtest$$") || warn; + open( my $fh2, $tempfile ) || die; + $ctx->addfile($fh2); + close($fh2); -is( $ctx->digest, "a0301" ); + is( $ctx->digest, "a0301" ); +} eval { $ctx->add_bits("1010"); }; like( $@, '/^Number of bits must be multiple of 8/' ); diff --git a/t/file.t b/t/file.t index f554898..20f1ec5 100644 --- a/t/file.t +++ b/t/file.t @@ -5,6 +5,8 @@ use warnings; use Test::More tests => 5; +use File::Temp 'tempfile'; + { package Digest::Foo; @@ -32,25 +34,23 @@ use Test::More tests => 5; use Digest::file qw(digest_file digest_file_hex digest_file_base64); -my $file = "test-$$"; -die if -f $file; -open( my $fh, ">$file" ) || die "Can't create '$file': $!"; -binmode($fh); -print $fh "foo\0\n"; -close($fh) || die "Can't write '$file': $!"; +{ + my ( $fh, $file ) = tempfile(); + binmode($fh); + print $fh "foo\0\n"; + close($fh) || die "Can't write '$file': $!"; -is( digest_file( $file, "Foo" ), "0005" ); + is( digest_file( $file, "Foo" ), "0005" ); -if ( ord('A') == 193 ) { # EBCDIC. - is( digest_file_hex( $file, "Foo" ), "f0f0f0f5" ); - is( digest_file_base64( $file, "Foo" ), "8PDw9Q" ); -} -else { - is( digest_file_hex( $file, "Foo" ), "30303035" ); - is( digest_file_base64( $file, "Foo" ), "MDAwNQ" ); + if ( ord('A') == 193 ) { # EBCDIC. + is( digest_file_hex( $file, "Foo" ), "f0f0f0f5" ); + is( digest_file_base64( $file, "Foo" ), "8PDw9Q" ); + } + else { + is( digest_file_hex( $file, "Foo" ), "30303035" ); + is( digest_file_base64( $file, "Foo" ), "MDAwNQ" ); + } } ok !eval { digest_file( "not-there.txt", "Foo" ) }; ok $@; - -END { unlink "$file"; } From cd0af7fd82f00270729375b5a085bb86f36901e5 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 13 Oct 2020 14:08:01 -0500 Subject: [PATCH 14/20] Bump to 1.18 for release to CPAN --- Changes | 5 +++-- lib/Digest.pm | 2 +- lib/Digest/base.pm | 2 +- lib/Digest/file.pm | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index cce4010..0a1193e 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,5 @@ -1.18 XXX 2020-10-XX -- correct documentation for add_bits +1.18 Tue 2020-10-13 +- Correct documentation for add_bits - Explain $args,... in constructor prototypes - Add base64_padded_digest method - Add support for the SHA3 digests @@ -11,6 +11,7 @@ - Provide a consistent tidy to the code base - Get rid of the use of bareword file handles - Modernize the changelog +- Use File::Temp for temporary test files 1.17 Sun 2011-10-02 - Less noisy 'git status' output - Gisle Aas diff --git a/lib/Digest.pm b/lib/Digest.pm index 55bb548..d200f2e 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -3,7 +3,7 @@ package Digest; use strict; use warnings; -our $VERSION = "1.17"; +our $VERSION = "1.18"; our %MMAP = ( "SHA-1" => [ [ "Digest::SHA", 1 ], "Digest::SHA1", [ "Digest::SHA2", 1 ] ], diff --git a/lib/Digest/base.pm b/lib/Digest/base.pm index bd86e56..19b17ea 100644 --- a/lib/Digest/base.pm +++ b/lib/Digest/base.pm @@ -3,7 +3,7 @@ package Digest::base; use strict; use warnings; -our $VERSION = "1.16"; +our $VERSION = "1.18"; # subclass is supposed to implement at least these sub new; diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 29ef78c..9dbe45e 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -7,7 +7,7 @@ use Exporter (); use Carp qw(croak); use Digest (); -our $VERSION = "1.16"; +our $VERSION = "1.18"; our @ISA = qw(Exporter); our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); From ec5f16c50f4eff2fdd07c848445a8e07f6363367 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 27 Jun 2016 16:21:21 +1000 Subject: [PATCH 15/20] Remove . from @INC when loading optional modules. --- Changes | 3 +++ lib/Digest.pm | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 0a1193e..a71d4c6 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,6 @@ +1.19 Tue 2020-10-13 +- Merge blead change: Remove . from @INC when loading optional modules. + 1.18 Tue 2020-10-13 - Correct documentation for add_bits - Explain $args,... in constructor prototypes diff --git a/lib/Digest.pm b/lib/Digest.pm index d200f2e..bc6d40d 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -41,7 +41,11 @@ sub new { unless ( exists ${"$class\::"}{"VERSION"} ) { my $pm_file = $class . ".pm"; $pm_file =~ s{::}{/}g; - eval { require $pm_file }; + eval { + local @INC = @INC; + pop @INC if $INC[-1] eq '.'; + require $pm_file + }; if ($@) { $err ||= $@; next; From 44aff5a3baa06a7c39f8d52f1af6ec2316c72eb8 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 13 Oct 2020 14:59:19 -0500 Subject: [PATCH 16/20] Bump to 1.19 for release to CPAN --- lib/Digest.pm | 2 +- lib/Digest/base.pm | 2 +- lib/Digest/file.pm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Digest.pm b/lib/Digest.pm index bc6d40d..97f55d0 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -3,7 +3,7 @@ package Digest; use strict; use warnings; -our $VERSION = "1.18"; +our $VERSION = "1.19"; our %MMAP = ( "SHA-1" => [ [ "Digest::SHA", 1 ], "Digest::SHA1", [ "Digest::SHA2", 1 ] ], diff --git a/lib/Digest/base.pm b/lib/Digest/base.pm index 19b17ea..0f3afcb 100644 --- a/lib/Digest/base.pm +++ b/lib/Digest/base.pm @@ -3,7 +3,7 @@ package Digest::base; use strict; use warnings; -our $VERSION = "1.18"; +our $VERSION = "1.19"; # subclass is supposed to implement at least these sub new; diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 9dbe45e..7d46938 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -7,7 +7,7 @@ use Exporter (); use Carp qw(croak); use Digest (); -our $VERSION = "1.18"; +our $VERSION = "1.19"; our @ISA = qw(Exporter); our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); From f8f3772485b25804000c623d498dac7678f1c03f Mon Sep 17 00:00:00 2001 From: James E Keenan Date: Tue, 24 Aug 2021 02:12:49 +0000 Subject: [PATCH 17/20] Unlink temporary files created during testing --- t/base.t | 2 +- t/file.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/t/base.t b/t/base.t index dca4d5a..153d4d4 100644 --- a/t/base.t +++ b/t/base.t @@ -60,7 +60,7 @@ $ctx->add("foo"); is( $ctx->b64digest, $EBCDIC ? "hvDw8PM" : "ZjAwMDM" ); { - my ( $fh, $tempfile ) = tempfile(); + my ( $fh, $tempfile ) = tempfile( UNLINK => 1 ); binmode($fh); print $fh "abc" x 100, "\n"; close($fh) || die; diff --git a/t/file.t b/t/file.t index 20f1ec5..48ef39d 100644 --- a/t/file.t +++ b/t/file.t @@ -35,7 +35,7 @@ use File::Temp 'tempfile'; use Digest::file qw(digest_file digest_file_hex digest_file_base64); { - my ( $fh, $file ) = tempfile(); + my ( $fh, $file ) = tempfile( UNLINK => 1 ); binmode($fh); print $fh "foo\0\n"; close($fh) || die "Can't write '$file': $!"; From c2be766484aa762b013bebc21900721f685e9b05 Mon Sep 17 00:00:00 2001 From: Todd Rinaldo Date: Tue, 24 Aug 2021 13:48:38 +0000 Subject: [PATCH 18/20] Update changelog and version to 1.20 for release to CPAN. Ignore common temp files in repo. --- .gitignore | 4 +++- Changes | 3 +++ lib/Digest.pm | 2 +- lib/Digest/base.pm | 2 +- lib/Digest/file.pm | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 132fccc..d5df0b2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ /MYMETA.* /META.* /MANIFEST.bak -/Digest-[0-9]* \ No newline at end of file +/Digest-[0-9]* +*.ERR +*.bak diff --git a/Changes b/Changes index a71d4c6..41a8b3c 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,6 @@ +1.20 Tue 2021-08-24 +- Remove temp files during unit tests. + 1.19 Tue 2020-10-13 - Merge blead change: Remove . from @INC when loading optional modules. diff --git a/lib/Digest.pm b/lib/Digest.pm index 97f55d0..b62ef64 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -3,7 +3,7 @@ package Digest; use strict; use warnings; -our $VERSION = "1.19"; +our $VERSION = "1.20"; our %MMAP = ( "SHA-1" => [ [ "Digest::SHA", 1 ], "Digest::SHA1", [ "Digest::SHA2", 1 ] ], diff --git a/lib/Digest/base.pm b/lib/Digest/base.pm index 0f3afcb..539559b 100644 --- a/lib/Digest/base.pm +++ b/lib/Digest/base.pm @@ -3,7 +3,7 @@ package Digest::base; use strict; use warnings; -our $VERSION = "1.19"; +our $VERSION = "1.20"; # subclass is supposed to implement at least these sub new; diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 7d46938..088fabf 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -7,7 +7,7 @@ use Exporter (); use Carp qw(croak); use Digest (); -our $VERSION = "1.19"; +our $VERSION = "1.20"; our @ISA = qw(Exporter); our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); From c884f1553dd6f27cd29742032e2ef48b68ae0ee9 Mon Sep 17 00:00:00 2001 From: Toddr Bot Date: Wed, 15 Apr 2026 08:52:29 +0000 Subject: [PATCH 19/20] fix: add DESTROY guard, modernize Digest::file, document digest_file_ctx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add empty DESTROY to Digest.pm to prevent AUTOLOAD from catching implicit DESTROY calls during garbage collection. Replace @ISA with use parent in Digest::file — the last module still using the legacy pattern. Document digest_file_ctx() in POD — it was exported but undocumented. Add tests for both changes. Co-Authored-By: Claude Opus 4.6 --- lib/Digest.pm | 2 ++ lib/Digest/file.pm | 18 +++++++++++++++--- t/digest.t | 5 ++++- t/file.t | 20 ++++++++++++++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/Digest.pm b/lib/Digest.pm index b62ef64..087274a 100644 --- a/lib/Digest.pm +++ b/lib/Digest.pm @@ -64,6 +64,8 @@ sub AUTOLOAD { $class->new( $algorithm, @_ ); } +sub DESTROY { } # prevent AUTOLOAD from catching implicit DESTROY calls + 1; __END__ diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index 088fabf..dd44c32 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -3,12 +3,11 @@ package Digest::file; use strict; use warnings; -use Exporter (); +use parent 'Exporter'; use Carp qw(croak); use Digest (); our $VERSION = "1.20"; -our @ISA = qw(Exporter); our @EXPORT_OK = qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); sub digest_file_ctx { @@ -52,11 +51,24 @@ Digest::file - Calculate digests of files =head1 DESCRIPTION -This module provide 3 convenience functions to calculate the digest +This module provide 4 convenience functions to calculate the digest of files. The following functions are provided: =over +=item digest_file_ctx( $file, $algorithm, [$arg,...] ) + +This function will open the given file in binary mode, feed its +contents to a new digest object, and return the L context +object. This is useful when you need to call a specific digest +method yourself rather than using one of the shorthand functions +below. The function will croak if no algorithm is specified or if +it fails to open or read the file. + +The $algorithm is a string like "MD2", "MD5", "SHA-1", "SHA-512". +Additional arguments are passed to the constructor for the +implementation of the given algorithm. + =item digest_file( $file, $algorithm, [$arg,...] ) This function will calculate and return the binary digest of the bytes diff --git a/t/digest.t b/t/digest.t index 941f21d..0f5dfe4 100644 --- a/t/digest.t +++ b/t/digest.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 4; +use Test::More tests => 5; # To find Digest::Dummy use lib 't/lib'; @@ -22,3 +22,6 @@ is $d->digest, "ooo"; $Digest::MMAP{"Dummy-24"} = [ ["NotThere"], "NotThereEither", [ "Digest::Dummy", 24 ] ]; $d = Digest->new("Dummy-24"); is $d->digest, "24"; + +# DESTROY should not trigger AUTOLOAD +ok( Digest->can("DESTROY"), "Digest has explicit DESTROY method" ); diff --git a/t/file.t b/t/file.t index 48ef39d..b83a563 100644 --- a/t/file.t +++ b/t/file.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 5; +use Test::More tests => 9; use File::Temp 'tempfile'; @@ -32,7 +32,7 @@ use File::Temp 'tempfile'; } } -use Digest::file qw(digest_file digest_file_hex digest_file_base64); +use Digest::file qw(digest_file_ctx digest_file digest_file_hex digest_file_base64); { my ( $fh, $file ) = tempfile( UNLINK => 1 ); @@ -52,5 +52,21 @@ use Digest::file qw(digest_file digest_file_hex digest_file_base64); } } +# digest_file_ctx returns a usable Digest context object +{ + my ( $fh2, $file2 ) = tempfile( UNLINK => 1 ); + binmode($fh2); + print $fh2 "test data"; + close($fh2) || die "Can't write '$file2': $!"; + + my $ctx = digest_file_ctx( $file2, "Foo" ); + isa_ok( $ctx, "Digest::Foo", "digest_file_ctx returns correct class" ); + is( $ctx->digest, "0009", "digest_file_ctx feeds file content to context" ); +} + +# Error handling +ok !eval { digest_file_ctx( "not-there.txt", "Foo" ) }; +like $@, qr/Can't open/, "digest_file_ctx croaks on missing file"; + ok !eval { digest_file( "not-there.txt", "Foo" ) }; ok $@; From 53571cb5a68b125573e43ac135a0e8f3ecc3be4b Mon Sep 17 00:00:00 2001 From: Toddr Bot Date: Wed, 15 Apr 2026 08:53:50 +0000 Subject: [PATCH 20/20] fix: use base instead of parent for Perl 5.006 compat parent.pm was added in 5.10.1 but MIN_PERL_VERSION is 5.006. base.pm is available since 5.004005 and consistent with Digest::base's own POD example. Co-Authored-By: Claude Opus 4.6 --- lib/Digest/file.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Digest/file.pm b/lib/Digest/file.pm index dd44c32..1bcfff0 100644 --- a/lib/Digest/file.pm +++ b/lib/Digest/file.pm @@ -3,7 +3,7 @@ package Digest::file; use strict; use warnings; -use parent 'Exporter'; +use base 'Exporter'; use Carp qw(croak); use Digest ();