X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=fdroidserver%2Fcommon.py;h=bb1de220fb53a538ac98967c5447ce514aa2f1bf;hb=27a5cce832cb4c2d42e3ebd91562c00043b02721;hp=c0e49027c84c10735fad585fb15eb58e8b9039c9;hpb=98a2f70e38605450446857fd7064e702f9f55b73;p=fdroidserver.git diff --git a/fdroidserver/common.py b/fdroidserver/common.py index c0e49027..bb1de220 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -1955,6 +1955,36 @@ def use_androguard(): use_androguard.show_path = True +def _get_androguard_APK(apkfile): + try: + from androguard.core.bytecodes.apk import APK + except ImportError: + raise FDroidException("androguard library is not installed and aapt not present") + + return APK(apkfile) + + +def ensure_final_value(packageName, arsc, value): + """Ensure incoming value is always the value, not the resid + + androguard will sometimes return the Android "resId" aka + Resource ID instead of the actual value. This checks whether + the value is actually a resId, then performs the Android + Resource lookup as needed. + + """ + if value: + returnValue = value + if value[0] == '@': + try: # can be a literal value or a resId + res_id = int('0x' + value[1:], 16) + res_id = arsc.get_id(packageName, res_id)[1] + returnValue = arsc.get_string(packageName, res_id)[1] + except ValueError: + pass + return returnValue + + def is_apk_and_debuggable_aapt(apkfile): p = SdkToolsPopen(['aapt', 'dump', 'xmltree', apkfile, 'AndroidManifest.xml'], output=False) @@ -1967,12 +1997,7 @@ def is_apk_and_debuggable_aapt(apkfile): def is_apk_and_debuggable_androguard(apkfile): - try: - from androguard.core.bytecodes.apk import APK - except ImportError: - raise FDroidException("androguard library is not installed and aapt not present") - - apkobject = APK(apkfile) + apkobject = _get_androguard_APK(apkfile) if apkobject.is_valid_APK(): debuggable = apkobject.get_element("application", "debuggable") if debuggable is not None: @@ -1994,12 +2019,30 @@ def is_apk_and_debuggable(apkfile): return is_apk_and_debuggable_aapt(apkfile) -def get_apk_id_aapt(apkfile): +def get_apk_id(apkfile): """Extract identification information from APK using aapt. :param apkfile: path to an APK file. :returns: triplet (appid, version code, version name) """ + if use_androguard(): + return get_apk_id_androguard(apkfile) + else: + return get_apk_id_aapt(apkfile) + + +def get_apk_id_androguard(apkfile): + if not os.path.exists(apkfile): + raise FDroidException(_("Reading packageName/versionCode/versionName failed, APK invalid: '{apkfilename}'") + .format(apkfilename=apkfile)) + a = _get_androguard_APK(apkfile) + versionName = ensure_final_value(a.package, a.get_android_resources(), a.get_androidversion_name()) + if not versionName: + versionName = '' # versionName is expected to always be a str + return a.package, a.get_androidversion_code(), versionName + + +def get_apk_id_aapt(apkfile): r = re.compile("^package: name='(?P.*)' versionCode='(?P.*)' versionName='(?P.*?)'(?: platformBuildVersionName='.*')?") p = SdkToolsPopen(['aapt', 'dump', 'badging', apkfile], output=False) for line in p.output.splitlines():