forked from miyagawa/cpanminus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
verify_checksums
73 lines (58 loc) · 2.33 KB
/
verify_checksums
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
name 'verify_checksums';
description 'Verify CHECKSUMS before unpacking the archive';
author 'Tatsuhiko Miyagawa';
api_version 0.1;
hook verify_archive => sub {
my $args = shift;
# Just require and throw errors -- cpanminus will catch them and display it in the build.log
require Module::Signature;
require Digest::SHA;
# TODO move this logic to cpanminus and set 'source' parameter
my $base = $args->{uri};
$base =~ s!(authors/id/[A-Z]/[A-Z]{2}/([A-Z]+))/[^/]+\.(?:tar\.gz|tgz|zip)$!$1!
or return;
my $pause_id = $2; # TODO this can be in the context
my $chk_uri = "$base/CHECKSUMS";
$args->{app}->chat("Fetching $chk_uri ...\n");
my $chk_file = "$pause_id.CHECKSUMS";
$args->{app}->mirror($chk_uri, $chk_file);
if (-e $chk_file) {
$args->{app}->chat("Verifying the signature of CHECKSUMS itself...\n");
my $rv = eval {
my $v = Module::Signature::_verify($chk_file);
$v == Module::Signature::SIGNATURE_OK();
};
if ($rv) {
$args->{app}->chat("Verified OK!\n");
} else {
$args->{app}->diag("Verifying CHECKSUMS signature failed: $rv\n");
return $args->{fail}++;
}
$args->{app}->chat("Verifying the SHA1 for $args->{file}\n");
open my $fh, "<$chk_file" or die "$chk_file: $!";
my $data = join '', <$fh>;
$data =~ s/\015?\012/\n/g;
require Safe;
my $chksum = Safe->new->reval($data);
if (!ref $chksum or ref $chksum ne 'HASH') {
$args->{app}->diag("! Checksum file downloaded from $chk_file is broken.\n");
return $args->{fail}++;
}
if (my $sha = $chksum->{$args->{file}}{sha256}) {
open my $fh, "<$args->{file}" or die "$args->{file}: $!";
my $dg = Digest::SHA->new(256);
my($data);
while (read($fh, $data, 4096)) {
$dg->add($data);
}
my $hex = $dg->hexdigest;
if ($hex eq $sha) {
$args->{app}->chat("Checksum for $args->{file}: Verified!\n");
} else {
$args->{app}->diag("Checksum mismatch for $args->{file}\n");
}
} else {
$args->{app}->chat("Checksum for $args->{file} not found in CHECKSUMS.\n");
}
}
};