Skip to content

Commit 69dcea6

Browse files
committed
Add methods to calculate the apk checksum and apk data checksum
1 parent a9fe939 commit 69dcea6

File tree

1 file changed

+72
-2
lines changed

1 file changed

+72
-2
lines changed

Build/Apk.pm

+72-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ package Build::Apk;
2323
use strict;
2424

2525
use Digest::MD5;
26-
eval { require Archive::Tar; };
26+
use Digest::SHA;
27+
28+
eval { require Archive::Tar };
2729
*Archive::Tar::new = sub {die("Archive::Tar is not available\n")} unless defined &Archive::Tar::new;
30+
eval { require Compress::Raw::Zlib };
31+
*Compress::Raw::Zlib::Inflate = sub {die("MIME::Base64 is not available\n")} unless defined &Compress::Raw::Zlib::Inflate;
32+
33+
eval { require MIME::Base64 };
34+
*MIME::Base64::encode_base64 = sub {die("MIME::Base64 is not available\n")} unless defined &MIME::Base64::encode_base64;
35+
2836

2937
sub expandvars_cplx {
3038
my ($v, $vars) = @_;
@@ -323,6 +331,7 @@ my %pkginfomap = (
323331
# 'replaces' => [ 'obsoletes' ],
324332
'provides' => [ 'provides' ],
325333
'install_if' => [ 'supplements' ],
334+
'datahash' => 'apkdatachksum',
326335
);
327336
328337
sub query {
@@ -365,6 +374,7 @@ sub query {
365374
$q{'source'} ||= $q{'name'} if defined $q{'name'};
366375
delete $q{'supplements'} unless $opts{'weakdeps'};
367376
delete $q{'buildtime'} unless $opts{'buildtime'};
377+
delete $q{'apkdatachksum'} unless $opts{'apkdatachksum'};
368378
return \%q;
369379
}
370380
@@ -376,7 +386,7 @@ my %idxinfomap = (
376386
't' => 'buildtime',
377387
'A' => 'arch',
378388
'L' => 'license',
379-
'C' => 'apk_chksum',
389+
'C' => 'apkchksum',
380390
'o' => 'source',
381391
'D' => [ 'requires' ],
382392
# 'r' => [ 'obsoletes' ],
@@ -449,6 +459,66 @@ sub queryhdrmd5 {
449459
return Digest::MD5::md5_hex($pkginfo);
450460
}
451461
462+
# this calculates the checksum of the second compressed section.
463+
sub calcapkchksum {
464+
my ($handle, $type) = @_;
465+
$type ||= 'Q1';
466+
die("unsupported apkchksum type $type\n") unless $type eq 'Q1' || $type eq 'sha1' || $type eq 'sha256' || $type eq 'sha512' || $type eq 'md5';
467+
my $fd;
468+
open($fd, '<', $handle) or die("$handle: $!\n");
469+
my $z = new Compress::Raw::Zlib::Inflate(-WindowBits => 15 + Compress::Raw::Zlib::WANT_GZIP_OR_ZLIB(), LimitOutput => 1);
470+
my $ctx;
471+
$ctx = Digest::SHA->new(1) if $type eq 'Q1' || $type eq 'sha1';
472+
$ctx = Digest::SHA->new(256) if $type eq 'sha256';
473+
$ctx = Digest::SHA->new(512) if $type eq 'sha512';
474+
$ctx = Digest::MD5->new() if $type eq 'md5';
475+
die("unsupported apkchksum type $type\n") unless $ctx;
476+
my $section = 0;
477+
my $input = '';
478+
my @offs;
479+
my $off = 0;
480+
while (1) {
481+
if (!length($input)) {
482+
read($fd, $input, 4096);
483+
die("unexpected EOF\n") unless length($input);
484+
$off += length($input);
485+
}
486+
my $oldinput = $input;
487+
my $output;
488+
my $status = $z->inflate($input, $output);
489+
$ctx->add(substr($oldinput, 0, length($oldinput) - length($input))) if $section == 1;
490+
next if $status == Compress::Raw::Zlib::Z_BUF_ERROR() && length($input);
491+
if ($status == Compress::Raw::Zlib::Z_STREAM_END()) {
492+
push @offs, $off - length($input);
493+
$section++;
494+
last if $section == 2;
495+
$z->inflateReset();
496+
} elsif ($status != Compress::Raw::Zlib::Z_OK()) {
497+
die("decompression error\n");
498+
}
499+
}
500+
my $chk = $ctx->digest();
501+
return 'Q1'.MIME::Base64::encode_base64($chk, ''), @offs if $type eq 'Q1';
502+
return "$type:".unpack('H*');
503+
}
504+
505+
sub calcapkdatachecksum {
506+
my ($handle, $apkdataoffset, $type) = @_;
507+
$apkdataoffset ||= (calcapkchksum($handle))[2];
508+
$type ||= 'sha256';
509+
die("unsupported apkchksum type $type\n") unless $type eq 'sha256';
510+
die("missing apkdataoffset\n") unless $apkdataoffset;
511+
my $fd;
512+
open($fd, '<', $handle) || die("$handle: $!\n");
513+
my $ctx;
514+
$ctx = Digest::SHA->new(256) if $type eq 'sha256';
515+
die("unsupported apkchksum type $type\n") unless $ctx;
516+
seek($fd, $apkdataoffset, 0) || die("$handle seek $apkdataoffset: $!\n");
517+
$ctx->addfile($fd);
518+
close($fd);
519+
return $ctx->hexdigest();
520+
}
521+
452522
my %verscmp_class = ( '.' => 1, 'X' => 2, '_' => 3, '~' => 4, '-' => 5, '$' => 6, '!' => 7 );
453523
my %verscmp_suf = ( 'alpha' => 1, 'beta' => 2, 'pre' => 3, 'rc' => 4, 'cvs' => 5, 'svn' => 6, 'git' => 7, 'hg' => 8, 'p' => 9 );
454524

0 commit comments

Comments
 (0)