This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade Digest::SHA from version 5.88 to 5.91
authorSteve Hay <steve.m.hay@googlemail.com>
Wed, 28 May 2014 13:28:13 +0000 (14:28 +0100)
committerSteve Hay <steve.m.hay@googlemail.com>
Wed, 28 May 2014 15:58:05 +0000 (16:58 +0100)
16 files changed:
MANIFEST
Porting/Maintainers.pl
cpan/Digest-SHA/Makefile.PL
cpan/Digest-SHA/SHA.xs
cpan/Digest-SHA/lib/Digest/SHA.pm
cpan/Digest-SHA/shasum
cpan/Digest-SHA/src/sdf.c [new file with mode: 0644]
cpan/Digest-SHA/src/sha.c
cpan/Digest-SHA/src/sha.h
cpan/Digest-SHA/src/sha64bit.c
cpan/Digest-SHA/src/sha64bit.h
cpan/Digest-SHA/t/inheritance.t [new file with mode: 0644]
cpan/Digest-SHA/t/methods.t
cpan/Digest-SHA/t/woodbury.t
cpan/Digest-SHA/typemap
pod/perldelta.pod

index 2443c46..6f89e70 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -685,6 +685,7 @@ cpan/Digest-SHA/lib/Digest/SHA.pm   Digest::SHA extension
 cpan/Digest-SHA/Makefile.PL            Digest::SHA Makefile.PL
 cpan/Digest-SHA/shasum                 shasum script
 cpan/Digest-SHA/SHA.xs                 Digest::SHA extension
+cpan/Digest-SHA/src/sdf.c              Digest::SHA extension
 cpan/Digest-SHA/src/sha64bit.c         Digest::SHA extension
 cpan/Digest-SHA/src/sha64bit.h         Digest::SHA extension
 cpan/Digest-SHA/src/sha.c              Digest::SHA extension
@@ -697,6 +698,7 @@ cpan/Digest-SHA/t/fips198.t         See if Digest::SHA works
 cpan/Digest-SHA/t/gglong.t             See if Digest::SHA works
 cpan/Digest-SHA/t/gg.t                 See if Digest::SHA works
 cpan/Digest-SHA/t/hmacsha.t            See if Digest::SHA works
+cpan/Digest-SHA/t/inheritance.t                See if Digest::SHA works
 cpan/Digest-SHA/t/ireland.t            See if Digest::SHA works
 cpan/Digest-SHA/t/methods.t            See if Digest::SHA works
 cpan/Digest-SHA/t/nistbit.t            See if Digest::SHA works
index 4e2fd83..61dfd3b 100755 (executable)
@@ -359,7 +359,7 @@ use File::Glob qw(:case);
     },
 
     'Digest::SHA' => {
-        'DISTRIBUTION' => 'MSHELOR/Digest-SHA-5.88.tar.gz',
+        'DISTRIBUTION' => 'MSHELOR/Digest-SHA-5.91.tar.gz',
         'FILES'        => q[cpan/Digest-SHA],
         'EXCLUDED'     => [
             qw( t/pod.t
index 3d83865..8e882ca 100644 (file)
@@ -5,14 +5,51 @@ use ExtUtils::MakeMaker;
 use Getopt::Std;
 use Config qw(%Config);
 
+use vars qw($opt_t $opt_w $opt_x);
+
 my $PM = 'lib/Digest/SHA.pm';
+my $SHASUM = 'shasum';
+
+       # 'use warnings' if possible, but stay portable
 
-my %opts;
-getopts('tx', \%opts); # -t is no longer used, but allow it anyway
+my($use_warnings, @EDITs);
+my $warn_1 = 'BEGIN { $^W = 1 }';
+my $warn_0 = 'BEGIN { $^W = 0 }';
+{
+       eval "require warnings; import warnings";
+       $use_warnings = $@ ? 0 : 1;
+
+       local(@ARGV) = ($PM, $SHASUM);
+       while (<>) {
+               if (
+               (!$use_warnings && /^(use|no) warnings\b/) ||
+               ( $use_warnings && /^\Q$warn_1\E # use warnings\b/) ||
+               ( $use_warnings && /^\Q$warn_0\E # no warnings\b/)) {
+                       push @EDITs, $ARGV;
+                       close ARGV;
+               }
+       }
+}
+
+if (@EDITs) {
+       local($^I, @ARGV) = ('', @EDITs);
+       while (<>) {
+               if ($use_warnings) {
+                       s/^\Q$warn_1\E # (.*)$/$1/;
+                       s/^\Q$warn_0\E # (.*)$/$1/;
+               }
+               else {
+                       s/^(use warnings\b.*)$/$warn_1 # $1/;
+                       s/^(no warnings\b.*)$/$warn_0 # $1/;
+               }
+               print;
+       }
+}
+
+getopts('twx');        # -t is no longer used, but allow it anyway
 
 my @defines;
-push(@defines, '-DSHA_PerlIO') if $] >= 5.004;
-push(@defines, '-DNO_SHA_384_512')  if $opts{'x'};
+push(@defines, '-DNO_SHA_384_512')  if $opt_x;
 my $define = join(' ', @defines);
 
        # Workaround for DEC compiler bug, adapted from Digest::MD5
@@ -21,7 +58,7 @@ my @extra = ();
 if ($^O eq 'VMS') {
        if (defined($Config{ccname})) {
                if (grep(/VMS_VAX/, @INC) && ($Config{ccname} eq 'DEC')) {
-                       # VAX compiler optimizer even up to v6.4 gets stuck
+                       # VAX optimizer, even up to v6.4, gets stuck
                        push(@extra, OPTIMIZE => "/Optimize=(NODISJOINT)");
                }
        }
@@ -33,18 +70,20 @@ if ($Config{archname} =~ /^i[3456]86/ && $Config{ccname} eq 'gcc') {
        push(@extra, OPTIMIZE => '-O1 -fomit-frame-pointer');
 }
 
-my %att = (
+push(@extra, CCFLAGS => '-W -Wall ' . $Config{ccflags}) if $opt_w;
+
+my %attr = (
        'NAME'          => 'Digest::SHA',
        'VERSION_FROM'  => $PM,
        'LIBS'          => [''],
        'DEFINE'        => $define,
        'INC'           => '-I.',
-       'EXE_FILES'     => [ 'shasum' ],
+       'EXE_FILES'     => [ $SHASUM ],
        'INSTALLDIRS'   => ($] >= 5.010 and $] < 5.011) ? 'perl' : 'site',
        @extra,
 );
 
-my $MMversion = $ExtUtils::MakeMaker::VERSION || 0;
-$att{NO_META} = 1 unless $MMversion < 6.10_03;
+my $MMversion = $ExtUtils::MakeMaker::VERSION || '0.00_00';
+$attr{NO_META} = 1 if $MMversion ge '6.10_03';
 
-WriteMakefile(%att);
+WriteMakefile(%attr);
index c38fcc4..7200a62 100644 (file)
        #define SvPVbyte SvPV
 #endif
 
+#ifndef PerlIO
+       #define PerlIO                          FILE
+       #define PerlIO_read(f, buf, count)      fread(buf, 1, count, f)
+#endif
+
+#ifndef sv_derived_from
+       #include "src/sdf.c"
+#endif
+
+#ifndef Newx
+       #define Newx(ptr, num, type)    New(0, ptr, num, type)
+       #define Newxz(ptr, num, type)   Newz(0, ptr, num, type)
+#endif
+
 #include "src/sha.c"
 
 static int ix2alg[] =
        {1,1,1,224,224,224,256,256,256,384,384,384,512,512,512,
        512224,512224,512224,512256,512256,512256};
 
-MODULE = Digest::SHA           PACKAGE = Digest::SHA
-
-PROTOTYPES: ENABLE
-
 #ifndef INT2PTR
 #define INT2PTR(p, i) (p) (i)
 #endif
 
 #define MAX_WRITE_SIZE 16384
+#define IO_BUFFER_SIZE 4096
 
-int
-shaclose(s)
-       SHA *   s
-CODE:
-       RETVAL = shaclose(s);
-       sv_setiv(SvRV(ST(0)), 0);
-OUTPUT:
-       RETVAL
+static SHA *getSHA(SV *self)
+{
+       if (!sv_isobject(self) || !sv_derived_from(self, "Digest::SHA"))
+               return(NULL);
+       return INT2PTR(SHA *, SvIV(SvRV(self)));
+}
 
-SHA *
-shadup(s)
-       SHA *   s
+MODULE = Digest::SHA           PACKAGE = Digest::SHA
+
+PROTOTYPES: ENABLE
 
-SHA *
-shaopen(alg)
+int
+shainit(s, alg)
+       SHA *   s
        int     alg
 
 void
@@ -55,7 +65,48 @@ shawrite(bitstr, bitcnt, s)
        unsigned long   bitcnt
        SHA *   s
 
+SV *
+newSHA(class, alg)
+       char *  class
+       int     alg
+PREINIT:
+       SHA *state;
+CODE:
+       Newxz(state, 1, SHA);
+       if (!shainit(state, alg)) {
+               Safefree(state);
+               XSRETURN_UNDEF;
+       }
+       RETVAL = newSV(0);
+       sv_setref_pv(RETVAL, class, (void *) state);
+       SvREADONLY_on(SvRV(RETVAL));
+OUTPUT:
+       RETVAL
+
+SV *
+clone(self)
+       SV *    self
+PREINIT:
+       SHA *state;
+       SHA *clone;
+CODE:
+       if ((state = getSHA(self)) == NULL)
+               XSRETURN_UNDEF;
+       Newx(clone, 1, SHA);
+       RETVAL = newSV(0);
+       sv_setref_pv(RETVAL, sv_reftype(SvRV(self), 1), (void *) clone);
+       SvREADONLY_on(SvRV(RETVAL));
+       Copy(state, clone, 1, SHA);
+OUTPUT:
+       RETVAL
+
 void
+DESTROY(s)
+       SHA *   s
+CODE:
+       Safefree(s);
+       
+SV *
 sha1(...)
 ALIAS:
        Digest::SHA::sha1 = 0
@@ -83,35 +134,35 @@ PREINIT:
        int i;
        UCHR *data;
        STRLEN len;
-       SHA *state;
+       SHA sha;
        char *result;
-PPCODE:
-       if ((state = shaopen(ix2alg[ix])) == NULL)
+CODE:
+       if (!shainit(&sha, ix2alg[ix]))
                XSRETURN_UNDEF;
        for (i = 0; i < items; i++) {
                data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
-                       shawrite(data, MAX_WRITE_SIZE << 3, state);
+                       shawrite(data, MAX_WRITE_SIZE << 3, &sha);
                        data += MAX_WRITE_SIZE;
                        len  -= MAX_WRITE_SIZE;
                }
-               shawrite(data, len << 3, state);
+               shawrite(data, len << 3, &sha);
        }
-       shafinish(state);
+       shafinish(&sha);
        len = 0;
        if (ix % 3 == 0) {
-               result = (char *) digcpy(state);
-               len = state->digestlen;
+               result = (char *) shadigest(&sha);
+               len = sha.digestlen;
        }
        else if (ix % 3 == 1)
-               result = shahex(state);
+               result = shahex(&sha);
        else
-               result = shabase64(state);
-       ST(0) = sv_2mortal(newSVpv(result, len));
-       shaclose(state);
-       XSRETURN(1);
+               result = shabase64(&sha);
+       RETVAL = newSVpv(result, len);
+OUTPUT:
+       RETVAL
 
-void
+SV *
 hmac_sha1(...)
 ALIAS:
        Digest::SHA::hmac_sha1 = 0
@@ -137,39 +188,41 @@ ALIAS:
        Digest::SHA::hmac_sha512256_base64 = 20
 PREINIT:
        int i;
-       UCHR *key;
+       UCHR *key = (UCHR *) "";
        UCHR *data;
-       STRLEN len;
-       HMAC *state;
+       STRLEN len = 0;
+       HMAC hmac;
        char *result;
-PPCODE:
-       key = (UCHR *) (SvPVbyte(ST(items-1), len));
-       if ((state = hmacopen(ix2alg[ix], key, len)) == NULL)
+CODE:
+       if (items > 0) {
+               key = (UCHR *) (SvPVbyte(ST(items-1), len));
+       }
+       if (hmacinit(&hmac, ix2alg[ix], key, len) == NULL)
                XSRETURN_UNDEF;
        for (i = 0; i < items - 1; i++) {
                data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
-                       hmacwrite(data, MAX_WRITE_SIZE << 3, state);
+                       hmacwrite(data, MAX_WRITE_SIZE << 3, &hmac);
                        data += MAX_WRITE_SIZE;
                        len  -= MAX_WRITE_SIZE;
                }
-               hmacwrite(data, len << 3, state);
+               hmacwrite(data, len << 3, &hmac);
        }
-       hmacfinish(state);
+       hmacfinish(&hmac);
        len = 0;
        if (ix % 3 == 0) {
-               result = (char *) digcpy(state->osha);
-               len = state->osha->digestlen;
+               result = (char *) hmacdigest(&hmac);
+               len = hmac.digestlen;
        }
        else if (ix % 3 == 1)
-               result = hmachex(state);
+               result = hmachex(&hmac);
        else
-               result = hmacbase64(state);
-       ST(0) = sv_2mortal(newSVpv(result, len));
-       hmacclose(state);
-       XSRETURN(1);
+               result = hmacbase64(&hmac);
+       RETVAL = newSVpv(result, len);
+OUTPUT:
+       RETVAL
 
-void
+int
 hashsize(self)
        SV *    self
 ALIAS:
@@ -177,14 +230,12 @@ ALIAS:
        Digest::SHA::algorithm = 1
 PREINIT:
        SHA *state;
-       int result;
-PPCODE:
-       if (!sv_isa(self, "Digest::SHA"))
+CODE:
+       if ((state = getSHA(self)) == NULL)
                XSRETURN_UNDEF;
-       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
-       result = ix ? state->alg : state->digestlen << 3;
-       ST(0) = sv_2mortal(newSViv(result));
-       XSRETURN(1);
+       RETVAL = ix ? state->alg : state->digestlen << 3;
+OUTPUT:
+       RETVAL
 
 void
 add(self, ...)
@@ -195,9 +246,8 @@ PREINIT:
        STRLEN len;
        SHA *state;
 PPCODE:
-       if (!sv_isa(self, "Digest::SHA"))
+       if ((state = getSHA(self)) == NULL)
                XSRETURN_UNDEF;
-       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
        for (i = 1; i < items; i++) {
                data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
@@ -209,75 +259,75 @@ PPCODE:
        }
        XSRETURN(1);
 
-void
+SV *
 digest(self)
        SV *    self
 ALIAS:
        Digest::SHA::digest = 0
-       Digest::SHA::Hexdigest = 1
-       Digest::SHA::B64digest = 2
+       Digest::SHA::hexdigest = 1
+       Digest::SHA::b64digest = 2
 PREINIT:
        STRLEN len;
        SHA *state;
        char *result;
-PPCODE:
-       if (!sv_isa(self, "Digest::SHA"))
+CODE:
+       if ((state = getSHA(self)) == NULL)
                XSRETURN_UNDEF;
-       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
        shafinish(state);
        len = 0;
        if (ix == 0) {
-               result = (char *) digcpy(state);
+               result = (char *) shadigest(state);
                len = state->digestlen;
        }
        else if (ix == 1)
                result = shahex(state);
        else
                result = shabase64(state);
-       ST(0) = sv_2mortal(newSVpv(result, len));
+       RETVAL = newSVpv(result, len);
        sharewind(state);
-       XSRETURN(1);
+OUTPUT:
+       RETVAL
 
-void
+SV *
 _getstate(self)
        SV *    self
 PREINIT:
        SHA *state;
        UCHR buf[256];
        UCHR *ptr = buf;
-PPCODE:
-       if (!sv_isa(self, "Digest::SHA"))
+CODE:
+       if ((state = getSHA(self)) == NULL)
                XSRETURN_UNDEF;
-       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
-       memcpy(ptr, digcpy(state), state->alg <= SHA256 ? 32 : 64);
+       Copy(digcpy(state), ptr, state->alg <= SHA256 ? 32 : 64, UCHR);
        ptr += state->alg <= SHA256 ? 32 : 64;
-       memcpy(ptr, state->block, state->alg <= SHA256 ? 64 : 128);
+       Copy(state->block, ptr, state->alg <= SHA256 ? 64 : 128, UCHR);
        ptr += state->alg <= SHA256 ? 64 : 128;
        ptr = w32mem(ptr, state->blockcnt);
        ptr = w32mem(ptr, state->lenhh);
        ptr = w32mem(ptr, state->lenhl);
        ptr = w32mem(ptr, state->lenlh);
        ptr = w32mem(ptr, state->lenll);
-       ST(0) = sv_2mortal(newSVpv((char *) buf, ptr - buf));
-       XSRETURN(1);
+       RETVAL = newSVpv((char *) buf, ptr - buf);
+OUTPUT:
+       RETVAL
 
 void
-_putstate(self, ...)
+_putstate(self, packed_state)
        SV *    self
+       SV *    packed_state
 PREINIT:
        UINT bc;
        STRLEN len;
        SHA *state;
        UCHR *data;
 PPCODE:
-       if (!sv_isa(self, "Digest::SHA"))
+       if ((state = getSHA(self)) == NULL)
                XSRETURN_UNDEF;
-       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
-       data = (UCHR *) SvPV(ST(1), len);
+       data = (UCHR *) SvPV(packed_state, len);
        if (len != (state->alg <= SHA256 ? 116 : 212))
                XSRETURN_UNDEF;
        data = statecpy(state, data);
-       memcpy(state->block, data, state->blocksize >> 3);
+       Copy(data, state->block, state->blocksize >> 3, UCHR);
        data += (state->blocksize >> 3);
        bc = memw32(data), data += 4;
        if (bc >= (state->alg <= SHA256 ? 512 : 1024))
@@ -288,3 +338,63 @@ PPCODE:
        state->lenlh = memw32(data), data += 4;
        state->lenll = memw32(data);
        XSRETURN(1);
+
+void
+_addfilebin(self, f)
+       SV *            self
+       PerlIO *        f
+PREINIT:
+       SHA *state;
+       int n;
+       UCHR in[IO_BUFFER_SIZE];
+PPCODE:
+       if (!f || (state = getSHA(self)) == NULL)
+               XSRETURN_UNDEF;
+       while ((n = PerlIO_read(f, in, sizeof(in))) > 0)
+               shawrite(in, n << 3, state);
+       XSRETURN(1);
+
+void
+_addfileuniv(self, f)
+       SV *            self
+       PerlIO *        f
+PREINIT:
+       char c;
+       int n;
+       int cr = 0;
+       UCHR *src, *dst;
+       UCHR in[IO_BUFFER_SIZE+1];
+       SHA *state;
+PPCODE:
+       if (!f || (state = getSHA(self)) == NULL)
+               XSRETURN_UNDEF;
+       while ((n = PerlIO_read(f, in+1, IO_BUFFER_SIZE)) > 0) {
+               for (dst = in, src = in + 1; n; n--) {
+                       c = *src++;
+                       if (!cr) {
+                               if (c == '\015')
+                                       cr = 1;
+                               else
+                                       *dst++ = c;
+                       }
+                       else {
+                               if (c == '\015')
+                                       *dst++ = '\012';
+                               else if (c == '\012') {
+                                       *dst++ = '\012';
+                                       cr = 0;
+                               }
+                               else {
+                                       *dst++ = '\012';
+                                       *dst++ = c;
+                                       cr = 0;
+                               }
+                       }
+               }
+               shawrite(in, (dst - in) << 3, state);
+       }
+       if (cr) {
+               in[0] = '\012';
+               shawrite(in, 1 << 3, state);
+       }
+       XSRETURN(1);
index 57f0bd6..0b598c6 100644 (file)
@@ -3,11 +3,12 @@ package Digest::SHA;
 require 5.003000;
 
 use strict;
+use warnings;
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
 use Fcntl;
 use integer;
 
-$VERSION = '5.88';
+$VERSION = '5.91';
 
 require Exporter;
 require DynaLoader;
@@ -28,52 +29,30 @@ require DynaLoader;
        sha512224       sha512224_base64        sha512224_hex
        sha512256       sha512256_base64        sha512256_hex);
 
-# If possible, inherit from Digest::base
+# Inherit from Digest::base if possible
 
 eval {
        require Digest::base;
        push(@ISA, 'Digest::base');
 };
 
-*addfile   = \&Addfile;
-*hexdigest = \&Hexdigest;
-*b64digest = \&B64digest;
-
 # The following routines aren't time-critical, so they can be left in Perl
 
 sub new {
        my($class, $alg) = @_;
        $alg =~ s/\D+//g if defined $alg;
        if (ref($class)) {      # instance method
-               unless (defined($alg) && ($alg != $class->algorithm)) {
-                       sharewind($$class);
+               if (!defined($alg) || ($alg == $class->algorithm)) {
+                       sharewind($class);
                        return($class);
                }
-               if ($$class) { shaclose($$class); $$class = undef }
-               return unless $$class = shaopen($alg);
-               return($class);
+               return shainit($class, $alg) ? $class : undef;
        }
        $alg = 1 unless defined $alg;
-       my $state = shaopen($alg) || return;
-       my $self = \$state;
-       bless($self, $class);
-       return($self);
-}
-
-sub DESTROY {
-       my $self = shift;
-       if ($$self) { shaclose($$self); $$self = undef }
-}
-
-sub clone {
-       my $self = shift;
-       my $state = shadup($$self) || return;
-       my $copy = \$state;
-       bless($copy, ref($self));
-       return($copy);
+       return $class->newSHA($alg);
 }
 
-*reset = \&new;
+BEGIN { *reset = \&new }
 
 sub add_bits {
        my($self, $data, $nbits) = @_;
@@ -82,7 +61,7 @@ sub add_bits {
                $data = pack("B*", $data);
        }
        $nbits = length($data) * 8 if $nbits > length($data) * 8;
-       shawrite($data, $nbits, $$self);
+       shawrite($data, $nbits, $self);
        return($self);
 }
 
@@ -90,48 +69,53 @@ sub _bail {
        my $msg = shift;
 
        $msg .= ": $!";
-        require Carp;
-        Carp::croak($msg);
+       require Carp;
+       Carp::croak($msg);
 }
 
-sub _addfile {  # this is "addfile" from Digest::base 1.00
-    my ($self, $handle) = @_;
-
-    my $n;
-    my $buf = "";
+{
+       my $_can_T_filehandle;
 
-    while (($n = read($handle, $buf, 4096))) {
-        $self->add($buf);
-    }
-    _bail("Read failed") unless defined $n;
+       sub _istext {
+               local *FH = shift;
+               my $file = shift;
 
-    $self;
+               if (! defined $_can_T_filehandle) {
+                       local $^W = 0;
+                       my $istext = eval { -T FH };
+                       $_can_T_filehandle = $@ ? 0 : 1;
+                       return $_can_T_filehandle ? $istext : -T $file;
+               }
+               return $_can_T_filehandle ? -T FH : -T $file;
+       }
 }
 
-my $_can_T_filehandle;
+sub _addfile {
+       my ($self, $handle) = @_;
 
-sub _istext {
-       local *FH = shift;
-       my $file = shift;
+       my $n;
+       my $buf = "";
 
-       if (! defined $_can_T_filehandle) {
-               local $^W = 0;
-               eval { -T FH };
-               $_can_T_filehandle = $@ ? 0 : 1;
+       while (($n = read($handle, $buf, 4096))) {
+               $self->add($buf);
        }
-       return $_can_T_filehandle ? -T FH : -T $file;
+       _bail("Read failed") unless defined $n;
+
+       $self;
 }
 
-sub Addfile {
+sub addfile {
        my ($self, $file, $mode) = @_;
 
        return(_addfile($self, $file)) unless ref(\$file) eq 'SCALAR';
 
        $mode = defined($mode) ? $mode : "";
-       my ($binary, $portable, $BITS) = map { $_ eq $mode } ("b", "p", "0");
+       my ($binary, $UNIVERSAL, $BITS, $portable) =
+               map { $_ eq $mode } ("b", "U", "0", "p");
 
                ## Always interpret "-" to mean STDIN; otherwise use
                ## sysopen to handle full range of POSIX file names
+
        local *FH;
        $file eq '-' and open(FH, '< -')
                or sysopen(FH, $file, O_RDONLY)
@@ -148,18 +132,18 @@ sub Addfile {
                return($self);
        }
 
-       binmode(FH) if $binary || $portable;
-       unless ($portable && _istext(*FH, $file)) {
-               $self->_addfile(*FH);
-               close(FH);
-               return($self);
+       binmode(FH) if $binary || $portable || $UNIVERSAL;
+       if ($UNIVERSAL && _istext(*FH, $file)) {
+               $self->_addfileuniv(*FH);
        }
-
-       while (<FH>) {
-               s/\015?\015\012/\012/g;         # DOS/Windows
-               s/\015/\012/g;                  # early MacOS
-               $self->add($_);
+       elsif ($portable && _istext(*FH, $file)) {
+               while (<FH>) {
+                       s/\015?\015\012/\012/g;
+                       s/\015/\012/g;
+                       $self->add($_);
+               }
        }
+       else { $self->_addfilebin(*FH) }
        close(FH);
 
        $self;
@@ -192,8 +176,7 @@ sub getstate {
 }
 
 sub putstate {
-       my $class = shift;
-       my $state = shift;
+       my($class, $state) = @_;
 
        my %s = ();
        for (split(/\n/, $state)) {
@@ -218,27 +201,17 @@ sub putstate {
                $s{'blockcnt'} < ($s{'alg'} <= 256 ? 512 : 1024) or return;
        }
 
-       my $state_packed = (
+       my $packed_state = (
                pack("H*", $s{'H'}) .
                pack("H*", $s{'block'}) .
-               pack("N", $s{'blockcnt'}) .
-               pack("N", $s{'lenhh'}) .
-               pack("N", $s{'lenhl'}) .
-               pack("N", $s{'lenlh'}) .
-               pack("N", $s{'lenll'})
+               pack("N",  $s{'blockcnt'}) .
+               pack("N",  $s{'lenhh'}) .
+               pack("N",  $s{'lenhl'}) .
+               pack("N",  $s{'lenlh'}) .
+               pack("N",  $s{'lenll'})
        );
 
-       if (ref($class)) {      # instance method
-               if ($$class) { shaclose($$class); $$class = undef }
-               return unless $$class = shaopen($s{'alg'});
-               return $class->_putstate($state_packed);
-       }
-       else {
-               my $sha = shaopen($s{'alg'}) or return;
-               my $self = \$sha;
-               bless($self, $class);
-               return $self->_putstate($state_packed);
-       }
+       return $class->new($s{'alg'})->_putstate($packed_state);
 }
 
 sub dump {
@@ -555,10 +528,10 @@ common string representations of the algorithm (e.g. "sha256",
 "SHA-384").  If the argument is missing, SHA-1 will be used by
 default.
 
-Invoking I<new> as an instance method will not create a new object;
-instead, it will simply reset the object to the initial state
-associated with I<$alg>.  If the argument is missing, the object
-will continue using the same algorithm that was selected at creation.
+Invoking I<new> as an instance method will reset the object to the
+initial state associated with I<$alg>.  If the argument is missing,
+the object will continue using the same algorithm that was selected
+at creation.
 
 =item B<reset($alg)>
 
@@ -631,22 +604,31 @@ argument to one of the following values:
 
        "b"     read file in binary mode
 
-       "p"     use portable mode
+       "U"     use universal newlines
 
        "0"     use BITS mode
 
-The "p" mode ensures that the digest value of I<$filename> will be the
-same when computed on different operating systems.  It accomplishes
-this by internally translating all newlines in text files to UNIX format
-before calculating the digest.  Binary files are read in raw mode with
-no translation whatsoever.
+       "p"     use portable mode (to be deprecated)
+
+The "U" mode is modeled on Python's "Universal Newlines" concept, whereby
+DOS and Mac OS line terminators are converted internally to UNIX newlines
+before processing.  This ensures consistent digest values when working
+simultaneously across multiple file systems.  B<The "U" mode influences
+only text files>, namely those passing Perl's I<-T> test; binary files
+are processed with no translation whatsoever.
+
+The "p" mode differs from "U" only in that it treats "\r\r\n" as a single
+newline, a quirky feature designed to accommodate legacy applications that
+occasionally added an extra carriage return before DOS line terminators.
+The "p" mode will be phased out eventually in favor of the cleaner and
+more well-established Universal Newlines concept.
 
 The BITS mode ("0") interprets the contents of I<$filename> as a logical
 stream of bits, where each ASCII '0' or '1' character represents a 0 or
 1 bit, respectively.  All other characters are ignored.  This provides
-a convenient way to calculate the digest values of partial-byte data by
-using files, rather than having to write programs using the I<add_bits>
-method.
+a convenient way to calculate the digest values of partial-byte data
+by using files, rather than having to write separate programs employing
+the I<add_bits> method.
 
 =item B<getstate>
 
@@ -691,9 +673,6 @@ Like I<digest>, this method is a read-once operation.  Call
 I<$sha-E<gt>clone-E<gt>hexdigest> if it's necessary to preserve
 the original digest state.
 
-This method is inherited if L<Digest::base> is installed on your
-system.  Otherwise, a functionally equivalent substitute is used.
-
 =item B<b64digest>
 
 Returns the digest encoded as a Base64 string.
@@ -702,9 +681,6 @@ Like I<digest>, this method is a read-once operation.  Call
 I<$sha-E<gt>clone-E<gt>b64digest> if it's necessary to preserve
 the original digest state.
 
-This method is inherited if L<Digest::base> is installed on your
-system.  Otherwise, a functionally equivalent substitute is used.
-
 It's important to note that the resulting string does B<not> contain
 the padding characters typical of Base64 encodings.  This omission is
 deliberate, and is done to maintain compatibility with the family of
@@ -811,6 +787,7 @@ The author is particularly grateful to
        Robert Gilmour
        Brian Gladman
        Adam Kennedy
+       Mark Lawrence
        Andy Lester
        Alex Muntada
        Steve Peters
index 32b7173..af0ddc3 100644 (file)
@@ -1,16 +1,22 @@
-#!perl -w
+#!perl
 
        ## shasum: filter for computing SHA digests (ref. sha1sum/md5sum)
        ##
        ## Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
        ##
-       ## Version: 5.88
-       ## Mon Mar 17 08:46:10 MST 2014
+       ## Version: 5.91
+       ## Fri May 16 10:21:44 MST 2014
 
-       ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum.
-       ## Add an "-a" option for algorithm selection, a "-p"
-       ## option for portable digest computation, and a "-0"
-       ## option for reading bit strings.
+       ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum. Add
+       ## "-a" option for algorithm selection,
+       ## "-U" option for Universal Newlines support,
+       ## "-0" option for reading bit strings, and
+       ## "-p" option for portable digests (to be deprecated).
+
+use strict;
+use warnings;
+use Fcntl;
+use Getopt::Long;
 
 my $POD = <<'END_OF_POD';
 
@@ -28,12 +34,13 @@ shasum - Print or Check SHA Checksums
    -b, --binary      read in binary mode
    -c, --check       read SHA sums from the FILEs and check them
    -t, --text        read in text mode (default)
-   -p, --portable    read in portable mode
+   -U, --UNIVERSAL   read in Universal Newlines mode
                          produces same digest on Windows/Unix/Mac
    -0, --01          read in BITS mode
                          ASCII '0' interpreted as 0-bit,
                          ASCII '1' interpreted as 1-bit,
                          all other characters ignored
+   -p, --portable    read in portable mode (to be deprecated)
 
  The following two options are useful only when verifying checksums:
    -s, --status      don't output anything, status code shows success
@@ -50,8 +57,8 @@ shasum - Print or Check SHA Checksums
  The sums are computed as described in FIPS PUB 180-4.  When checking,
  the input should be a former output of this program.  The default
  mode is to print a line with checksum, a character indicating type
- (`*' for binary, ` ' for text, `?' for portable, `^' for BITS),
- and name for each FILE.
+ (`*' for binary, ` ' for text, `U' for UNIVERSAL, `^' for BITS, `?'
for portable), and name for each FILE.
 
  Report shasum bugs to mshelor@cpan.org
 
@@ -94,11 +101,7 @@ L<Digest::SHA::PurePerl>.
 
 END_OF_POD
 
-use strict;
-use Fcntl;
-use Getopt::Long;
-
-my $VERSION = "5.88";
+my $VERSION = "5.91";
 
 sub usage {
        my($err, $msg) = @_;
@@ -126,7 +129,7 @@ select((select(STDERR), $| = 1)[0]);
        ## Collect options from command line
 
 my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
-my ($portable, $BITS, $modules, $versions);
+my ($portable, $BITS, $reverse, $UNIVERSAL, $versions);
 
 eval { Getopt::Long::Configure ("bundling") };
 GetOptions(
@@ -136,7 +139,8 @@ GetOptions(
        'h|help' => \$help, 'v|version' => \$version,
        'p|portable' => \$portable,
        '0|01' => \$BITS,
-       'M|MODULES=s' => \$modules,
+       'R|REVERSE' => \$reverse,
+       'U|UNIVERSAL' => \$UNIVERSAL,
        'V|VERSIONS' => \$versions,
 ) or usage(1, "");
 
@@ -146,7 +150,8 @@ GetOptions(
 usage(0)
        if $help;
 usage(1, "shasum: Ambiguous file mode\n")
-       if scalar(grep {defined $_} ($binary, $portable, $text, $BITS)) > 1;
+       if scalar(grep {defined $_}
+               ($binary, $portable, $text, $BITS, $UNIVERSAL)) > 1;
 usage(1, "shasum: --warn option used only when verifying checksums\n")
        if $warn && !$check;
 usage(1, "shasum: --status option used only when verifying checksums\n")
@@ -156,12 +161,11 @@ usage(1, "shasum: --status option used only when verifying checksums\n")
        ## Try to use Digest::SHA.  If not installed, use the slower
        ## but functionally equivalent Digest::SHA::PurePerl instead.
 
-       ## If option -M "Mod::Num1 Mod::Num2 ..." is invoked, try
-       ## those modules instead, in the order indicated.
+       ## If option -R is invoked, reverse the module preference,
+       ## i.e. try Digest::SHA::PurePerl first, then Digest::SHA.
 
-my @MODS = defined $modules
-               ? split(" ", $modules)
-               : qw(Digest::SHA Digest::SHA::PurePerl);
+my @MODS = qw(Digest::SHA Digest::SHA::PurePerl);
+@MODS[0, 1] = @MODS[1, 0] if $reverse;
 
 my $module;
 for (@MODS) {
@@ -200,12 +204,13 @@ if ($versions) {
        ## Try to figure out if the OS is DOS-like.  If it is,
        ## default to binary mode when reading files, unless
        ## explicitly overridden by command line "--text" or
-       ## "--portable" options.
+       ## "--UNIVERSAL" or "--portable" options.
 
 my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
-if ($isDOSish) { $binary = 1 unless $text || $portable }
+if ($isDOSish) { $binary = 1 unless $text || $UNIVERSAL || $portable }
 
-my $modesym = $binary ? '*' : ($portable ? '?' : ($BITS ? '^' : ' '));
+my $modesym = $binary ? '*' : ($UNIVERSAL ? 'U' :
+               ($BITS ? '^' : ($portable ? '?' : ' ')));
 
 
        ## Read from STDIN (-) if no files listed on command line
@@ -218,7 +223,8 @@ my $modesym = $binary ? '*' : ($portable ? '?' : ($BITS ? '^' : ' '));
 sub sumfile {
        my $file = shift;
 
-       my $mode = $portable ? 'p' : ($binary ? 'b' : ($BITS ? '0' : ''));
+       my $mode = $binary ? 'b' : ($UNIVERSAL ? 'U' :
+                       ($BITS ? '0' : ($portable ? 'p' : '')));
        my $digest = eval { $module->new($alg)->addfile($file, $mode) };
        if ($@) { warn "shasum: $file: $!\n"; return }
        $digest->hexdigest;
@@ -261,7 +267,7 @@ sub verify {
                next if /^#/; s/\n$//; s/^[ \t]+//; $num_lines++;
                $bslash = s/^\\//;
                ($sum, $modesym, $fname) =
-                       /^([\da-fA-F]+)[ \t]([ *?^])([^\0]*)/;
+                       /^([\da-fA-F]+)[ \t]([ *?^U])([^\0]*)/;
                $alg = defined $sum ? $len2alg{length($sum)} : undef;
                $fname = unescape($fname) if defined $fname && $bslash;
                if (grep { ! defined $_ } ($alg, $sum, $modesym, $fname)) {
@@ -273,8 +279,8 @@ sub verify {
                }
                $fname =~ s/\r$// unless -e $fname;
                $rsp = "$fname: "; $num_files++;
-               ($binary, $portable, $text, $BITS) =
-                       map { $_ eq $modesym } ('*', '?', ' ', '^');
+               ($binary, $text, $UNIVERSAL, $BITS, $portable) =
+                       map { $_ eq $modesym } ('*', ' ', 'U', '^', 'p');
                unless ($digest = sumfile($fname)) {
                        $rsp .= "FAILED open or read\n";
                        $err = 1; $read_errs++;
diff --git a/cpan/Digest-SHA/src/sdf.c b/cpan/Digest-SHA/src/sdf.c
new file mode 100644 (file)
index 0000000..e74f8e0
--- /dev/null
@@ -0,0 +1,100 @@
+/* Extracted from perl-5.004/universal.c, contributed by Graham Barr */
+
+static SV *
+isa_lookup(stash, name, len, level)
+HV *stash;
+char *name;
+int len;
+int level;
+{
+    AV* av;
+    GV* gv;
+    GV** gvp;
+    HV* hv = Nullhv;
+
+    if (!stash)
+       return &sv_undef;
+
+    if(strEQ(HvNAME(stash), name))
+       return &sv_yes;
+
+    if (level > 100)
+       croak("Recursive inheritance detected");
+
+    gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, FALSE);
+
+    if (gvp && (gv = *gvp) != (GV*)&sv_undef && (hv = GvHV(gv))) {
+       SV* sv;
+       SV** svp = (SV**)hv_fetch(hv, name, len, FALSE);
+       if (svp && (sv = *svp) != (SV*)&sv_undef)
+           return sv;
+    }
+
+    gvp = (GV**)hv_fetch(stash,"ISA",3,FALSE);
+    
+    if (gvp && (gv = *gvp) != (GV*)&sv_undef && (av = GvAV(gv))) {
+       if(!hv) {
+           gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, TRUE);
+
+           gv = *gvp;
+
+           if (SvTYPE(gv) != SVt_PVGV)
+               gv_init(gv, stash, "::ISA::CACHE::", 14, TRUE);
+
+           hv = GvHVn(gv);
+       }
+       if(hv) {
+           SV** svp = AvARRAY(av);
+           I32 items = AvFILL(av) + 1;
+           while (items--) {
+               SV* sv = *svp++;
+               HV* basestash = gv_stashsv(sv, FALSE);
+               if (!basestash) {
+                   if (dowarn)
+                       warn("Can't locate package %s for @%s::ISA",
+                           SvPVX(sv), HvNAME(stash));
+                   continue;
+               }
+               if(&sv_yes == isa_lookup(basestash, name, len, level + 1)) {
+                   (void)hv_store(hv,name,len,&sv_yes,0);
+                   return &sv_yes;
+               }
+           }
+           (void)hv_store(hv,name,len,&sv_no,0);
+       }
+    }
+
+    return &sv_no;
+}
+
+static bool
+sv_derived_from(sv, name)
+SV * sv ;
+char * name ;
+{
+    SV *rv;
+    char *type;
+    HV *stash;
+  
+    stash = Nullhv;
+    type = Nullch;
+    if (SvGMAGICAL(sv))
+        mg_get(sv) ;
+
+    if (SvROK(sv)) {
+        sv = SvRV(sv);
+        type = sv_reftype(sv,0);
+        if(SvOBJECT(sv))
+            stash = SvSTASH(sv);
+    }
+    else {
+        stash = gv_stashsv(sv, FALSE);
+    }
+    return (type && strEQ(type,name)) ||
+            (stash && isa_lookup(stash, name, strlen(name), 0) == &sv_yes)
+        ? TRUE
+        : FALSE ;
+}
index 70ee233..ba236e6 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.88
- * Mon Mar 17 08:46:10 MST 2014
+ * Version: 5.91
+ * Fri May 16 10:21:44 MST 2014
  *
  */
 
@@ -273,59 +273,44 @@ static UCHR *statecpy(SHA *s, UCHR *buf)
                        *p32++ = memw32(buf);
        else
                for (i = 0; i < 8; i++, buf += 8)
-                       *p64++ = ((W64) memw32(buf) << 32) +
+                       *p64++ = (((W64)memw32(buf) << 16) << 16) +
                                        memw32(buf+4);
        return(buf);
 }
 
-#define SHA_INIT(algo, transform)                                      \
+#define SHA_INIT(s, algo, transform)                                   \
        do {                                                            \
-               memset(s, 0, sizeof(SHA));                              \
+               Zero(s, 1, SHA);                                        \
                s->alg = algo; s->sha = sha ## transform;               \
-               memcpy(s->H, H0 ## algo, sizeof(H0 ## algo));           \
+               Copy(H0 ## algo, s->H, sizeof(H0 ## algo), char);       \
                s->blocksize = SHA ## algo ## _BLOCK_BITS;              \
                s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3;        \
        } while (0)
 
-/* sharewind: re-initializes the digest object */
+/* sharewind: resets digest object */
 static void sharewind(SHA *s)
 {
-       if      (s->alg == SHA1)   SHA_INIT(1, 1);
-       else if (s->alg == SHA224) SHA_INIT(224, 256);
-       else if (s->alg == SHA256) SHA_INIT(256, 256);
-       else if (s->alg == SHA384) SHA_INIT(384, 512);
-       else if (s->alg == SHA512) SHA_INIT(512, 512);
-       else if (s->alg == SHA512224) SHA_INIT(512224, 512);
-       else if (s->alg == SHA512256) SHA_INIT(512256, 512);
+       if      (s->alg == SHA1)   SHA_INIT(s, 1, 1);
+       else if (s->alg == SHA224) SHA_INIT(s, 224, 256);
+       else if (s->alg == SHA256) SHA_INIT(s, 256, 256);
+       else if (s->alg == SHA384) SHA_INIT(s, 384, 512);
+       else if (s->alg == SHA512) SHA_INIT(s, 512, 512);
+       else if (s->alg == SHA512224) SHA_INIT(s, 512224, 512);
+       else if (s->alg == SHA512256) SHA_INIT(s, 512256, 512);
 }
 
-/* shaopen: creates a new digest object */
-static SHA *shaopen(int alg)
+/* shainit: initializes digest object */
+static int shainit(SHA *s, int alg)
 {
-       SHA *s = NULL;
-
+       if (alg >= SHA384 && !sha_384_512)
+               return 0;
        if (alg != SHA1 && alg != SHA224 && alg != SHA256 &&
                alg != SHA384    && alg != SHA512 &&
                alg != SHA512224 && alg != SHA512256)
-               return(NULL);
-       if (alg >= SHA384 && !sha_384_512)
-               return(NULL);
-       SHA_newz(0, s, 1, SHA);
-       if (s == NULL)
-               return(NULL);
+               return 0;
        s->alg = alg;
        sharewind(s);
-       return(s);
-}
-
-/* shaclose: de-allocates digest object */
-static int shaclose(SHA *s)
-{
-       if (s != NULL) {
-               memset(s, 0, sizeof(SHA));
-               SHA_free(s);
-       }
-       return(0);
+       return 1;
 }
 
 /* shadirect: updates state directly (w/o going through s->block) */
@@ -339,13 +324,13 @@ static ULNG shadirect(UCHR *bitstr, ULNG bitcnt, SHA *s)
                bitcnt -= s->blocksize;
        }
        if (bitcnt > 0) {
-               memcpy(s->block, bitstr, NBYTES(bitcnt));
+               Copy(bitstr, s->block, NBYTES(bitcnt), char);
                s->blockcnt = bitcnt;
        }
        return(savecnt);
 }
 
-/* shabytes: updates state for byte-aligned input data */
+/* shabytes: updates state for byte-aligned data in s->block */
 static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA *s)
 {
        UINT offset;
@@ -355,20 +340,20 @@ static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA *s)
        offset = s->blockcnt >> 3;
        if (s->blockcnt + bitcnt >= s->blocksize) {
                nbits = s->blocksize - s->blockcnt;
-               memcpy(s->block+offset, bitstr, nbits>>3);
+               Copy(bitstr, s->block+offset, nbits>>3, char);
                bitcnt -= nbits;
                bitstr += (nbits >> 3);
                s->sha(s, s->block), s->blockcnt = 0;
                shadirect(bitstr, bitcnt, s);
        }
        else {
-               memcpy(s->block+offset, bitstr, NBYTES(bitcnt));
+               Copy(bitstr, s->block+offset, NBYTES(bitcnt), char);
                s->blockcnt += bitcnt;
        }
        return(savecnt);
 }
 
-/* shabits: updates state for bit-aligned input data */
+/* shabits: updates state for bit-aligned data in s->block */
 static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA *s)
 {
        UINT i;
@@ -446,6 +431,8 @@ static void shafinish(SHA *s)
        s->sha(s, s->block);
 }
 
+#define shadigest(state)       digcpy(state)
+
 /* xmap: translation map for hexadecimal encoding */
 static char xmap[] =
        "0123456789abcdef";
@@ -481,7 +468,7 @@ static void encbase64(UCHR *in, int n, char *out)
        out[0] = '\0';
        if (n < 1 || n > 3)
                return;
-       memcpy(byte, in, n);
+       Copy(in, byte, n, UCHR);
        out[0] = bmap[byte[0] >> 2];
        out[1] = bmap[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
        out[2] = bmap[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
@@ -509,94 +496,61 @@ static char *shabase64(SHA *s)
        return(s->base64);
 }
 
-/* shadup: duplicates current digest object */
-static SHA *shadup(SHA *s)
-{
-       SHA *p;
-
-       SHA_new(0, p, 1, SHA);
-       if (p == NULL)
-               return(NULL);
-       memcpy(p, s, sizeof(SHA));
-       return(p);
-}
-
-/* hmacopen: creates a new HMAC-SHA digest object */
-static HMAC *hmacopen(int alg, UCHR *key, UINT keylen)
+/* hmacinit: initializes HMAC-SHA digest object */
+static HMAC *hmacinit(HMAC *h, int alg, UCHR *key, UINT keylen)
 {
        UINT i;
-       HMAC *h;
+       SHA ksha;
 
-       SHA_newz(0, h, 1, HMAC);
-       if (h == NULL)
+       Zero(h, 1, HMAC);
+       if (!shainit(&h->isha, alg))
                return(NULL);
-       if ((h->isha = shaopen(alg)) == NULL) {
-               SHA_free(h);
+       if (!shainit(&h->osha, alg))
                return(NULL);
-       }
-       if ((h->osha = shaopen(alg)) == NULL) {
-               shaclose(h->isha);
-               SHA_free(h);
-               return(NULL);
-       }
-       if (keylen <= h->osha->blocksize / 8)
-               memcpy(h->key, key, keylen);
+       if (keylen <= h->osha.blocksize / 8)
+               Copy(key, h->key, keylen, char);
        else {
-               if ((h->ksha = shaopen(alg)) == NULL) {
-                       shaclose(h->isha);
-                       shaclose(h->osha);
-                       SHA_free(h);
+               if (!shainit(&ksha, alg))
                        return(NULL);
-               }
-               shawrite(key, keylen * 8, h->ksha);
-               shafinish(h->ksha);
-               memcpy(h->key, digcpy(h->ksha), h->ksha->digestlen);
-               shaclose(h->ksha);
+               shawrite(key, keylen * 8, &ksha);
+               shafinish(&ksha);
+               Copy(digcpy(&ksha), h->key, ksha.digestlen, char);
        }
-       for (i = 0; i < h->osha->blocksize / 8; i++)
+       h->digestlen = h->osha.digestlen;
+       for (i = 0; i < h->osha.blocksize / 8; i++)
                h->key[i] ^= 0x5c;
-       shawrite(h->key, h->osha->blocksize, h->osha);
-       for (i = 0; i < h->isha->blocksize / 8; i++)
+       shawrite(h->key, h->osha.blocksize, &h->osha);
+       for (i = 0; i < h->isha.blocksize / 8; i++)
                h->key[i] ^= (0x5c ^ 0x36);
-       shawrite(h->key, h->isha->blocksize, h->isha);
-       memset(h->key, 0, sizeof(h->key));
+       shawrite(h->key, h->isha.blocksize, &h->isha);
+       Zero(h->key, sizeof(h->key), char);
        return(h);
 }
 
 /* hmacwrite: triggers a state update using data in bitstr/bitcnt */
 static ULNG hmacwrite(UCHR *bitstr, ULNG bitcnt, HMAC *h)
 {
-       return(shawrite(bitstr, bitcnt, h->isha));
+       return(shawrite(bitstr, bitcnt, &h->isha));
 }
 
 /* hmacfinish: computes final digest state */
 static void hmacfinish(HMAC *h)
 {
-       shafinish(h->isha);
-       shawrite(digcpy(h->isha), h->isha->digestlen * 8, h->osha);
-       shaclose(h->isha);
-       shafinish(h->osha);
+       shafinish(&h->isha);
+       shawrite(digcpy(&h->isha), h->isha.digestlen * 8, &h->osha);
+       shafinish(&h->osha);
 }
 
+#define hmacdigest(h)  digcpy(&(h)->osha)
+
 /* hmachex: returns pointer to digest (hexadecimal) */
 static char *hmachex(HMAC *h)
 {
-       return(shahex(h->osha));
+       return(shahex(&h->osha));
 }
 
 /* hmacbase64: returns pointer to digest (Base 64) */
 static char *hmacbase64(HMAC *h)
 {
-       return(shabase64(h->osha));
-}
-
-/* hmacclose: de-allocates digest object */
-static int hmacclose(HMAC *h)
-{
-       if (h != NULL) {
-               shaclose(h->osha);
-               memset(h, 0, sizeof(HMAC));
-               SHA_free(h);
-       }
-       return(0);
+       return(shabase64(&h->osha));
 }
index b9f1e70..0a2a909 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.88
- * Mon Mar 17 08:46:10 MST 2014
+ * Version: 5.91
+ * Fri May 16 10:21:44 MST 2014
  *
  */
 
 
 #if defined(BYTEORDER) && (BYTEORDER & 0xffff) == 0x4321
        #if defined(SHA32_ALIGNED)
-               #define SHA32_SCHED(W, b)       memcpy(W, b, 64)
+               #define SHA32_SCHED(W, b)       Copy(b, W, 64, char)
        #endif
        #if defined(SHA64) && defined(SHA64_ALIGNED)
-               #define SHA64_SCHED(W, b)       memcpy(W, b, 128)
+               #define SHA64_SCHED(W, b)       Copy(b, W, 128, char)
        #endif
 #endif
 
                        (SHA64) b[6] <<  8 | (SHA64) b[7]; }
 #endif
 
-#define SHA_new                New
-#define SHA_newz       Newz
-#define SHA_free       Safefree
-
 #define SHA1           1
 #define SHA224         224
 #define SHA256         256
@@ -156,9 +152,9 @@ typedef struct SHA {
 } SHA;
 
 typedef struct {
-       SHA *ksha;
-       SHA *isha;
-       SHA *osha;
+       SHA isha;
+       SHA osha;
+       int digestlen;
        unsigned char key[SHA_MAX_BLOCK_BITS/8];
 } HMAC;
 
index 71f9978..a6c3547 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.88
- * Mon Mar 17 08:46:10 MST 2014
+ * Version: 5.91
+ * Fri May 16 10:21:44 MST 2014
  *
  */
 
@@ -14,7 +14,6 @@
 
 #undef sha_384_512
 #undef W64
-#undef strto64
 #undef sha512
 #undef H0384
 #undef H0512
@@ -93,17 +92,6 @@ C64(0x963877195940eabd), C64(0x96283ee2a88effe3), C64(0xbe5e1e2553863992),
 C64(0x2b0199fc2c85b8aa), C64(0x0eb72ddc81c52ca2)
 };
 
-/* strto64: converts hex string to a 64-bit word */
-static W64 strto64(char *s)
-{
-       char str[2] = {0, 0};
-       W64 u = C64(0);
-
-       while (isxdigit(str[0] = *s++))
-               u = (u << 4) + strtoul(str, NULL, 16);
-       return(u);
-}
-
 static void sha512(SHA *s, unsigned char *block) /* SHA-384/512 transform */
 {
        W64 a, b, c, d, e, f, g, h, T1, T2;
index bdd7b1c..a0bec90 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.88
- * Mon Mar 17 08:46:10 MST 2014
+ * Version: 5.91
+ * Fri May 16 10:21:44 MST 2014
  *
  * The following macros supply placeholder values that enable the
  * sha.c module to successfully compile when 64-bit integer types
@@ -19,7 +19,6 @@
 
 #define sha_384_512            0
 #define W64                    unsigned long
-#define strto64(p)             0
 #define sha512                 NULL
 #define H0384                  H01
 #define H0512                  H01
diff --git a/cpan/Digest-SHA/t/inheritance.t b/cpan/Digest-SHA/t/inheritance.t
new file mode 100644 (file)
index 0000000..d94c23a
--- /dev/null
@@ -0,0 +1,31 @@
+# Adapted from script by Mark Lawrence (ref. rt.cpan.org #94830)
+
+use strict;
+
+my $MODULE;
+
+BEGIN {
+       $MODULE = (-d "src") ? "Digest::SHA" : "Digest::SHA::PurePerl";
+       eval "require $MODULE" || die $@;
+       $MODULE->import(qw(sha1));
+}
+
+BEGIN {
+       if ($ENV{PERL_CORE}) {
+               chdir 't' if -d 't';
+               @INC = '../lib';
+       }
+}
+
+package P1;
+use vars qw(@ISA);
+@ISA = ($MODULE);
+
+package main;
+
+print "1..1\n";
+
+my $data = 'a';
+my $d = P1->new;
+print "not " unless $d->add($data)->digest eq sha1($data);
+print "ok 1\n";
index f7cecd2..7bbc706 100644 (file)
@@ -21,7 +21,7 @@ my @out = (
        "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
 );
 
-my $numtests = 8 + scalar @out;
+my $numtests = 9 + scalar @out;
 print "1..$numtests\n";
 
        # attempt to use an invalid algorithm, and check for failure
@@ -101,6 +101,17 @@ print "not " unless $sha->new(1)->addfile($tempfile, "p")->hexdigest eq
        "d449e19c1b0b0c191294c8dc9fa2e4a6ff77fc51";
 print "ok ", $testnum++, "\n";
 
+       # test addfile "universal newlines" mode
+
+$fh = FileHandle->new($tempfile, "w");
+binmode($fh);
+print $fh "MacOS\r" . "MSDOS\r\n" . "UNIX\n" . "Quirky\r\r\n";
+$fh->close;
+
+print "not " unless $sha->new(1)->addfile($tempfile, "U")->hexdigest eq
+       "f4c6855783c737c7e224873c90e80a9df5c2bc97";     # per Python 3
+print "ok ", $testnum++, "\n";
+
        # test addfile BITS mode
 
 $fh = FileHandle->new($tempfile, "w");
index 35f4e6a..afcb731 100644 (file)
@@ -9,7 +9,7 @@ my $MODULE;
 BEGIN {
        $MODULE = (-d "src") ? "Digest::SHA" : "Digest::SHA::PurePerl";
        eval "require $MODULE" || die $@;
-       $MODULE->import(qw(hmac_sha256_hex hmac_sha384_hex hmac_sha512_hex));
+       $MODULE->import(qw(hmac_sha256 hmac_sha384 hmac_sha512));
 }
 
 BEGIN {
@@ -44,12 +44,12 @@ my $testnum = 1;
 
 while (@data_bs512) {
        print "not " unless
-               hmac_sha256_hex(shift @data_bs512, shift @keys_bs512)
-                       eq shift @hmac256rsp;
+               hmac_sha256(shift @data_bs512, shift @keys_bs512)
+                       eq pack("H*", shift @hmac256rsp);
        print "ok ", $testnum++, "\n";
 }
 
-my $skip = hmac_sha384_hex("", "") ? 0 : 1;
+my $skip = hmac_sha384("", "") ? 0 : 1;
 
 while (@data_bs1024) {
        if ($skip) {
@@ -59,8 +59,8 @@ while (@data_bs1024) {
                next;
        }
        print "not " unless
-               hmac_sha384_hex(shift @data_bs1024, shift @keys_bs1024)
-                       eq shift @hmac384rsp;
+               hmac_sha384(shift @data_bs1024, shift @keys_bs1024)
+                       eq pack("H*", shift @hmac384rsp);
        print "ok ", $testnum++, "\n";
 }
 
@@ -72,8 +72,8 @@ while (@dat2_bs1024) {
                next;
        }
        print "not " unless
-               hmac_sha512_hex(shift @dat2_bs1024, shift @key2_bs1024)
-                       eq shift @hmac512rsp;
+               hmac_sha512(shift @dat2_bs1024, shift @key2_bs1024)
+                       eq pack("H*", shift @hmac512rsp);
        print "ok ", $testnum++, "\n";
 }
 
index 70c4dc1..b881a1d 100644 (file)
@@ -1,2 +1,7 @@
-SHA *                                          T_PTROBJ
-HMAC *                                         T_PTROBJ
+TYPEMAP
+SHA *          T_SHA
+PerlIO *       T_IN
+
+INPUT
+T_SHA
+       $var = getSHA($arg)
index 527de13..5e10412 100644 (file)
@@ -128,6 +128,13 @@ L<[perl #121574]|https://rt.perl.org/Ticket/Display.html?id=121574>
 
 =item *
 
+L<Digest::SHA> has been upgraded from version 5.88 to 5.91.
+
+Numerous enhancements, bug fixes and performance improvements have been made.
+See the F<Changes> file in the CPAN distribution for full details.
+
+=item *
+
 L<Math::BigRat> has been upgraded from version 0.2606 to 0.2607.
 
 Synchronize POD changes from the CPAN release.