Skip to content

Commit e95bc92

Browse files
committed
Support the Apkv3 format
1 parent c8854e6 commit e95bc92

File tree

5 files changed

+465
-19
lines changed

5 files changed

+465
-19
lines changed

Build/Apk.pm

+30-5
Original file line numberDiff line numberDiff line change
@@ -469,9 +469,25 @@ my %pkginfomap = (
469469
'hdrmd5' => 'hdrmd5',
470470
);
471471
472+
sub is_apkv3 {
473+
my ($file) = @_;
474+
my $fd;
475+
open($fd, '<', $file) || die("$file: $!\n");
476+
my $first;
477+
read($fd, $first, 3);
478+
close $fd;
479+
return $first && substr($first, 0, 3) eq 'ADB' ? 1 : 0;
480+
}
481+
472482
sub query {
473483
my ($handle, %opts) = @_;
474-
my $qq = queryvars($handle, 1);
484+
my $qq;
485+
if (is_apkv3($handle)) {
486+
require Build::Apkv3 unless defined &Build::Apkv3::querypkginfo;
487+
$qq = Build::Apkv3::querypkginfo($handle, 1);
488+
} else {
489+
$qq = queryvars($handle, 1);
490+
}
475491
my %q;
476492
for (keys %$qq) {
477493
my $m = $pkginfomap{$_};
@@ -574,6 +590,10 @@ sub queryinstalled {
574590
575591
sub queryhdrmd5 {
576592
my ($handle) = @_;
593+
if (is_apkv3($handle)) {
594+
require Build::Apkv3 unless defined &Build::Apkv3::calcapkchksum;
595+
return Build::Apkv3::calcapkchksum($handle, 'md5', 'ctrl');
596+
}
577597
my $tar = Archive::Tar->new;
578598
my @read = $tar->read($handle, 1, {'filter' => '^\.PKGINFO$', 'limit' => 1});
579599
die("$handle: not an apk package file\n") unless @read == 1;
@@ -585,16 +605,20 @@ sub queryhdrmd5 {
585605
# this calculates the checksum of a compressed section.
586606
sub calcapkchksum {
587607
my ($handle, $type, $section, $toeof) = @_;
608+
if (is_apkv3($handle)) {
609+
require Build::Apkv3 unless defined &Build::Apkv3::querypkginfo;
610+
return Build::Apkv3::calcapkchksum(@_);
611+
}
588612
$section ||= 'ctrl';
589613
$type ||= 'Q1';
590-
die("unsupported apkchksum type $type\n") unless $type eq 'Q1' || $type eq 'sha1' || $type eq 'sha256' || $type eq 'sha512' || $type eq 'md5' || $type eq 'raw';
614+
die("unsupported apkchksum type $type\n") unless $type eq 'Q1' || $type eq 'Q2' || $type eq 'sha1' || $type eq 'sha256' || $type eq 'sha512' || $type eq 'md5' || $type eq 'raw' || $type eq 'X1' || $type eq 'X2';
591615
die("unsupported apkchksum section $section\n") unless $section eq 'sig' || $section eq 'ctrl' || $section eq 'data';
592616
$section = $section eq 'sig' ? 0 : $section eq 'ctrl' ? 1 : 2;
593617
my $fd;
594618
open($fd, '<', $handle) or die("$handle: $!\n");
595619
my $ctx;
596-
$ctx = Digest::SHA->new(1) if $type eq 'Q1' || $type eq 'sha1';
597-
$ctx = Digest::SHA->new(256) if $type eq 'sha256';
620+
$ctx = Digest::SHA->new(1) if $type eq 'Q1' || $type eq 'X1' || $type eq 'sha1';
621+
$ctx = Digest::SHA->new(256) if $type eq 'Q2' || $type eq 'X2' || $type eq 'sha256';
598622
$ctx = Digest::SHA->new(512) if $type eq 'sha512';
599623
$ctx = Digest::MD5->new() if $type eq 'md5';
600624
$ctx = '' if $type eq 'raw';
@@ -633,7 +657,8 @@ sub calcapkchksum {
633657
$ctx->addfile($fd);
634658
}
635659
return $ctx if $type eq 'raw';
636-
return 'Q1'.MIME::Base64::encode_base64($ctx->digest(), '') if $type eq 'Q1';
660+
return $type.MIME::Base64::encode_base64($ctx->digest(), '') if $type eq 'Q1' || $type eq 'Q2';
661+
return $type.$ctx->hexdigest() if $type eq 'X1' || $type eq 'X2';
637662
return $ctx->hexdigest();
638663
}
639664

Build/Apkrepo.pm

+52-10
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,67 @@ sub addpkg {
5151

5252
$data->{'location'} = "$data->{'name'}-$data->{'version'}.apk";
5353
$data->{'release'} = $1 if $data->{'version'} =~ s/-([^-]*)$//s;
54-
my $apk_chksum = delete $data->{'apk_chksum'};
55-
if ($options->{'withapkchecksum'} && $apk_chksum) {
56-
if (substr($apk_chksum, 0, 2) eq 'Q1' && defined &MIME::Base64::decode_base64) {
57-
my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
58-
$data->{'apkchecksum'} = "sha1:" . unpack('H*', $c) if $c && length($c) == 20;
59-
} elsif (substr($apk_chksum, 0, 2) eq 'Q2' && defined &MIME::Base64::decode_base64) {
60-
my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
61-
$data->{'apkchecksum'} = "sha256:" . unpack('H*', $c) if $c && length($c) == 32;
62-
}
63-
}
54+
#my $apk_chksum = delete $data->{'apk_chksum'};
55+
#if ($options->{'withapkchecksum'} && $apk_chksum) {
56+
# if (substr($apk_chksum, 0, 2) eq 'Q1' && defined &MIME::Base64::decode_base64) {
57+
# my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
58+
# $data->{'apkchecksum'} = "sha1:" . unpack('H*', $c) if $c && length($c) == 20;
59+
# } elsif (substr($apk_chksum, 0, 2) eq 'Q2' && defined &MIME::Base64::decode_base64) {
60+
# my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
61+
# $data->{'apkchecksum'} = "sha256:" . unpack('H*', $c) if $c && length($c) == 32;
62+
# }
63+
#}
6464
if (ref($res) eq 'CODE') {
6565
$res->($data);
6666
} else {
6767
push @$res, $data;
6868
}
6969
}
7070

71+
my %pkginfomap = (
72+
'pkgname' => 'name',
73+
'pkgver' => 'version',
74+
'pkgdesc' => 'summary',
75+
'url' => 'url',
76+
'builddate' => 'buildtime',
77+
'arch' => 'arch',
78+
'license' => 'license',
79+
'origin' => 'source',
80+
'depend' => 'requires',
81+
'provides' => 'provides',
82+
'datahash' => 'apkdatachksum',
83+
'hdrmd5' => 'hdrmd5',
84+
);
85+
86+
sub apkv3_parse {
87+
my ($in, $res, %options) = @_;
88+
require Build::Apkv3 unless defined &Build::Apkv3::querypkgindex;
89+
my $q = Build::Apkv3::querypkgindex($in);
90+
for my $qq (@{$q->{'packages'} || []}) {
91+
my %q;
92+
for (keys %$qq) {
93+
my $m = $pkginfomap{$_};
94+
$q{$m} = $qq->{$_} if $m;
95+
}
96+
if ($qq->{'apkchksum'}) {
97+
$q{'apkchksum'} = 'X1'.$qq->{'apkchksum'} if length($qq->{'apkchksum'}) == 40;
98+
$q{'apkchksum'} = 'X2'.$qq->{'apkchksum'} if length($qq->{'apkchksum'}) == 64;
99+
}
100+
my @conflicts = grep {/^\!/} @{$q{'requires'} || []};
101+
if (@conflicts) {
102+
substr($_, 0, 1, '') for @conflicts;
103+
$q{'conflicts'} = \@conflicts;
104+
$q{'requires'} = [ grep {!/^\!/} @{$q{'requires'} || []} ];
105+
delete $q{'requires'} unless @{$q{'requires'}};
106+
}
107+
addpkg($res, \%q, \%options);
108+
}
109+
}
110+
71111
sub parse {
72112
my ($in, $res, %options) = @_;
113+
die("Build::Apkrepo::parse needs a filename\n") if ref($in);
114+
return apkv3_parse(@_) if Build::Apk::is_apkv3($in);
73115
$res ||= [];
74116
my $tar = Archive::Tar->new;
75117
my @read = $tar->read($in, 1, {'filter' => '^APKINDEX$', 'limit' => 1});

0 commit comments

Comments
 (0)