Skip to content

Commit

Permalink
Support the Apkv3 format
Browse files Browse the repository at this point in the history
  • Loading branch information
mlschroe committed Jan 10, 2025
1 parent c8854e6 commit e95bc92
Show file tree
Hide file tree
Showing 5 changed files with 465 additions and 19 deletions.
35 changes: 30 additions & 5 deletions Build/Apk.pm
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,25 @@ my %pkginfomap = (
'hdrmd5' => 'hdrmd5',
);
sub is_apkv3 {
my ($file) = @_;
my $fd;
open($fd, '<', $file) || die("$file: $!\n");
my $first;
read($fd, $first, 3);
close $fd;
return $first && substr($first, 0, 3) eq 'ADB' ? 1 : 0;
}
sub query {
my ($handle, %opts) = @_;
my $qq = queryvars($handle, 1);
my $qq;
if (is_apkv3($handle)) {
require Build::Apkv3 unless defined &Build::Apkv3::querypkginfo;
$qq = Build::Apkv3::querypkginfo($handle, 1);
} else {
$qq = queryvars($handle, 1);
}
my %q;
for (keys %$qq) {
my $m = $pkginfomap{$_};
Expand Down Expand Up @@ -574,6 +590,10 @@ sub queryinstalled {
sub queryhdrmd5 {
my ($handle) = @_;
if (is_apkv3($handle)) {
require Build::Apkv3 unless defined &Build::Apkv3::calcapkchksum;
return Build::Apkv3::calcapkchksum($handle, 'md5', 'ctrl');
}
my $tar = Archive::Tar->new;
my @read = $tar->read($handle, 1, {'filter' => '^\.PKGINFO$', 'limit' => 1});
die("$handle: not an apk package file\n") unless @read == 1;
Expand All @@ -585,16 +605,20 @@ sub queryhdrmd5 {
# this calculates the checksum of a compressed section.
sub calcapkchksum {
my ($handle, $type, $section, $toeof) = @_;
if (is_apkv3($handle)) {
require Build::Apkv3 unless defined &Build::Apkv3::querypkginfo;
return Build::Apkv3::calcapkchksum(@_);
}
$section ||= 'ctrl';
$type ||= 'Q1';
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';
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';
die("unsupported apkchksum section $section\n") unless $section eq 'sig' || $section eq 'ctrl' || $section eq 'data';
$section = $section eq 'sig' ? 0 : $section eq 'ctrl' ? 1 : 2;
my $fd;
open($fd, '<', $handle) or die("$handle: $!\n");
my $ctx;
$ctx = Digest::SHA->new(1) if $type eq 'Q1' || $type eq 'sha1';
$ctx = Digest::SHA->new(256) if $type eq 'sha256';
$ctx = Digest::SHA->new(1) if $type eq 'Q1' || $type eq 'X1' || $type eq 'sha1';
$ctx = Digest::SHA->new(256) if $type eq 'Q2' || $type eq 'X2' || $type eq 'sha256';
$ctx = Digest::SHA->new(512) if $type eq 'sha512';
$ctx = Digest::MD5->new() if $type eq 'md5';
$ctx = '' if $type eq 'raw';
Expand Down Expand Up @@ -633,7 +657,8 @@ sub calcapkchksum {
$ctx->addfile($fd);
}
return $ctx if $type eq 'raw';
return 'Q1'.MIME::Base64::encode_base64($ctx->digest(), '') if $type eq 'Q1';
return $type.MIME::Base64::encode_base64($ctx->digest(), '') if $type eq 'Q1' || $type eq 'Q2';
return $type.$ctx->hexdigest() if $type eq 'X1' || $type eq 'X2';
return $ctx->hexdigest();
}
Expand Down
62 changes: 52 additions & 10 deletions Build/Apkrepo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,67 @@ sub addpkg {

$data->{'location'} = "$data->{'name'}-$data->{'version'}.apk";
$data->{'release'} = $1 if $data->{'version'} =~ s/-([^-]*)$//s;
my $apk_chksum = delete $data->{'apk_chksum'};
if ($options->{'withapkchecksum'} && $apk_chksum) {
if (substr($apk_chksum, 0, 2) eq 'Q1' && defined &MIME::Base64::decode_base64) {
my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
$data->{'apkchecksum'} = "sha1:" . unpack('H*', $c) if $c && length($c) == 20;
} elsif (substr($apk_chksum, 0, 2) eq 'Q2' && defined &MIME::Base64::decode_base64) {
my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
$data->{'apkchecksum'} = "sha256:" . unpack('H*', $c) if $c && length($c) == 32;
}
}
#my $apk_chksum = delete $data->{'apk_chksum'};
#if ($options->{'withapkchecksum'} && $apk_chksum) {
# if (substr($apk_chksum, 0, 2) eq 'Q1' && defined &MIME::Base64::decode_base64) {
# my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
# $data->{'apkchecksum'} = "sha1:" . unpack('H*', $c) if $c && length($c) == 20;
# } elsif (substr($apk_chksum, 0, 2) eq 'Q2' && defined &MIME::Base64::decode_base64) {
# my $c = MIME::Base64::decode_base64(substr($apk_chksum, 2));
# $data->{'apkchecksum'} = "sha256:" . unpack('H*', $c) if $c && length($c) == 32;
# }
#}
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
}

my %pkginfomap = (
'pkgname' => 'name',
'pkgver' => 'version',
'pkgdesc' => 'summary',
'url' => 'url',
'builddate' => 'buildtime',
'arch' => 'arch',
'license' => 'license',
'origin' => 'source',
'depend' => 'requires',
'provides' => 'provides',
'datahash' => 'apkdatachksum',
'hdrmd5' => 'hdrmd5',
);

sub apkv3_parse {
my ($in, $res, %options) = @_;
require Build::Apkv3 unless defined &Build::Apkv3::querypkgindex;
my $q = Build::Apkv3::querypkgindex($in);
for my $qq (@{$q->{'packages'} || []}) {
my %q;
for (keys %$qq) {
my $m = $pkginfomap{$_};
$q{$m} = $qq->{$_} if $m;
}
if ($qq->{'apkchksum'}) {
$q{'apkchksum'} = 'X1'.$qq->{'apkchksum'} if length($qq->{'apkchksum'}) == 40;
$q{'apkchksum'} = 'X2'.$qq->{'apkchksum'} if length($qq->{'apkchksum'}) == 64;
}
my @conflicts = grep {/^\!/} @{$q{'requires'} || []};
if (@conflicts) {
substr($_, 0, 1, '') for @conflicts;
$q{'conflicts'} = \@conflicts;
$q{'requires'} = [ grep {!/^\!/} @{$q{'requires'} || []} ];
delete $q{'requires'} unless @{$q{'requires'}};
}
addpkg($res, \%q, \%options);
}
}

sub parse {
my ($in, $res, %options) = @_;
die("Build::Apkrepo::parse needs a filename\n") if ref($in);
return apkv3_parse(@_) if Build::Apk::is_apkv3($in);
$res ||= [];
my $tar = Archive::Tar->new;
my @read = $tar->read($in, 1, {'filter' => '^APKINDEX$', 'limit' => 1});
Expand Down
Loading

0 comments on commit e95bc92

Please sign in to comment.