Skip to content
This repository
tree: ee6cd30d70
Fetching contributors…

Cannot retrieve contributors at this time

file 73 lines (58 sloc) 2.388 kb
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");
        }

    }
};
Something went wrong with that request. Please try again.