chiark / gitweb /
regexs for getting packageName and versionCode from filenames
authorHans-Christoph Steiner <hans@eds.org>
Wed, 31 May 2017 21:02:28 +0000 (23:02 +0200)
committerHans-Christoph Steiner <hans@eds.org>
Thu, 1 Jun 2017 14:01:05 +0000 (16:01 +0200)
This is useful for parsing APK files, which can include packageName,
versionCode, and optionally 7 char signing key ID (i.e. <sig>).
This also can set the packageName and versionCoe for non APK files, so
that it is easy to assign them to metadata files, and to allow for
upgrades by setting the versionCode in the filename.

fdroidserver/common.py
fdroidserver/update.py
tests/common.TestCase
tests/stats/known_apks.txt

index ca02219fe50466f20ea916bb52377507e76c5366..75eac97cafb777403891f45f77b27bd18874223c 100644 (file)
@@ -55,6 +55,8 @@ from .asynchronousfilereader import AsynchronousFileReader
 
 # A signature block file with a .DSA, .RSA, or .EC extension
 CERT_PATH_REGEX = re.compile(r'^META-INF/.*\.(DSA|EC|RSA)$')
+APK_NAME_REGEX = re.compile(r'^([a-zA-Z][\w.]*)_(-?[0-9]+)_?([0-9a-f]{7})?\.apk')
+STANDARD_FILE_NAME_REGEX = re.compile(r'^(\w[\w.]*)_(-?[0-9]+)\.\w+')
 
 XMLElementTree.register_namespace('android', 'http://schemas.android.com/apk/res/android')
 
index caea795b44f29ed624673060cfe2f15f76fa6627..c36fd86e3ca3e69b9080045d91a72b3807d6ac27 100644 (file)
@@ -853,14 +853,10 @@ def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False):
             # the static ID is the SHA256 unless it is set in the metadata
             repo_file['packageName'] = shasum
 
-            n = name_utf8.rsplit('_', maxsplit=1)
-            if len(n) == 2:
-                packageName = n[0]
-                versionCode = n[1].split('.')[0]
-                if re.match('^-?[0-9]+$', versionCode) \
-                   and common.is_valid_package_name(n[0]):
-                    repo_file['packageName'] = packageName
-                    repo_file['versionCode'] = int(versionCode)
+            m = common.STANDARD_FILE_NAME_REGEX.match(name_utf8)
+            if m:
+                repo_file['packageName'] = m.group(1)
+                repo_file['versionCode'] = int(m.group(2))
             srcfilename = name + b'_src.tar.gz'
             if os.path.exists(os.path.join(repodir, srcfilename)):
                 repo_file['srcname'] = srcfilename.decode('utf-8')
index 74364098ecd73391cbf6ef4abac5c212c9e8c33e..f0dcaccee41bef5df6b8ac5ba8e120ec45a12f2c 100755 (executable)
@@ -281,6 +281,70 @@ class CommonTest(unittest.TestCase):
                 key = "val"
                 """))
 
+    def test_apk_name_regex(self):
+        good = [
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_-123456.apk',
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_123456_abcdef0.apk',
+            'urzip_-123456.apk',
+            'a0_0.apk',
+            'Z0_0.apk',
+            'a0_0_abcdef0.apk',
+            'a_a_a_a_0_abcdef0.apk',
+            'a_____0.apk',
+            'a_____123456_abcdef0.apk',
+            'org.fdroid.fdroid_123456.apk',
+            # valid, but "_99999" is part of packageName rather than versionCode
+            'org.fdroid.fdroid_99999_123456.apk',
+            # should be valid, but I can't figure out the regex since \w includes digits
+            # 'πÇÇπÇÇ现代汉语通用字българскиعربي1234ö_0_123bafd.apk',
+        ]
+        for name in good:
+            m = fdroidserver.common.APK_NAME_REGEX.match(name)
+            self.assertIsNotNone(m)
+            self.assertIn(m.group(2), ('-123456', '0', '123456'))
+            self.assertIn(m.group(3), ('abcdef0', None))
+
+        bad = [
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_123456_abcdefg.apk',
+            'urzip-_-198274.apk',
+            'urzip-_0_123bafd.apk',
+            'no spaces allowed_123.apk',
+            '0_0.apk',
+            '0_0_abcdef0.apk',
+        ]
+        for name in bad:
+            self.assertIsNone(fdroidserver.common.APK_NAME_REGEX.match(name))
+
+    def test_standard_file_name_regex(self):
+        good = [
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_-123456.mp3',
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_123456.mov',
+            'Document_-123456.pdf',
+            'WTF_0.MOV',
+            'Z0_0.ebk',
+            'a_a_a_a_0.txt',
+            'org.fdroid.fdroid.privileged.ota_123456.zip',
+            'πÇÇπÇÇ现代汉语通用字българскиعربي1234ö_0.jpeg',
+            'a_____0.PNG',
+            # valid, but "_99999" is part of packageName rather than versionCode
+            'a_____99999_123456.zip',
+            'org.fdroid.fdroid_99999_123456.zip',
+        ]
+        for name in good:
+            m = fdroidserver.common.STANDARD_FILE_NAME_REGEX.match(name)
+            self.assertIsNotNone(m)
+            self.assertIn(m.group(2), ('-123456', '0', '123456'))
+
+        bad = [
+            'urzipπÇÇπÇÇ现代汉语通用字българскиعربي1234ö_abcdefg.JPEG',
+            'urzip-_-198274.zip',
+            'urzip-_123bafd.pdf',
+            'no spaces allowed_123.foobar',
+            'a_____0.',
+        ]
+        for name in bad:
+            self.assertIsNone(fdroidserver.common.STANDARD_FILE_NAME_REGEX.match(name))
+
 
 if __name__ == "__main__":
     parser = optparse.OptionParser()
index ec7772422c6ceb900b321194dba9675c694d8581..329213b7a594a8f317f7b04eb20dcdb248b3129c 100644 (file)
@@ -1,4 +1,4 @@
-fake.ota.update_1234.zip 897a92a4ccff4f415f6ba275b2af16d4ecaee60a983b215bddcb9f8964e7a24c 2016-03-10
+fake.ota.update_1234.zip fake.ota.update 2016-03-10
 obb.main.oldversion_1444412523.apk obb.main.oldversion 2013-12-31
 obb.main.twoversions_1101613.apk obb.main.twoversions 2015-10-12
 obb.main.twoversions_1101615.apk obb.main.twoversions 2016-01-01