diff --git a/fdroidserver/build.py b/fdroidserver/build.py index 021c5da7..cbbed3cd 100644 --- a/fdroidserver/build.py +++ b/fdroidserver/build.py @@ -454,6 +454,54 @@ def capitalize_intact(string): return string[0].upper() + string[1:] +def get_metadata_from_apk(app, build, apkfile): + """get the required metadata from the built APK""" + + p = SdkToolsPopen(['aapt', 'dump', 'badging', apkfile], output=False) + + vercode = None + version = None + foundid = None + nativecode = None + for line in p.output.splitlines(): + if line.startswith("package:"): + pat = re.compile(".*name='([a-zA-Z0-9._]*)'.*") + m = pat.match(line) + if m: + foundid = m.group(1) + pat = re.compile(".*versionCode='([0-9]*)'.*") + m = pat.match(line) + if m: + vercode = m.group(1) + pat = re.compile(".*versionName='([^']*)'.*") + m = pat.match(line) + if m: + version = m.group(1) + elif line.startswith("native-code:"): + nativecode = line[12:] + + # Ignore empty strings or any kind of space/newline chars that we don't + # care about + if nativecode is not None: + nativecode = nativecode.strip() + nativecode = None if not nativecode else nativecode + + if build.buildjni and build.buildjni != ['no']: + if nativecode is None: + raise BuildException("Native code should have been built but none was packaged") + if build.novcheck: + vercode = build.vercode + version = build.version + if not version or not vercode: + raise BuildException("Could not find version information in build in output") + if not foundid: + raise BuildException("Could not find package ID in output") + if foundid != app.id: + raise BuildException("Wrong package ID - build " + foundid + " but expected " + app.id) + + return vercode, version + + def build_local(app, build, vcs, build_dir, output_dir, srclib_dir, extlib_dir, tmp_dir, force, onserver, refresh): """Do a build locally.""" @@ -809,7 +857,7 @@ def build_local(app, build, vcs, build_dir, output_dir, srclib_dir, extlib_dir, src = os.path.normpath(apks[0]) # Make sure it's not debuggable... - if common.isApkDebuggable(src, config): + if common.isApkAndDebuggable(src, config): raise BuildException("APK is debuggable") # By way of a sanity check, make sure the version and version @@ -818,56 +866,17 @@ def build_local(app, build, vcs, build_dir, output_dir, srclib_dir, extlib_dir, if not os.path.exists(src): raise BuildException("Unsigned apk is not at expected location of " + src) - p = SdkToolsPopen(['aapt', 'dump', 'badging', src], output=False) - - vercode = None - version = None - foundid = None - nativecode = None - for line in p.output.splitlines(): - if line.startswith("package:"): - pat = re.compile(".*name='([a-zA-Z0-9._]*)'.*") - m = pat.match(line) - if m: - foundid = m.group(1) - pat = re.compile(".*versionCode='([0-9]*)'.*") - m = pat.match(line) - if m: - vercode = m.group(1) - pat = re.compile(".*versionName='([^']*)'.*") - m = pat.match(line) - if m: - version = m.group(1) - elif line.startswith("native-code:"): - nativecode = line[12:] - - # Ignore empty strings or any kind of space/newline chars that we don't - # care about - if nativecode is not None: - nativecode = nativecode.strip() - nativecode = None if not nativecode else nativecode - - if build.buildjni and build.buildjni != ['no']: - if nativecode is None: - raise BuildException("Native code should have been built but none was packaged") - if build.novcheck: + if common.get_file_extension(src) == 'apk': + vercode, version = get_metadata_from_apk(app, build, src) + if (version != build.version or vercode != build.vercode): + raise BuildException(("Unexpected version/version code in output;" + " APK: '%s' / '%s', " + " Expected: '%s' / '%s'") + % (version, str(vercode), build.version, + str(build.vercode))) + else: vercode = build.vercode version = build.version - if not version or not vercode: - raise BuildException("Could not find version information in build in output") - if not foundid: - raise BuildException("Could not find package ID in output") - if foundid != app.id: - raise BuildException("Wrong package ID - build " + foundid + " but expected " + app.id) - - if (version != build.version or - vercode != build.vercode): - raise BuildException(("Unexpected version/version code in output;" - " APK: '%s' / '%s', " - " Expected: '%s' / '%s'") - % (version, str(vercode), build.version, - str(build.vercode)) - ) # Add information for 'fdroid verify' to be able to reproduce the build # environment. diff --git a/fdroidserver/common.py b/fdroidserver/common.py index 2ef58460..b653d5a8 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -1618,11 +1618,14 @@ def get_file_extension(filename): return os.path.splitext(filename)[1].lower()[1:] -def isApkDebuggable(apkfile, config): - """Returns True if the given apk file is debuggable +def isApkAndDebuggable(apkfile, config): + """Returns True if the given file is an APK and is debuggable :param apkfile: full path to the apk to check""" + if get_file_extension(apkfile) != 'apk': + return False + p = SdkToolsPopen(['aapt', 'dump', 'xmltree', apkfile, 'AndroidManifest.xml'], output=False) if p.returncode != 0: diff --git a/fdroidserver/update.py b/fdroidserver/update.py index 30390f82..cebd5a92 100644 --- a/fdroidserver/update.py +++ b/fdroidserver/update.py @@ -739,7 +739,7 @@ def scan_apks(apkcache, repodir, knownapks, use_date_from_apk=False): apk['minSdkVersion'] = 1 # Check for debuggable apks... - if common.isApkDebuggable(apkfile, config): + if common.isApkAndDebuggable(apkfile, config): logging.warning('{0} is set to android:debuggable="true"'.format(apkfile)) # Get the signature (or md5 of, to be precise)... diff --git a/tests/common.TestCase b/tests/common.TestCase index d7dca14e..d01568a2 100755 --- a/tests/common.TestCase +++ b/tests/common.TestCase @@ -74,7 +74,7 @@ class CommonTest(unittest.TestCase): testfiles.append(os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')) testfiles.append(os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')) for apkfile in testfiles: - debuggable = fdroidserver.common.isApkDebuggable(apkfile, config) + debuggable = fdroidserver.common.isApkAndDebuggable(apkfile, config) self.assertTrue(debuggable, "debuggable APK state was not properly parsed!") # these are set NOT debuggable @@ -82,7 +82,7 @@ class CommonTest(unittest.TestCase): testfiles.append(os.path.join(os.path.dirname(__file__), 'urzip-release.apk')) testfiles.append(os.path.join(os.path.dirname(__file__), 'urzip-release-unsigned.apk')) for apkfile in testfiles: - debuggable = fdroidserver.common.isApkDebuggable(apkfile, config) + debuggable = fdroidserver.common.isApkAndDebuggable(apkfile, config) self.assertFalse(debuggable, "debuggable APK state was not properly parsed!")