chiark / gitweb /
common: fix bug in new SHA-256 signatures for >= android-18
[fdroidserver.git] / fdroidserver / common.py
index 8248a9441349f3c06b87eb66f0706db7ed7a8dee..06d40faab5b1a870b7e44f155a1cc33e0081a54f 100644 (file)
@@ -57,6 +57,9 @@ from fdroidserver.exception import FDroidException, VCSException, NoSubmodulesEx
     BuildException, VerificationException
 from .asynchronousfilereader import AsynchronousFileReader
 
+# this is the build-tools version, aapt has a separate version that
+# has to be manually set in test_aapt_version()
+MINIMUM_AAPT_VERSION = '26.0.0'
 
 # A signature block file with a .DSA, .RSA, or .EC extension
 CERT_PATH_REGEX = re.compile(r'^META-INF/.*\.(DSA|EC|RSA)$')
@@ -84,7 +87,7 @@ default_config = {
         'r16': None,
     },
     'qt_sdk_path': None,
-    'build_tools': "25.0.2",
+    'build_tools': MINIMUM_AAPT_VERSION,
     'force_build_tools': False,
     'java_paths': None,
     'ant': "ant",
@@ -397,13 +400,13 @@ def test_aapt_version(aapt):
             # the Debian package has the version string like "v0.2-23.0.2"
             too_old = False
             if '.' in bugfix:
-                if LooseVersion(bugfix) < LooseVersion('24.0.0'):
+                if LooseVersion(bugfix) < LooseVersion(MINIMUM_AAPT_VERSION):
                     too_old = True
-            elif LooseVersion('.'.join((major, minor, bugfix))) < LooseVersion('0.2.2964546'):
+            elif LooseVersion('.'.join((major, minor, bugfix))) < LooseVersion('0.2.4062713'):
                 too_old = True
             if too_old:
-                logging.warning(_("'{aapt}' is too old, fdroid requires build-tools-24.0.0 or newer!")
-                                .format(aapt=aapt))
+                logging.warning(_("'{aapt}' is too old, fdroid requires build-tools-{version} or newer!")
+                                .format(aapt=aapt, version=MINIMUM_AAPT_VERSION))
         else:
             logging.warning(_('Unknown version of aapt, might cause problems: ') + output)
 
@@ -1336,44 +1339,49 @@ def parse_androidmanifests(paths, app):
         vercode = None
         package = None
 
-        flavour = ""
+        flavour = None
         if app.builds and 'gradle' in app.builds[-1] and app.builds[-1].gradle:
-                flavour = app.builds[-1].gradle[-1]
+            flavour = app.builds[-1].gradle[-1]
 
         if has_extension(path, 'gradle'):
-            # first try to get version name and code from correct flavour
             with open(path, 'r') as f:
-                buildfile = f.read()
-
-                regex_string = r"" + flavour + "[^}]*?{.*?}"
-                search = re.compile(regex_string, re.DOTALL)
-                result = search.search(buildfile)
-
-            if result is not None:
-                resultgroup = result.group()
-
-                if not package:
-                    matches = psearch_g(resultgroup)
-                    if matches:
-                        s = matches.group(2)
-                        if app_matches_packagename(app, s):
-                            package = s
-                if not version:
-                    matches = vnsearch_g(resultgroup)
-                    if matches:
-                        version = matches.group(2)
-                if not vercode:
-                    matches = vcsearch_g(resultgroup)
-                    if matches:
-                        vercode = matches.group(1)
-            else:
-                # fall back to parse file line by line
-                with open(path, 'r') as f:
-                    for line in f:
-                        if gradle_comment.match(line):
-                            continue
-                        # Grab first occurence of each to avoid running into
-                        # alternative flavours and builds.
+                inside_flavour_group = 0
+                inside_required_flavour = 0
+                for line in f:
+                    if gradle_comment.match(line):
+                        continue
+
+                    if inside_flavour_group > 0:
+                        if inside_required_flavour > 0:
+                            matches = psearch_g(line)
+                            if matches:
+                                s = matches.group(2)
+                                if app_matches_packagename(app, s):
+                                    package = s
+
+                            matches = vnsearch_g(line)
+                            if matches:
+                                version = matches.group(2)
+
+                            matches = vcsearch_g(line)
+                            if matches:
+                                vercode = matches.group(1)
+
+                            if '{' in line:
+                                inside_required_flavour += 1
+                            if '}' in line:
+                                inside_required_flavour -= 1
+                        else:
+                            if flavour and (flavour in line):
+                                inside_required_flavour = 1
+
+                        if '{' in line:
+                            inside_flavour_group += 1
+                        if '}' in line:
+                            inside_flavour_group -= 1
+                    else:
+                        if "productFlavors" in line:
+                            inside_flavour_group = 1
                         if not package:
                             matches = psearch_g(line)
                             if matches:
@@ -2458,7 +2466,7 @@ def sign_apk(unsigned_path, signed_path, keyalias):
     if get_minSdkVersion_aapt(unsigned_path) < 18:
         signature_algorithm = ['-sigalg', 'SHA1withRSA', '-digestalg', 'SHA1']
     else:
-        signature_algorithm = ['-sigalg', 'SHA256withRSA', '-digestalg', 'SHA256']
+        signature_algorithm = ['-sigalg', 'SHA256withRSA', '-digestalg', 'SHA-256']
 
     p = FDroidPopen([config['jarsigner'], '-keystore', config['keystore'],
                      '-storepass:env', 'FDROID_KEY_STORE_PASS',