@@ -23,8 +23,16 @@ package Build::Apk;
23
23
use strict;
24
24
25
25
use Digest::MD5;
26
- eval { require Archive::Tar; };
26
+ use Digest::SHA;
27
+
28
+ eval { require Archive::Tar };
27
29
*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
+
28
36
29
37
sub expandvars_cplx {
30
38
my ($v , $vars ) = @_ ;
@@ -323,6 +331,7 @@ my %pkginfomap = (
323
331
# 'replaces' => [ 'obsoletes' ],
324
332
'provides' => [ 'provides' ],
325
333
'install_if' => [ 'supplements' ],
334
+ 'datahash' => 'apkdatachksum',
326
335
);
327
336
328
337
sub query {
@@ -365,6 +374,7 @@ sub query {
365
374
$q {'source'} ||= $q {'name'} if defined $q {'name'};
366
375
delete $q {'supplements'} unless $opts {'weakdeps'};
367
376
delete $q {'buildtime'} unless $opts {'buildtime'};
377
+ delete $q {'apkdatachksum'} unless $opts {'apkdatachksum'};
368
378
return \% q;
369
379
}
370
380
@@ -376,7 +386,7 @@ my %idxinfomap = (
376
386
't' => 'buildtime',
377
387
'A' => 'arch',
378
388
'L' => 'license',
379
- 'C' => 'apk_chksum ',
389
+ 'C' => 'apkchksum ',
380
390
'o' => 'source',
381
391
'D' => [ 'requires' ],
382
392
# 'r' => [ 'obsoletes' ],
@@ -449,6 +459,66 @@ sub queryhdrmd5 {
449
459
return Digest::MD5::md5_hex($pkginfo );
450
460
}
451
461
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
+
452
522
my %verscmp_class = ( '.' => 1, 'X' => 2, '_' => 3, '~' => 4, '-' => 5, '$' => 6, '!' => 7 );
453
523
my %verscmp_suf = ( 'alpha' => 1, 'beta' => 2, 'pre' => 3, 'rc' => 4, 'cvs' => 5, 'svn' => 6, 'git' => 7, 'hg' => 8, 'p' => 9 );
454
524
0 commit comments