port to androguard >= 4 and drop support for older than 3.3.3

This also makes androguard a hard requirement, which has been true for a
while anyway.  So the code that handles androguard as an optional
requirement is removed.  androguard from Debian/buster is new enough, so
this does not seem like it will cause any problems.
This commit is contained in:
Hans-Christoph Steiner 2024-04-01 11:42:23 +02:00
parent e24640da85
commit 39e0b12957
5 changed files with 30 additions and 35 deletions

View File

@ -2629,29 +2629,12 @@ def get_file_extension(filename):
return os.path.splitext(filename)[1].lower()[1:]
def use_androguard():
"""Report if androguard is available, and config its debug logging."""
try:
import androguard
if use_androguard.show_path:
logging.debug(_('Using androguard from "{path}"').format(path=androguard.__file__))
use_androguard.show_path = False
if options and options.verbose:
logging.getLogger("androguard.axml").setLevel(logging.INFO)
logging.getLogger("androguard.core.api_specific_resources").setLevel(logging.ERROR)
return True
except ImportError:
return False
use_androguard.show_path = True # type: ignore
def _get_androguard_APK(apkfile):
try:
# these were moved in androguard 4.0
from androguard.core.apk import APK
except ImportError:
from androguard.core.bytecodes.apk import APK
except ImportError as exc:
raise FDroidException("androguard library is not installed") from exc
return APK(apkfile)
@ -2693,7 +2676,11 @@ def is_debuggable_or_testOnly(apkfile):
"""
if get_file_extension(apkfile) != 'apk':
return False
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG
try:
# these were moved in androguard 4.0
from androguard.core.axml import AXMLParser, format_value, START_TAG
except ImportError:
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG
with ZipFile(apkfile) as apk:
with apk.open('AndroidManifest.xml') as manifest:
axml = AXMLParser(manifest.read())
@ -2753,12 +2740,19 @@ def get_apk_id_androguard(apkfile):
versionName is set to a Android String Resource (e.g. an integer
hex value that starts with @).
This function is part of androguard as get_apkid(), so this
vendored and modified to return versionCode as an integer.
"""
if not os.path.exists(apkfile):
raise FDroidException(_("Reading packageName/versionCode/versionName failed, APK invalid: '{apkfilename}'")
.format(apkfilename=apkfile))
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
try:
# these were moved in androguard 4.0
from androguard.core.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
except ImportError:
from androguard.core.bytecodes.axml import AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
appid = None
versionCode = None
@ -3159,7 +3153,7 @@ def get_first_signer_certificate(apkpath):
elif len(cert_files) == 1:
cert_encoded = get_certificate(apk.read(cert_files[0]))
if not cert_encoded and use_androguard():
if not cert_encoded:
apkobject = _get_androguard_APK(apkpath)
certs = apkobject.get_certificates_der_v2()
if len(certs) > 0:

View File

@ -1571,8 +1571,7 @@ def _sanitize_sdk_version(value):
def scan_apk_androguard(apk, apkfile):
try:
from androguard.core.bytecodes.apk import APK
apkobject = APK(apkfile)
apkobject = common._get_androguard_APK(apkfile)
if apkobject.is_valid_APK():
arsc = apkobject.get_android_resources()
else:
@ -2430,7 +2429,6 @@ def main():
config = common.read_config(options)
common.setup_status_output(start_timestamp)
common.use_androguard()
if not (('jarsigner' in config or 'apksigner' in config)
and 'keytool' in config):
raise FDroidException(_('Java JDK not found! Install in standard location or set java_paths!'))

View File

@ -92,7 +92,7 @@ setup(
],
install_requires=[
'appdirs',
'androguard >= 3.1.0, != 3.3.0, != 3.3.1, != 3.3.2, <4',
'androguard >= 3.3.3',
'clint',
'defusedxml',
'GitPython',

View File

@ -8,7 +8,9 @@ echo_header() {
get_fdroid_apk_filename() {
if [ -z $aapt ]; then
python3 -c "from androguard.core.bytecodes.apk import APK; a=APK('$1'); print(a.package+'_'+a.get_androidversion_code()+'.apk')"
appid=$(androguard apkid "$1" | grep -Eio '"[a-z][^"]+",' | sed 's/[,"]//g')
versionCode=$(androguard apkid "$1" | grep -Eo '"[0-9]+"' | sed 's,",,g')
echo "${appid}_${versionCode}.apk"
else
$aapt dump badging "$1" | sed -n "s,^package: name='\(.*\)' versionCode='\([0-9][0-9]*\)' .*,\1_\2.apk,p"
fi

View File

@ -5,6 +5,7 @@
import copy
import git
import glob
import hashlib
import inspect
import json
import logging
@ -20,11 +21,18 @@ import unittest
import yaml
import zipfile
import textwrap
from binascii import hexlify
from datetime import datetime
from pathlib import Path
from testcommon import TmpCwd, mkdtemp
from unittest import mock
try:
# these were moved in androguard 4.0
from androguard.core.apk import APK
except ImportError:
from androguard.core.bytecodes.apk import APK
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
@ -581,13 +589,6 @@ class UpdateTest(unittest.TestCase):
self.assertEqual(good_fingerprint, sig,
'python sig was: ' + str(sig))
# check that v1 and v2 have the same certificate
try:
import hashlib
from binascii import hexlify
from androguard.core.bytecodes.apk import APK
except ImportError:
print('WARNING: skipping rest of test since androguard is missing!')
return
apkobject = APK(apkpath)
cert_encoded = apkobject.get_certificates_der_v2()[0]
self.assertEqual(good_fingerprint, sig,