purge update.scan_apk_aapt()

androguard v3.3.3+ properly extracts the app name, so this adds the
names to the tests.
This commit is contained in:
Hans-Christoph Steiner 2020-10-14 17:04:26 +02:00
parent 8fd7dcd425
commit 08931f4524
4 changed files with 60 additions and 169 deletions

View File

@ -49,7 +49,6 @@ from . import _
from . import common
from . import index
from . import metadata
from .common import SdkToolsPopen
from .exception import BuildException, FDroidException
from PIL import Image, PngImagePlugin
@ -1350,10 +1349,7 @@ def scan_apk(apk_file):
'antiFeatures': set(),
}
if common.use_androguard():
scan_apk_androguard(apk, apk_file)
else:
scan_apk_aapt(apk, apk_file)
scan_apk_androguard(apk, apk_file)
if not common.is_valid_package_name(apk['packageName']):
raise BuildException(_("{appid} from {path} is not a valid Java Package Name!")
@ -1412,83 +1408,6 @@ def _get_apk_icons_src(apkfile, icon_name):
return icons_src
def scan_apk_aapt(apk, apkfile):
p = SdkToolsPopen(['aapt', 'dump', 'badging', apkfile], output=False)
if p.returncode != 0:
if options.delete_unknown:
if os.path.exists(apkfile):
logging.error(_("Failed to get apk information, deleting {path}").format(path=apkfile))
os.remove(apkfile)
else:
logging.error("Could not find {0} to remove it".format(apkfile))
else:
logging.error(_("Failed to get apk information, skipping {path}").format(path=apkfile))
raise BuildException(_("Invalid APK"))
icon_name = None
for line in p.output.splitlines():
if line.startswith("package:"):
try:
apk['packageName'] = re.match(APK_NAME_PAT, line).group(1)
apk['versionCode'] = int(re.match(APK_VERCODE_PAT, line).group(1))
apk['versionName'] = re.match(APK_VERNAME_PAT, line).group(1)
except Exception as e:
raise FDroidException("Package matching failed: " + str(e) + "\nLine was: " + line)
elif line.startswith("application:"):
m = re.match(APK_LABEL_ICON_PAT, line)
if m:
apk['name'] = m.group(1)
icon_name = os.path.splitext(os.path.basename(m.group(2)))[0]
elif not apk.get('name') and line.startswith("launchable-activity:"):
# Only use launchable-activity as fallback to application
apk['name'] = re.match(APK_LABEL_ICON_PAT, line).group(1)
elif line.startswith("sdkVersion:"):
m = re.match(APK_SDK_VERSION_PAT, line)
if m is None:
logging.error(line.replace('sdkVersion:', '')
+ ' is not a valid minSdkVersion!')
else:
apk['minSdkVersion'] = int(m.group(1))
elif line.startswith("targetSdkVersion:"):
m = re.match(APK_SDK_VERSION_PAT, line)
if m is None:
logging.error(line.replace('targetSdkVersion:', '')
+ ' is not a valid targetSdkVersion!')
else:
apk['targetSdkVersion'] = int(m.group(1))
elif line.startswith("maxSdkVersion:"):
apk['maxSdkVersion'] = int(re.match(APK_SDK_VERSION_PAT, line).group(1))
elif line.startswith("native-code:"):
apk['nativecode'] = []
for arch in line[13:].split(' '):
apk['nativecode'].append(arch[1:-1])
elif line.startswith('uses-permission:'):
perm_match = re.match(APK_PERMISSION_PAT, line).groups()
permission = UsesPermission(
perm_match[0], # name
None if perm_match[1] is None else int(perm_match[1]), # maxSdkVersion
)
apk['uses-permission'].append(permission)
elif line.startswith('uses-permission-sdk-23:'):
perm_match = re.match(APK_PERMISSION_PAT, line).groups()
permission_sdk_23 = UsesPermissionSdk23(
perm_match[0], # name
None if perm_match[1] is None else int(perm_match[1]), # maxSdkVersion
)
apk['uses-permission-sdk-23'].append(permission_sdk_23)
elif line.startswith('uses-feature:'):
feature = re.match(APK_FEATURE_PAT, line).group(1)
# Filter out this, it's only added with the latest SDK tools and
# causes problems for lots of apps.
if feature != "android.hardware.screen.portrait" \
and feature != "android.hardware.screen.landscape":
if feature.startswith("android.feature."):
feature = feature[16:]
apk['features'].add(feature)
apk['icons_src'] = _get_apk_icons_src(apkfile, icon_name)
def _sanitize_sdk_version(value):
"""Sanitize the raw values from androguard to handle bad values
@ -1529,8 +1448,6 @@ def scan_apk_androguard(apk, apkfile):
logging.error(_("Failed to get apk information, skipping {path}")
.format(path=apkfile))
raise BuildException(_("Invalid APK"))
except ImportError:
raise FDroidException("androguard library is not installed and aapt not present")
except FileNotFoundError:
logging.error(_("Could not open apk file for analysis"))
raise BuildException(_("Invalid APK"))

View File

@ -10,6 +10,7 @@ icons_src:
'-1': res/drawable/ic_launcher.png
'160': res/drawable/ic_launcher.png
minSdkVersion: 4
name: urzip
packageName: info.guardianproject.urzip
sig: e0ecb5fc2d63088e4a07ae410a127722
signer: 7eabd8c15de883d1e82b5df2fd4f7f769e498078e9ad6dc901f0e96db77ceac3

View File

@ -14,6 +14,7 @@ icons_src:
'160': res/drawable-mdpi-v4/icon_launcher.png
'240': res/drawable-hdpi-v4/icon_launcher.png
minSdkVersion: 7
name: Compass Keyboard
nativecode:
- arm64-v8a
- armeabi

View File

@ -458,98 +458,72 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.config = config
fdroidserver.update.config = config
os.chdir(os.path.join(localmodule, 'tests'))
try:
config['aapt'] = fdroidserver.common.find_sdk_tools_cmd('aapt')
except fdroidserver.exception.FDroidException:
pass # aapt is not required if androguard is present
for use_androguard in (True, False):
if use_androguard:
try:
import androguard
androguard
def func():
return True
fdroidserver.common.use_androguard = func
except ImportError:
continue
else:
if 'aapt' in config:
def func():
return False
fdroidserver.common.use_androguard = func
else:
continue
print('USE_ANDROGUARD', use_androguard)
apksigner = fdroidserver.common.find_apksigner()
if apksigner:
if use_androguard: # v2 parsing needs both
config['apksigner'] = apksigner
apk_info = fdroidserver.update.scan_apk('v2.only.sig_2.apk')
self.assertIsNone(apk_info.get('maxSdkVersion'))
self.assertEqual(apk_info.get('versionName'), 'v2-only')
self.assertEqual(apk_info.get('versionCode'), 2)
else:
print('WARNING: skipping v2-only test since apksigner cannot be found')
apk_info = fdroidserver.update.scan_apk('repo/v1.v2.sig_1020.apk')
apksigner = fdroidserver.common.find_apksigner()
if apksigner:
config['apksigner'] = apksigner
apk_info = fdroidserver.update.scan_apk('v2.only.sig_2.apk')
self.assertIsNone(apk_info.get('maxSdkVersion'))
self.assertEqual(apk_info.get('versionName'), 'v1+2')
self.assertEqual(apk_info.get('versionCode'), 1020)
self.assertEqual(apk_info.get('versionName'), 'v2-only')
self.assertEqual(apk_info.get('versionCode'), 2)
else:
print('WARNING: skipping v2-only test since apksigner cannot be found')
apk_info = fdroidserver.update.scan_apk('repo/v1.v2.sig_1020.apk')
self.assertIsNone(apk_info.get('maxSdkVersion'))
self.assertEqual(apk_info.get('versionName'), 'v1+2')
self.assertEqual(apk_info.get('versionCode'), 1020)
apk_info = fdroidserver.update.scan_apk('repo/souch.smsbypass_9.apk')
self.assertIsNone(apk_info.get('maxSdkVersion'))
self.assertEqual(apk_info.get('versionName'), '0.9')
apk_info = fdroidserver.update.scan_apk('repo/souch.smsbypass_9.apk')
self.assertIsNone(apk_info.get('maxSdkVersion'))
self.assertEqual(apk_info.get('versionName'), '0.9')
apk_info = fdroidserver.update.scan_apk('repo/duplicate.permisssions_9999999.apk')
self.assertEqual(apk_info.get('versionName'), '')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_launcher.png',
'-1': 'res/drawable/ic_launcher.png'})
apk_info = fdroidserver.update.scan_apk('repo/duplicate.permisssions_9999999.apk')
self.assertEqual(apk_info.get('versionName'), '')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_launcher.png',
'-1': 'res/drawable/ic_launcher.png'})
apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
'120': 'res/drawable-ldpi-v4/icon_launcher.png',
'160': 'res/drawable-mdpi-v4/icon_launcher.png',
'-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
self.assertEqual(apk_info['icons'], {})
self.assertEqual(apk_info['features'], [])
self.assertEqual(apk_info['antiFeatures'], set())
self.assertEqual(apk_info['versionName'], 'v1.6pre2')
self.assertEqual(apk_info['hash'],
'897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
self.assertEqual(apk_info['versionCode'], 20)
self.assertEqual(apk_info['size'], 132453)
self.assertEqual(apk_info['nativecode'],
['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
self.assertEqual(apk_info['minSdkVersion'], 7)
self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
self.assertEqual(apk_info['hashType'], 'sha256')
self.assertEqual(apk_info['targetSdkVersion'], 8)
apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
'120': 'res/drawable-ldpi-v4/icon_launcher.png',
'160': 'res/drawable-mdpi-v4/icon_launcher.png',
'-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
self.assertEqual(apk_info['icons'], {})
self.assertEqual(apk_info['features'], [])
self.assertEqual(apk_info['antiFeatures'], set())
self.assertEqual(apk_info['versionName'], 'v1.6pre2')
self.assertEqual(apk_info['hash'],
'897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
self.assertEqual(apk_info['versionCode'], 20)
self.assertEqual(apk_info['size'], 132453)
self.assertEqual(apk_info['nativecode'],
['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
self.assertEqual(apk_info['minSdkVersion'], 7)
self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
self.assertEqual(apk_info['hashType'], 'sha256')
self.assertEqual(apk_info['targetSdkVersion'], 8)
apk_info = fdroidserver.update.scan_apk('org.bitbucket.tickytacky.mirrormirror_4.apk')
self.assertEqual(apk_info.get('versionName'), '1.0.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable-mdpi/mirror.png',
'-1': 'res/drawable-mdpi/mirror.png'})
apk_info = fdroidserver.update.scan_apk('org.bitbucket.tickytacky.mirrormirror_4.apk')
self.assertEqual(apk_info.get('versionName'), '1.0.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable-mdpi/mirror.png',
'-1': 'res/drawable-mdpi/mirror.png'})
apk_info = fdroidserver.update.scan_apk('repo/info.zwanenburg.caffeinetile_4.apk')
self.assertEqual(apk_info.get('versionName'), '1.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_coffee_on.xml',
'-1': 'res/drawable/ic_coffee_on.xml'})
apk_info = fdroidserver.update.scan_apk('repo/info.zwanenburg.caffeinetile_4.apk')
self.assertEqual(apk_info.get('versionName'), '1.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_coffee_on.xml',
'-1': 'res/drawable/ic_coffee_on.xml'})
apk_info = fdroidserver.update.scan_apk('repo/com.politedroid_6.apk')
self.assertEqual(apk_info.get('versionName'), '1.5')
self.assertEqual(apk_info['icons_src'], {'120': 'res/drawable-ldpi-v4/icon.png',
'160': 'res/drawable-mdpi-v4/icon.png',
'240': 'res/drawable-hdpi-v4/icon.png',
'320': 'res/drawable-xhdpi-v4/icon.png',
'-1': 'res/drawable-mdpi-v4/icon.png'})
apk_info = fdroidserver.update.scan_apk('repo/com.politedroid_6.apk')
self.assertEqual(apk_info.get('versionName'), '1.5')
self.assertEqual(apk_info['icons_src'], {'120': 'res/drawable-ldpi-v4/icon.png',
'160': 'res/drawable-mdpi-v4/icon.png',
'240': 'res/drawable-hdpi-v4/icon.png',
'320': 'res/drawable-xhdpi-v4/icon.png',
'-1': 'res/drawable-mdpi-v4/icon.png'})
apk_info = fdroidserver.update.scan_apk('SpeedoMeterApp.main_1.apk')
self.assertEqual(apk_info.get('versionName'), '1.0')
self.assertEqual(apk_info['icons_src'], {})
apk_info = fdroidserver.update.scan_apk('SpeedoMeterApp.main_1.apk')
self.assertEqual(apk_info.get('versionName'), '1.0')
self.assertEqual(apk_info['icons_src'], {})
def test_scan_apk_no_min_target(self):
config = dict()
@ -627,8 +601,6 @@ class UpdateTest(unittest.TestCase):
# Don't care about the date added to the repo and relative apkName
del apk['added']
del apk['apkName']
# avoid AAPT application name bug
del apk['name']
# ensure that icons have been extracted properly
if apkName == '../urzip.apk':