diff --git a/.gitignore b/.gitignore index 69c27f93..0ad4ccc7 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,6 @@ makebuildserver.config.py /tests/archive/index-v1.jar /tests/repo/index.jar /tests/repo/index-v1.jar +/tests/repo/info.guardianproject.urzip/ /tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk /unsigned/ diff --git a/fdroidserver/build.py b/fdroidserver/build.py index 5b21939b..bf790970 100644 --- a/fdroidserver/build.py +++ b/fdroidserver/build.py @@ -544,7 +544,7 @@ def get_apk_metadata_androguard(apkfile): def get_metadata_from_apk(app, build, apkfile): """get the required metadata from the built APK""" - if common.set_command_in_config('aapt'): + if common.SdkToolsPopen(['aapt', 'version'], output=False): vercode, version, foundid, nativecode = get_apk_metadata_aapt(apkfile) else: vercode, version, foundid, nativecode = get_apk_metadata_androguard(apkfile) diff --git a/fdroidserver/common.py b/fdroidserver/common.py index df90e5f4..cc1df84e 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -1727,7 +1727,7 @@ def isApkAndDebuggable(apkfile, config): if get_file_extension(apkfile) != 'apk': return False - if set_command_in_config('aapt'): + if SdkToolsPopen(['aapt', 'version'], output=False): return get_apk_debuggable_aapt(apkfile) else: return get_apk_debuggable_androguard(apkfile) diff --git a/fdroidserver/index.py b/fdroidserver/index.py index aae2e1b6..6eda4a53 100644 --- a/fdroidserver/index.py +++ b/fdroidserver/index.py @@ -169,7 +169,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict): appslist = [] output['apps'] = appslist - for appid, appdict in apps.items(): + for packageName, appdict in apps.items(): d = collections.OrderedDict() appslist.append(d) for k, v in sorted(appdict.items()): @@ -190,7 +190,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict): elif k == 'CurrentVersion': # TODO make SuggestedVersionName the canonical name k = 'suggestedVersionName' elif k == 'AutoName': - if 'Name' not in apps[appid]: + if 'Name' not in apps[packageName]: d['name'] = v continue else: @@ -201,6 +201,9 @@ def make_v1(apps, packages, repodir, repodict, requestsdict): output['packages'] = output_packages for package in packages: packageName = package['packageName'] + if packageName not in apps: + logging.info('Ignoring package without metadata: ' + package['apkName']) + continue if packageName in output_packages: packagelist = output_packages[packageName] else: diff --git a/fdroidserver/metadata.py b/fdroidserver/metadata.py index c650ddbc..301a2de0 100644 --- a/fdroidserver/metadata.py +++ b/fdroidserver/metadata.py @@ -21,7 +21,7 @@ import json import os import re import glob -import cgi +import html import logging import textwrap import io @@ -492,10 +492,10 @@ class DescriptionFormatter: self.laststate = self.state self.state = self.stNONE - def formatted(self, txt, html): + def formatted(self, txt, htmlbody): res = '' - if html: - txt = cgi.escape(txt) + if htmlbody: + txt = html.escape(txt, quote=False) while True: index = txt.find("''") if index == -1: @@ -503,7 +503,7 @@ class DescriptionFormatter: res += txt[:index] txt = txt[index:] if txt.startswith("'''"): - if html: + if htmlbody: if self.bold: res += '' else: @@ -511,7 +511,7 @@ class DescriptionFormatter: self.bold = not self.bold txt = txt[3:] else: - if html: + if htmlbody: if self.ital: res += '' else: @@ -538,7 +538,7 @@ class DescriptionFormatter: url, urltext = self.linkResolver(url) else: urltext = url - res_html += '' + cgi.escape(urltext) + '' + res_html += '' + html.escape(urltext, quote=False) + '' res_plain += urltext txt = txt[index + 2:] else: @@ -554,7 +554,7 @@ class DescriptionFormatter: url = url[:index2] if url == urltxt: warn_or_exception("Url title is just the URL - use [url]") - res_html += '' + cgi.escape(urltxt) + '' + res_html += '' + html.escape(urltxt, quote=False) + '' res_plain += urltxt if urltxt != url: res_plain += ' (' + url + ')' diff --git a/fdroidserver/update.py b/fdroidserver/update.py index 1cb2fc4e..71277c3e 100644 --- a/fdroidserver/update.py +++ b/fdroidserver/update.py @@ -676,14 +676,14 @@ def insert_localized_app_metadata(apps): must be PNG or JPEG files ending with ".png", ".jpg", or ".jpeg" and must be in the following layout: # TODO replace these docs with link to All_About_Descriptions_Graphics_and_Screenshots - # TODO mention that the 'localized' section is not in metadata.yml, so key names are like Java vars: camelCase with first letter lowercase. + repo/packageName/locale/featureGraphic.png repo/packageName/locale/phoneScreenshots/1.png repo/packageName/locale/phoneScreenshots/2.png The changelog files must be text files named with the versionCode ending with ".txt" and must be in the following layout: - https://github.com/fastlane/fastlane/blob/1.109.0/supply/README.md#changelogs-whats-new + https://github.com/fastlane/fastlane/blob/2.28.7/supply/README.md#changelogs-whats-new repo/packageName/locale/changelogs/12345.txt @@ -701,7 +701,7 @@ def insert_localized_app_metadata(apps): metadata/ folder and the apps' source repos for standard locations of graphic and screenshot files. If it finds them, it will copy them into the repo. The fastlane files follow this pattern: - https://github.com/fastlane/fastlane/blob/1.109.0/supply/README.md#images-and-screenshots + https://github.com/fastlane/fastlane/blob/2.28.7/supply/README.md#images-and-screenshots """ @@ -718,7 +718,6 @@ def insert_localized_app_metadata(apps): logging.debug(packageName + ' does not have app metadata, skipping l18n scan.') continue locale = segments[-1] - destdir = os.path.join('repo', packageName, locale) for f in files: if f == 'full_description.txt': _set_localized_text_entry(apps[packageName], locale, 'description', @@ -737,11 +736,15 @@ def insert_localized_app_metadata(apps): os.path.join(root, f)) continue elif f == str(apps[packageName]['CurrentVersionCode']) + '.txt': - _set_localized_text_entry(apps[packageName], segments[-2], 'whatsNew', + locale = segments[-2] + _set_localized_text_entry(apps[packageName], locale, 'whatsNew', os.path.join(root, f)) continue base, extension = common.get_extension(f) + if locale == 'images': + locale = segments[-2] + destdir = os.path.join('repo', packageName, locale) if base in GRAPHIC_NAMES and extension in ALLOWED_EXTENSIONS: os.makedirs(destdir, mode=0o755, exist_ok=True) logging.debug('copying ' + os.path.join(root, f) + ' ' + destdir) @@ -783,7 +786,7 @@ def insert_localized_app_metadata(apps): graphics[base] = filename elif screenshotdir in SCREENSHOT_DIRS: # there can any number of these per locale - logging.debug('adding ' + base + ':' + f) + logging.debug('adding to ' + screenshotdir + ': ' + f) if screenshotdir not in graphics: graphics[screenshotdir] = [] graphics[screenshotdir].append(filename) @@ -849,12 +852,13 @@ def scan_repo_files(apkcache, repodir, knownapks, use_date_from_file=False): repo_file['versionName'] = shasum # the static ID is the SHA256 unless it is set in the metadata repo_file['packageName'] = shasum - n = name_utf8.split('_') + + 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(name_utf8.split('_')[0]): + and common.is_valid_package_name(n[0]): repo_file['packageName'] = packageName repo_file['versionCode'] = int(versionCode) srcfilename = name + b'_src.tar.gz' @@ -1124,11 +1128,9 @@ def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk): apk['antiFeatures'].add('KnownVuln') try: - if common.set_command_in_config('aapt'): - logging.warning("Using AAPT for metadata") + if SdkToolsPopen(['aapt', 'version'], output=False): scan_apk_aapt(apk, apkfile) else: - logging.warning("Using androguard for metadata") scan_apk_androguard(apk, apkfile) except BuildException: return True, None, False diff --git a/tests/androguard_test.py b/tests/androguard_test.py index 9e5d845a..c708b85f 100644 --- a/tests/androguard_test.py +++ b/tests/androguard_test.py @@ -4,12 +4,8 @@ import inspect import logging import optparse import os -import shutil import sys -import tempfile import unittest -import yaml -from binascii import unhexlify localmodule = os.path.realpath( os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')) @@ -53,9 +49,10 @@ class UpdateTest(unittest.TestCase): fdroidserver.update.options.clean = True fdroidserver.update.options.delete_unknown = True - self.assertTrue(fdroidserver.common.set_command_in_config('aapt')) + self.assertTrue(fdroidserver.common.SdkToolsPopen('aapt')) try: from androguard.core.bytecodes.apk import APK + dir(APK) except ImportError: raise Exception("androguard not installed!") @@ -89,4 +86,4 @@ if __name__ == "__main__": newSuite = unittest.TestSuite() newSuite.addTest(unittest.makeSuite(UpdateTest)) - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tests/metadata/info.guardianproject.urzip/en-US/images/featureGraphic.png b/tests/metadata/info.guardianproject.urzip/en-US/images/featureGraphic.png new file mode 100644 index 00000000..cb6720cb Binary files /dev/null and b/tests/metadata/info.guardianproject.urzip/en-US/images/featureGraphic.png differ diff --git a/tests/metadata/info.guardianproject.urzip/en-US/images/icon.png b/tests/metadata/info.guardianproject.urzip/en-US/images/icon.png new file mode 100644 index 00000000..21439b7b Binary files /dev/null and b/tests/metadata/info.guardianproject.urzip/en-US/images/icon.png differ diff --git a/tests/update.TestCase b/tests/update.TestCase index 4e204ae6..be1a7266 100755 --- a/tests/update.TestCase +++ b/tests/update.TestCase @@ -37,6 +37,8 @@ class UpdateTest(unittest.TestCase): fdroidserver.update.options = fdroidserver.common.options os.chdir(os.path.join(localmodule, 'tests')) + shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True) + apps = dict() for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'): apps[packageName] = dict() @@ -45,17 +47,23 @@ class UpdateTest(unittest.TestCase): apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100 fdroidserver.update.insert_localized_app_metadata(apps) + appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US') + self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png'))) + self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png'))) + self.assertEqual(3, len(apps)) for packageName, app in apps.items(): self.assertTrue('localized' in app) self.assertTrue('en-US' in app['localized']) self.assertEqual(1, len(app['localized'])) if packageName == 'info.guardianproject.urzip': - self.assertEqual(5, len(app['localized']['en-US'])) + self.assertEqual(7, len(app['localized']['en-US'])) self.assertEqual('full description\n', app['localized']['en-US']['description']) self.assertEqual('title\n', app['localized']['en-US']['name']) self.assertEqual('short description\n', app['localized']['en-US']['summary']) self.assertEqual('video\n', app['localized']['en-US']['video']) + self.assertEqual('icon.png', app['localized']['en-US']['icon']) + self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic']) self.assertEqual('100\n', app['localized']['en-US']['whatsNew']) elif packageName == 'org.videolan.vlc': self.assertEqual('icon.png', app['localized']['en-US']['icon']) @@ -244,6 +252,7 @@ class UpdateTest(unittest.TestCase): fdroidserver.update.options = type('', (), {})() fdroidserver.update.options.clean = True + fdroidserver.update.options.rename_apks = False fdroidserver.update.options.delete_unknown = True for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):