/tests/repo/index.jar
/tests/repo/index-v1.jar
/tests/repo/info.guardianproject.urzip/
+/tests/repo/info.guardianproject.checkey/en-US/phoneScreenshots/checkey-phone.png
+/tests/repo/info.guardianproject.checkey/en-US/phoneScreenshots/checkey.png
/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk
/unsigned/
- pip3 install -e .
- cd tests
- ./complete-ci-tests
+
+# Test that the parsing of the .txt format didn't change. The metadata
+# field 'Author Web Site' was added after 0.7.0, so that can't be part
+# of the test.
+metadata_v0:
+ script:
+ - cd tests
+ - cp dump_internal_metadata_format.py dump.py # since this isn't in old commits
+ - git checkout 0.7.0 # or any old commit of your choosing
+ - cd ..
+ - sed -i "s/'Author Email',/'Author Email',\n'Author Web Site',/" fdroidserver/metadata.py
+ - git clone --depth 1 https://gitlab.com/fdroid/fdroiddata
+ - cd fdroiddata
+ - ../tests/dump.py
+ - cd ..
+ - git reset --hard
+ - git checkout master
+ - cd fdroiddata
+ - ../tests/dump.py
+ - sed -i "/AuthorWebSite/d" metadata/dump_*/*.yaml
+ - diff -uw metadata/dump_*
elsif configfile["vm_provider"] == "libvirt"
# use KVM/QEMU if this is running in KVM/QEMU
config.vm.provider :libvirt do |libvirt|
- libvirt.driver = "kvm"
+ libvirt.driver = configfile["hwvirtex"] == "on" ? "kvm" : "qemu"
libvirt.host = "localhost"
libvirt.uri = "qemu:///system"
libvirt.cpus = configfile["cpus"]
opts="-c -v -q -b -i -I -e -w"
lopts="--create-metadata --verbose --quiet --buildreport
--interactive --icons --editor --wiki --pretty --clean --delete-unknown
- --nosign --use-date-from-apk"
+ --nosign --rename-apks --use-date-from-apk"
case "${prev}" in
-e|--editor)
_filedir
# 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')
class KnownApks:
+ """permanent store of existing APKs with the date they were added
+
+ This is currently the only way to permanently store the "updated"
+ date of APKs.
+ """
def __init__(self):
self.path = os.path.join('stats', 'known_apks.txt')
for line in sorted(lst, key=natural_key):
f.write(line + '\n')
- def recordapk(self, apk, app, default_date=None):
+ def recordapk(self, apkName, app, default_date=None):
'''
Record an apk (if it's new, otherwise does nothing)
Returns the date it was added as a datetime instance
'''
- if apk not in self.apks:
+ if apkName not in self.apks:
if default_date is None:
default_date = datetime.utcnow()
- self.apks[apk] = (app, default_date)
+ self.apks[apkName] = (app, default_date)
self.changed = True
- _, added = self.apks[apk]
+ _, added = self.apks[apkName]
return added
# Look up information - given the 'apkname', returns (app id, date added/None).
import binascii
import os
+import re
import shutil
import urllib.request
from argparse import ArgumentParser
req = urllib.request.urlopen(url)
if req.getcode() != 200:
return (None, 'Unable to get ' + url + ' - return code ' + str(req.getcode()))
- page = req.read()
+ page = req.read().decode(req.headers.get_content_charset())
# Works for BitBucket
+ m = re.search('data-fetch-url="(.*)"', page)
+ if m is not None:
+ repo = m.group(1)
+
+ if repo.endswith('.git'):
+ return ('git', repo)
+
+ return ('hg', repo)
+
+ # Works for BitBucket (obsolete)
index = page.find('hg clone')
if index != -1:
repotype = 'hg'
repo = repo.split('"')[0]
return (repotype, repo)
- # Works for BitBucket
+ # Works for BitBucket (obsolete)
index = page.find('git clone')
if index != -1:
repotype = 'git'
# Get a list of the apks for this app...
apklist = []
+ versionCodes = []
for apk in apks:
if apk['packageName'] == appid:
- apklist.append(apk)
+ if apk['versionCode'] not in versionCodes:
+ apklist.append(apk)
+ versionCodes.append(apk['versionCode'])
if len(apklist) == 0:
continue
# Check for duplicates - they will make the client unhappy...
for i in range(len(apklist) - 1):
- if apklist[i]['versionCode'] == apklist[i + 1]['versionCode']:
- raise FDroidException("duplicate versions: '%s' - '%s'" % (
- apklist[i]['apkName'], apklist[i + 1]['apkName']))
+ first = apklist[i]
+ second = apklist[i + 1]
+ if first['versionCode'] == second['versionCode'] \
+ and first['sig'] == second['sig']:
+ if first['hash'] == second['hash']:
+ raise FDroidException('"{0}/{1}" and "{0}/{2}" are exact duplicates!'.format(
+ repodir, first['apkName'], second['apkName']))
+ else:
+ raise FDroidException('duplicates: "{0}/{1}" - "{0}/{2}"'.format(
+ repodir, first['apkName'], second['apkName']))
current_version_code = 0
current_version_file = None
and repodir == 'repo': # only create these
namefield = common.config['current_version_name_source']
sanitized_name = re.sub(b'''[ '"&%?+=/]''', b'', app.get(namefield).encode('utf-8'))
- apklinkname = sanitized_name + b'.apk'
+ apklinkname = sanitized_name + os.path.splitext(current_version_file)[1].encode('utf-8')
current_version_path = os.path.join(repodir, current_version_file).encode('utf-8', 'surrogateescape')
if os.path.islink(apklinkname):
os.remove(apklinkname)
forbid_shortener('goo.gl'),
forbid_shortener('t.co'),
forbid_shortener('ur1.ca'),
+ forbid_shortener('is.gd'),
+ forbid_shortener('bit.ly'),
+ forbid_shortener('tiny.cc'),
+ forbid_shortener('tinyurl.com'),
]
http_checks = https_enforcings + http_url_shorteners + [
(re.compile(r'.*\s$'),
"Unnecessary trailing space"),
],
- 'License': [
- (re.compile(r'^(|None|Unknown)$'),
- "No license specified"),
- ],
'Summary': [
- (re.compile(r'^$'),
- "Summary yet to be filled"),
(re.compile(r'.*\b(free software|open source)\b.*', re.IGNORECASE),
"No need to specify that the app is Free Software"),
(re.compile(r'.*((your|for).*android|android.*(app|device|client|port|version))', re.IGNORECASE),
"Unnecessary trailing space"),
],
'Description': [
- (re.compile(r'^No description available$'),
- "Description yet to be filled"),
(re.compile(r'\s*[*#][^ .]'),
"Invalid bulleted list"),
(re.compile(r'^\s'),
],
}
+locale_pattern = re.compile(r'^[a-z]{2,3}(-[A-Z][A-Z])?$')
+
def check_regexes(app):
for f, checks in regex_checks.items():
files = set()
for name in os.listdir(dir_path):
path = os.path.join(dir_path, name)
- if not os.path.isfile(path):
+ if not (os.path.isfile(path) or name == 'signatures' or locale_pattern.match(name)):
yield "Found non-file at %s" % path
continue
files.add(name)
- used = set()
+ used = {'signatures', }
for build in app.builds:
for fname in build.patch:
if fname not in files:
used.add(fname)
for name in files.difference(used):
+ if locale_pattern.match(name):
+ continue
yield "Unused file at %s" % os.path.join(dir_path, name)
yield "Run rewritemeta to fix formatting"
+def check_license_tag(app):
+ '''Ensure all license tags are in https://spdx.org/license-list'''
+ if app.License.rstrip('+') not in SPDX:
+ yield 'Invalid license tag "%s"! Use only tags from https://spdx.org/license-list' \
+ % (app.License)
+
+
def check_extlib_dir(apps):
dir_path = os.path.join('build', 'extlib')
files = set()
check_builds,
check_files_dir,
check_format,
+ check_license_tag,
]
for check_func in app_check_funcs:
sys.exit(1)
+# A compiled, public domain list of official SPDX license tags from:
+# https://github.com/sindresorhus/spdx-license-list/blob/v3.0.1/spdx-simple.json
+# The deprecated license tags have been removed from the list, they are at the
+# bottom, starting after the last license tags that start with Z.
+# This is at the bottom, since its a long list of data
+SPDX = [
+ "PublicDomain", # an F-Droid addition, until we can enforce a better option
+ "Glide",
+ "Abstyles",
+ "AFL-1.1",
+ "AFL-1.2",
+ "AFL-2.0",
+ "AFL-2.1",
+ "AFL-3.0",
+ "AMPAS",
+ "APL-1.0",
+ "Adobe-Glyph",
+ "APAFML",
+ "Adobe-2006",
+ "AGPL-1.0",
+ "Afmparse",
+ "Aladdin",
+ "ADSL",
+ "AMDPLPA",
+ "ANTLR-PD",
+ "Apache-1.0",
+ "Apache-1.1",
+ "Apache-2.0",
+ "AML",
+ "APSL-1.0",
+ "APSL-1.1",
+ "APSL-1.2",
+ "APSL-2.0",
+ "Artistic-1.0",
+ "Artistic-1.0-Perl",
+ "Artistic-1.0-cl8",
+ "Artistic-2.0",
+ "AAL",
+ "Bahyph",
+ "Barr",
+ "Beerware",
+ "BitTorrent-1.0",
+ "BitTorrent-1.1",
+ "BSL-1.0",
+ "Borceux",
+ "BSD-2-Clause",
+ "BSD-2-Clause-FreeBSD",
+ "BSD-2-Clause-NetBSD",
+ "BSD-3-Clause",
+ "BSD-3-Clause-Clear",
+ "BSD-3-Clause-No-Nuclear-License",
+ "BSD-3-Clause-No-Nuclear-License-2014",
+ "BSD-3-Clause-No-Nuclear-Warranty",
+ "BSD-4-Clause",
+ "BSD-Protection",
+ "BSD-Source-Code",
+ "BSD-3-Clause-Attribution",
+ "0BSD",
+ "BSD-4-Clause-UC",
+ "bzip2-1.0.5",
+ "bzip2-1.0.6",
+ "Caldera",
+ "CECILL-1.0",
+ "CECILL-1.1",
+ "CECILL-2.0",
+ "CECILL-2.1",
+ "CECILL-B",
+ "CECILL-C",
+ "ClArtistic",
+ "MIT-CMU",
+ "CNRI-Jython",
+ "CNRI-Python",
+ "CNRI-Python-GPL-Compatible",
+ "CPOL-1.02",
+ "CDDL-1.0",
+ "CDDL-1.1",
+ "CPAL-1.0",
+ "CPL-1.0",
+ "CATOSL-1.1",
+ "Condor-1.1",
+ "CC-BY-1.0",
+ "CC-BY-2.0",
+ "CC-BY-2.5",
+ "CC-BY-3.0",
+ "CC-BY-4.0",
+ "CC-BY-ND-1.0",
+ "CC-BY-ND-2.0",
+ "CC-BY-ND-2.5",
+ "CC-BY-ND-3.0",
+ "CC-BY-ND-4.0",
+ "CC-BY-NC-1.0",
+ "CC-BY-NC-2.0",
+ "CC-BY-NC-2.5",
+ "CC-BY-NC-3.0",
+ "CC-BY-NC-4.0",
+ "CC-BY-NC-ND-1.0",
+ "CC-BY-NC-ND-2.0",
+ "CC-BY-NC-ND-2.5",
+ "CC-BY-NC-ND-3.0",
+ "CC-BY-NC-ND-4.0",
+ "CC-BY-NC-SA-1.0",
+ "CC-BY-NC-SA-2.0",
+ "CC-BY-NC-SA-2.5",
+ "CC-BY-NC-SA-3.0",
+ "CC-BY-NC-SA-4.0",
+ "CC-BY-SA-1.0",
+ "CC-BY-SA-2.0",
+ "CC-BY-SA-2.5",
+ "CC-BY-SA-3.0",
+ "CC-BY-SA-4.0",
+ "CC0-1.0",
+ "Crossword",
+ "CrystalStacker",
+ "CUA-OPL-1.0",
+ "Cube",
+ "curl",
+ "D-FSL-1.0",
+ "diffmark",
+ "WTFPL",
+ "DOC",
+ "Dotseqn",
+ "DSDP",
+ "dvipdfm",
+ "EPL-1.0",
+ "ECL-1.0",
+ "ECL-2.0",
+ "eGenix",
+ "EFL-1.0",
+ "EFL-2.0",
+ "MIT-advertising",
+ "MIT-enna",
+ "Entessa",
+ "ErlPL-1.1",
+ "EUDatagrid",
+ "EUPL-1.0",
+ "EUPL-1.1",
+ "Eurosym",
+ "Fair",
+ "MIT-feh",
+ "Frameworx-1.0",
+ "FreeImage",
+ "FTL",
+ "FSFAP",
+ "FSFUL",
+ "FSFULLR",
+ "Giftware",
+ "GL2PS",
+ "Glulxe",
+ "AGPL-3.0",
+ "GFDL-1.1",
+ "GFDL-1.2",
+ "GFDL-1.3",
+ "GPL-1.0",
+ "GPL-2.0",
+ "GPL-3.0",
+ "LGPL-2.1",
+ "LGPL-3.0",
+ "LGPL-2.0",
+ "gnuplot",
+ "gSOAP-1.3b",
+ "HaskellReport",
+ "HPND",
+ "IBM-pibs",
+ "IPL-1.0",
+ "ICU",
+ "ImageMagick",
+ "iMatix",
+ "Imlib2",
+ "IJG",
+ "Info-ZIP",
+ "Intel-ACPI",
+ "Intel",
+ "Interbase-1.0",
+ "IPA",
+ "ISC",
+ "JasPer-2.0",
+ "JSON",
+ "LPPL-1.0",
+ "LPPL-1.1",
+ "LPPL-1.2",
+ "LPPL-1.3a",
+ "LPPL-1.3c",
+ "Latex2e",
+ "BSD-3-Clause-LBNL",
+ "Leptonica",
+ "LGPLLR",
+ "Libpng",
+ "libtiff",
+ "LAL-1.2",
+ "LAL-1.3",
+ "LiLiQ-P-1.1",
+ "LiLiQ-Rplus-1.1",
+ "LiLiQ-R-1.1",
+ "LPL-1.02",
+ "LPL-1.0",
+ "MakeIndex",
+ "MTLL",
+ "MS-PL",
+ "MS-RL",
+ "MirOS",
+ "MITNFA",
+ "MIT",
+ "Motosoto",
+ "MPL-1.0",
+ "MPL-1.1",
+ "MPL-2.0",
+ "MPL-2.0-no-copyleft-exception",
+ "mpich2",
+ "Multics",
+ "Mup",
+ "NASA-1.3",
+ "Naumen",
+ "NBPL-1.0",
+ "Net-SNMP",
+ "NetCDF",
+ "NGPL",
+ "NOSL",
+ "NPL-1.0",
+ "NPL-1.1",
+ "Newsletr",
+ "NLPL",
+ "Nokia",
+ "NPOSL-3.0",
+ "NLOD-1.0",
+ "Noweb",
+ "NRL",
+ "NTP",
+ "Nunit",
+ "OCLC-2.0",
+ "ODbL-1.0",
+ "PDDL-1.0",
+ "OCCT-PL",
+ "OGTSL",
+ "OLDAP-2.2.2",
+ "OLDAP-1.1",
+ "OLDAP-1.2",
+ "OLDAP-1.3",
+ "OLDAP-1.4",
+ "OLDAP-2.0",
+ "OLDAP-2.0.1",
+ "OLDAP-2.1",
+ "OLDAP-2.2",
+ "OLDAP-2.2.1",
+ "OLDAP-2.3",
+ "OLDAP-2.4",
+ "OLDAP-2.5",
+ "OLDAP-2.6",
+ "OLDAP-2.7",
+ "OLDAP-2.8",
+ "OML",
+ "OPL-1.0",
+ "OSL-1.0",
+ "OSL-1.1",
+ "OSL-2.0",
+ "OSL-2.1",
+ "OSL-3.0",
+ "OpenSSL",
+ "OSET-PL-2.1",
+ "PHP-3.0",
+ "PHP-3.01",
+ "Plexus",
+ "PostgreSQL",
+ "psfrag",
+ "psutils",
+ "Python-2.0",
+ "QPL-1.0",
+ "Qhull",
+ "Rdisc",
+ "RPSL-1.0",
+ "RPL-1.1",
+ "RPL-1.5",
+ "RHeCos-1.1",
+ "RSCPL",
+ "RSA-MD",
+ "Ruby",
+ "SAX-PD",
+ "Saxpath",
+ "SCEA",
+ "SWL",
+ "SMPPL",
+ "Sendmail",
+ "SGI-B-1.0",
+ "SGI-B-1.1",
+ "SGI-B-2.0",
+ "OFL-1.0",
+ "OFL-1.1",
+ "SimPL-2.0",
+ "Sleepycat",
+ "SNIA",
+ "Spencer-86",
+ "Spencer-94",
+ "Spencer-99",
+ "SMLNJ",
+ "SugarCRM-1.1.3",
+ "SISSL",
+ "SISSL-1.2",
+ "SPL-1.0",
+ "Watcom-1.0",
+ "TCL",
+ "TCP-wrappers",
+ "Unlicense",
+ "TMate",
+ "TORQUE-1.1",
+ "TOSL",
+ "Unicode-DFS-2015",
+ "Unicode-DFS-2016",
+ "Unicode-TOU",
+ "UPL-1.0",
+ "NCSA",
+ "Vim",
+ "VOSTROM",
+ "VSL-1.0",
+ "W3C-20150513",
+ "W3C-19980720",
+ "W3C",
+ "Wsuipa",
+ "Xnet",
+ "X11",
+ "Xerox",
+ "XFree86-1.1",
+ "xinetd",
+ "xpp",
+ "XSkat",
+ "YPL-1.0",
+ "YPL-1.1",
+ "Zed",
+ "Zend-2.0",
+ "Zimbra-1.3",
+ "Zimbra-1.4",
+ "Zlib",
+ "zlib-acknowledgement",
+ "ZPL-1.1",
+ "ZPL-2.0",
+ "ZPL-2.1",
+]
+
if __name__ == "__main__":
main()
mf.write('\n')
w_field_nonempty('Name')
w_field_nonempty('Auto Name')
- w_field_always('Summary')
- w_field_always('Description', description_txt(app.Description))
+ w_field_nonempty('Summary')
+ w_field_nonempty('Description', description_txt(app.Description))
mf.write('\n')
if app.RequiresRoot:
w_field_always('Requires Root', 'yes')
if an error occurred.
"""
- # verify the jar signature is correct
- if not common.verify_apk_signature(apkpath):
- return None
-
with zipfile.ZipFile(apkpath, 'r') as apk:
certs = [n for n in apk.namelist() if common.CERT_PATH_REGEX.match(n)]
"""
sourcedirs = glob.glob(os.path.join('build', '[A-Za-z]*', 'fastlane', 'metadata', 'android', '[a-z][a-z]*'))
+ sourcedirs += glob.glob(os.path.join('build', '[A-Za-z]*', 'metadata', '[a-z][a-z]*'))
sourcedirs += glob.glob(os.path.join('metadata', '[A-Za-z]*', '[a-z][a-z]*'))
- for d in sorted(sourcedirs):
- if not os.path.isdir(d):
+ for srcd in sorted(sourcedirs):
+ if not os.path.isdir(srcd):
continue
- for root, dirs, files in os.walk(d):
+ for root, dirs, files in os.walk(srcd):
segments = root.split('/')
packageName = segments[1]
if packageName not in 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':
+ if f in ('description.txt', 'full_description.txt'):
_set_localized_text_entry(apps[packageName], locale, 'description',
os.path.join(root, f))
continue
- elif f == 'short_description.txt':
+ elif f in ('summary.txt', 'short_description.txt'):
_set_localized_text_entry(apps[packageName], locale, 'summary',
os.path.join(root, f))
continue
- elif f == 'title.txt':
+ elif f in ('name.txt', 'title.txt'):
_set_localized_text_entry(apps[packageName], locale, 'name',
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)
+ 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)
if not usecache:
logging.debug("Processing " + name_utf8)
repo_file = collections.OrderedDict()
+ repo_file['name'] = os.path.splitext(name_utf8)[0]
# TODO rename apkname globally to something more generic
- repo_file['name'] = name_utf8
repo_file['apkName'] = name_utf8
repo_file['hash'] = shasum
repo_file['hashType'] = 'sha256'
# 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')
"""
if ' ' in apkfilename:
- logging.critical("Spaces in filenames are not allowed.")
- return True, None, False
+ if options.rename_apks:
+ newfilename = apkfilename.replace(' ', '_')
+ os.rename(os.path.join(repodir, apkfilename),
+ os.path.join(repodir, newfilename))
+ apkfilename = newfilename
+ else:
+ logging.critical("Spaces in filenames are not allowed.")
+ return True, None, False
apkfile = os.path.join(repodir, apkfilename)
shasum = sha256sum(apkfile)
if not usecache:
logging.debug("Processing " + apkfilename)
apk = {}
- apk['apkName'] = apkfilename
apk['hash'] = shasum
apk['hashType'] = 'sha256'
- srcfilename = apkfilename[:-4] + "_src.tar.gz"
- if os.path.exists(os.path.join(repodir, srcfilename)):
- apk['srcname'] = srcfilename
- apk['size'] = os.path.getsize(apkfile)
apk['uses-permission'] = []
apk['uses-permission-sdk-23'] = []
apk['features'] = []
apk['icons_src'] = {}
apk['icons'] = {}
apk['antiFeatures'] = set()
- if has_old_openssl(apkfile):
- apk['antiFeatures'].add('KnownVuln')
try:
if SdkToolsPopen(['aapt', 'version'], output=False):
logging.critical("Failed to get apk signature")
return True, None, False
+ if options.rename_apks:
+ n = apk['packageName'] + '_' + str(apk['versionCode']) + '.apk'
+ std_short_name = os.path.join(repodir, n)
+ if apkfile != std_short_name:
+ if os.path.exists(std_short_name):
+ std_long_name = std_short_name.replace('.apk', '_' + apk['sig'][:7] + '.apk')
+ if apkfile != std_long_name:
+ if os.path.exists(std_long_name):
+ dupdir = os.path.join('duplicates', repodir)
+ if not os.path.isdir(dupdir):
+ os.makedirs(dupdir, exist_ok=True)
+ dupfile = os.path.join('duplicates', std_long_name)
+ logging.warning('Moving duplicate ' + std_long_name + ' to ' + dupfile)
+ os.rename(apkfile, dupfile)
+ return True, None, False
+ else:
+ os.rename(apkfile, std_long_name)
+ apkfile = std_long_name
+ else:
+ os.rename(apkfile, std_short_name)
+ apkfile = std_short_name
+ apkfilename = apkfile[len(repodir) + 1:]
+
+ apk['apkName'] = apkfilename
+ srcfilename = apkfilename[:-4] + "_src.tar.gz"
+ if os.path.exists(os.path.join(repodir, srcfilename)):
+ apk['srcname'] = srcfilename
+ apk['size'] = os.path.getsize(apkfile)
+
+ # verify the jar signature is correct
+ if not common.verify_apk_signature(apkfile):
+ return True, None, False
+
+ if has_old_openssl(apkfile):
+ apk['antiFeatures'].add('KnownVuln')
+
apkzip = zipfile.ZipFile(apkfile, 'r')
# if an APK has files newer than the system time, suggest updating
help="When configured for signed indexes, create only unsigned indexes at this stage")
parser.add_argument("--use-date-from-apk", action="store_true", default=False,
help="Use date from apk instead of current time for newly added apks")
+ parser.add_argument("--rename-apks", action="store_true", default=False,
+ help="Rename APK files that do not match package.name_123.apk")
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
resize_all_icons(repodirs)
sys.exit(0)
+ if options.rename_apks:
+ options.clean = True
+
# check that icons exist now, rather than fail at the end of `fdroid update`
for k in ['repo_icon', 'archive_icon']:
if k in config:
# point to the Vagrant/VirtualBox configs created by reproducible_setup_fdroid_build_environment.sh
# these variables are actually set in fdroidserver/jenkins-build-makebuildserver
-export SETUP_WORKSPACE=$(dirname $WORKSPACE)/fdroid/fdroidserver
+export SETUP_WORKSPACE=$(dirname $WORKSPACE)/reproducible_setup_fdroid_build_environment/fdroidserver
export XDG_CONFIG_HOME=$SETUP_WORKSPACE
export VBOX_USER_HOME=$SETUP_WORKSPACE/VirtualBox
export VAGRANT_HOME=$SETUP_WORKSPACE/vagrant.d
git remote update -p
git checkout master
git reset --hard origin/master
+ # no don't `git clean` here, it'll wipe the APKs in unsigned/
else
git clone https://gitlab.com/fdroid/fdroiddata.git fdroiddata
cd fdroiddata
git remote update -p
git checkout master
git reset --hard origin/master
+ git clean -fdx
cd ..
else
git clone --depth 1 https://gitlab.com/fdroid/fdroiddata.git fdroiddata
--- /dev/null
+fdroid
+fdroidserver/btlog.py
+fdroidserver/build.py
+fdroidserver/checkupdates.py
+fdroidserver/common.py
+fdroidserver/dscanner.py
+fdroidserver/import.py
+fdroidserver/init.py
+fdroidserver/install.py
+fdroidserver/lint.py
+fdroidserver/metadata.py
+fdroidserver/publish.py
+fdroidserver/rewritemeta.py
+fdroidserver/scanner.py
+fdroidserver/server.py
+fdroidserver/stats.py
+fdroidserver/update.py
+fdroidserver/verify.py
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-06-01 17:23+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../fdroid:34
+msgid "Build a package from source"
+msgstr ""
+
+#: ../fdroid:35
+msgid "Quickly start a new repository"
+msgstr ""
+
+#: ../fdroid:36
+msgid "Sign and place packages in the repo"
+msgstr ""
+
+#: ../fdroid:37
+msgid "Add gpg signatures for packages in repo"
+msgstr ""
+
+#: ../fdroid:38
+msgid "Update repo information for new packages"
+msgstr ""
+
+#: ../fdroid:39
+msgid "Verify the integrity of downloaded packages"
+msgstr ""
+
+#: ../fdroid:40
+msgid "Check for updates to applications"
+msgstr ""
+
+#: ../fdroid:41
+msgid "Add a new application from its source code"
+msgstr ""
+
+#: ../fdroid:42
+msgid "Install built packages on devices"
+msgstr ""
+
+#: ../fdroid:43
+msgid "Read all the metadata files and exit"
+msgstr ""
+
+#: ../fdroid:44
+msgid "Rewrite all the metadata files"
+msgstr ""
+
+#: ../fdroid:45
+msgid "Warn about possible metadata errors"
+msgstr ""
+
+#: ../fdroid:46
+msgid "Scan the source code of a package"
+msgstr ""
+
+#: ../fdroid:47
+msgid "Dynamically scan APKs post build"
+msgstr ""
+
+#: ../fdroid:48
+msgid "Update the stats of the repo"
+msgstr ""
+
+#: ../fdroid:49
+msgid "Interact with the repo HTTP server"
+msgstr ""
+
+#: ../fdroid:50
+msgid "Sign indexes created using update --nosign"
+msgstr ""
+
+#: ../fdroid:51
+msgid "Update the binary transparency log for a URL"
+msgstr ""
+
+#: ../fdroid:56
+msgid "usage: fdroid [-h|--help|--version] <command> [<args>]"
+msgstr ""
+
+#: ../fdroid:58
+msgid "Valid commands are:"
+msgstr ""
+
+#: ../fdroid:104
+#, c-format
+msgid "Command '%s' not recognised.\n"
+msgstr ""
+
+#: ../fdroid:150
+msgid "Unknown exception found!"
+msgstr ""
+
+#: ../fdroidserver/btlog.py:154
+msgid "Path to the git repo to use as the log"
+msgstr ""
+
+#: ../fdroidserver/btlog.py:156
+msgid "The base URL for the repo to log (default: https://f-droid.org)"
+msgstr ""
+
+#: ../fdroidserver/btlog.py:158
+msgid "Push the log to this git remote repository"
+msgstr ""
+
+#: ../fdroidserver/build.py:875 ../fdroidserver/install.py:52
+#: ../fdroidserver/publish.py:45 ../fdroidserver/scanner.py:255
+#: ../fdroidserver/verify.py:41
+msgid "app-id with optional versionCode in the form APPID[:VERCODE]"
+msgstr ""
+
+#: ../fdroidserver/build.py:877
+msgid "Build only the latest version of each package"
+msgstr ""
+
+#: ../fdroidserver/build.py:879
+msgid "Make the build stop on exceptions"
+msgstr ""
+
+#: ../fdroidserver/build.py:881
+msgid ""
+"Test mode - put output in the tmp directory only, and always build, even if "
+"the output already exists."
+msgstr ""
+
+#: ../fdroidserver/build.py:883
+msgid "Use build server"
+msgstr ""
+
+#: ../fdroidserver/build.py:885
+msgid ""
+"Reset and create a brand new build server, even if the existing one appears "
+"to be ok."
+msgstr ""
+
+#: ../fdroidserver/build.py:887
+msgid "Specify that we're running on the build server"
+msgstr ""
+
+#: ../fdroidserver/build.py:889
+msgid "Skip scanning the source code for binaries and other problems"
+msgstr ""
+
+#: ../fdroidserver/build.py:891
+msgid "Setup an emulator, install the apk on it and perform a drozer scan"
+msgstr ""
+
+#: ../fdroidserver/build.py:893
+msgid "Don't create a source tarball, useful when testing a build"
+msgstr ""
+
+#: ../fdroidserver/build.py:895
+msgid ""
+"Don't refresh the repository, useful when testing a build with no internet "
+"connection"
+msgstr ""
+
+#: ../fdroidserver/build.py:897
+msgid ""
+"Force build of disabled apps, and carries on regardless of scan problems. "
+"Only allowed in test mode."
+msgstr ""
+
+#: ../fdroidserver/build.py:899
+msgid "Build all applications available"
+msgstr ""
+
+#: ../fdroidserver/build.py:901 ../fdroidserver/update.py:1519
+msgid "Update the wiki"
+msgstr ""
+
+#: ../fdroidserver/checkupdates.py:513
+msgid "app-id to check for updates"
+msgstr ""
+
+#: ../fdroidserver/checkupdates.py:515
+msgid "Process auto-updates"
+msgstr ""
+
+#: ../fdroidserver/checkupdates.py:517
+msgid "Only process apps with auto-updates"
+msgstr ""
+
+#: ../fdroidserver/checkupdates.py:519
+msgid "Commit changes"
+msgstr ""
+
+#: ../fdroidserver/checkupdates.py:521
+msgid "Only print differences with the Play Store"
+msgstr ""
+
+#: ../fdroidserver/common.py:124
+msgid "Spew out even more information than normal"
+msgstr ""
+
+#: ../fdroidserver/common.py:126
+msgid "Restrict output to warnings and errors"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:410
+msgid "app-id with optional versioncode in the form APPID[:VERCODE]"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:413
+msgid "Scan only the latest version of each package"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:416
+msgid "Clean after all scans have finished"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:419
+msgid "Clean before the scans start and rebuild the container"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:422
+msgid "Clean up all containers and then exit"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:425
+msgid "Prepare drozer to run a scan"
+msgstr ""
+
+#: ../fdroidserver/dscanner.py:428
+msgid "Override path for repo APKs (default: ./repo)"
+msgstr ""
+
+#: ../fdroidserver/import.py:193
+msgid "Project URL to import from."
+msgstr ""
+
+#: ../fdroidserver/import.py:195
+msgid "Path to main android project subdirectory, if not in root."
+msgstr ""
+
+#: ../fdroidserver/import.py:197
+msgid "Comma separated list of categories."
+msgstr ""
+
+#: ../fdroidserver/import.py:199
+msgid "Overall license of the project."
+msgstr ""
+
+#: ../fdroidserver/import.py:201
+msgid ""
+"Allows a different revision (or git branch) to be specified for the initial "
+"import"
+msgstr ""
+
+#: ../fdroidserver/init.py:56
+msgid "X.509 'Distiguished Name' used when generating keys"
+msgstr ""
+
+#: ../fdroidserver/init.py:58
+msgid "Path to the keystore for the repo signing key"
+msgstr ""
+
+#: ../fdroidserver/init.py:60
+msgid "Alias of the repo signing key in the keystore"
+msgstr ""
+
+#: ../fdroidserver/init.py:62
+msgid "Path to the Android SDK (sometimes set in ANDROID_HOME)"
+msgstr ""
+
+#: ../fdroidserver/init.py:64
+msgid "Do not prompt for Android SDK path, just fail"
+msgstr ""
+
+#: ../fdroidserver/install.py:54
+msgid "Install all signed applications available"
+msgstr ""
+
+#: ../fdroidserver/lint.py:393
+msgid "Also warn about formatting issues, like rewritemeta -l"
+msgstr ""
+
+#: ../fdroidserver/lint.py:394 ../fdroidserver/rewritemeta.py:57
+msgid "app-id in the form APPID"
+msgstr ""
+
+#: ../fdroidserver/metadata.py:1337
+msgid "force errors to be warnings, or ignore"
+msgstr ""
+
+#: ../fdroidserver/rewritemeta.py:54
+msgid "List files that would be reformatted"
+msgstr ""
+
+#: ../fdroidserver/rewritemeta.py:56
+msgid "Rewrite to a specific format: "
+msgstr ""
+
+#: ../fdroidserver/server.py:547
+msgid "command to execute, either 'init' or 'update'"
+msgstr ""
+
+#: ../fdroidserver/server.py:549
+msgid "Specify an identity file to provide to SSH for rsyncing"
+msgstr ""
+
+#: ../fdroidserver/server.py:551
+msgid "Specify a local folder to sync the repo to"
+msgstr ""
+
+#: ../fdroidserver/server.py:553
+msgid "Don't use rsync checksums"
+msgstr ""
+
+#: ../fdroidserver/stats.py:64
+msgid "Download logs we don't have"
+msgstr ""
+
+#: ../fdroidserver/stats.py:66
+msgid "Recalculate aggregate stats - use when changes "
+msgstr ""
+
+#: ../fdroidserver/stats.py:69
+msgid "Don't do anything logs-related"
+msgstr ""
+
+#: ../fdroidserver/update.py:1504
+msgid "Create a repo signing key in a keystore"
+msgstr ""
+
+#: ../fdroidserver/update.py:1506
+msgid "Create skeleton metadata files that are missing"
+msgstr ""
+
+#: ../fdroidserver/update.py:1508
+msgid "Delete APKs and/or OBBs without metadata from the repo"
+msgstr ""
+
+#: ../fdroidserver/update.py:1510
+msgid "Report on build data status"
+msgstr ""
+
+#: ../fdroidserver/update.py:1512
+msgid "Interactively ask about things that need updating."
+msgstr ""
+
+#: ../fdroidserver/update.py:1514
+msgid "Resize all the icons exceeding the max pixel size and exit"
+msgstr ""
+
+#: ../fdroidserver/update.py:1516
+#, c-format
+msgid "Specify editor to use in interactive mode. Default %s"
+msgstr ""
+
+#: ../fdroidserver/update.py:1521
+msgid "Produce human-readable index.xml"
+msgstr ""
+
+#: ../fdroidserver/update.py:1523
+msgid "Clean update - don't uses caches, reprocess all apks"
+msgstr ""
+
+#: ../fdroidserver/update.py:1525
+msgid ""
+"When configured for signed indexes, create only unsigned indexes at this "
+"stage"
+msgstr ""
+
+#: ../fdroidserver/update.py:1527
+msgid "Use date from apk instead of current time for newly added apks"
+msgstr ""
+
+#: ../fdroidserver/update.py:1529
+msgid "Rename APK files that do not match package.name_123.apk"
+msgstr ""
shutil.rmtree(aptcachepartial)
cachefiles = [
- ('https://dl.google.com/android/repository/tools_r25.2.3-linux.zip',
- '1b35bcb94e9a686dff6460c8bca903aa0281c6696001067f34ec00093145b560'),
+ ('https://dl.google.com/android/repository/tools_r25.2.5-linux.zip',
+ '577516819c8b5fae680f049d39014ff1ba4af870b687cab10595783e6f22d33e'),
('https://dl.google.com/android/repository/android_m2repository_r47.zip',
'a3f91808dce50c1717737de90c18479ed3a78b147e06985247d138e7ab5123d0'),
('https://dl.google.com/android/repository/android-1.5_r04-linux.zip',
'f268f5945c6ece7ea95c1c252067280854d2a20da924e22ae4720287df8bdbc9'),
('https://dl.google.com/android/repository/platform-25_r01.zip',
'da519dc3e07b8cb879265c94f798262c1f90791dfaa8b745d34883891378438e'),
+ ('https://dl.google.com/android/repository/platform-26_r01.zip',
+ '44e7eca5923320db1abb422aa7a3d0ac9ee199a379af6f5c7603e714d7717561'),
('https://dl.google.com/android/repository/build-tools_r17-linux.zip',
'4c8444972343a19045236f6924bd7f12046287c70dace96ab88b2159c8ec0e74'),
('https://dl.google.com/android/repository/build-tools_r18.0.1-linux.zip',
'671b4e00f5b986c7355507c7024b725a4b4cadf11ca61fa5b1334ec6ea57d94f'),
('https://dl.google.com/android/repository/build-tools_r25.0.2-linux.zip',
'1d7ac9b6def16fb0254ec23c135c02dd9f6908073352a20315a017e4b2a904b0'),
+ ('https://dl.google.com/android/repository/build-tools_r25.0.3-linux.zip',
+ '152c1b187947edd10c65af8b279d40321ecc106106323e53df3608e578042d65'),
+ ('https://dl.google.com/android/repository/build-tools_r26-linux.zip',
+ '7422682f92fb471d4aad4c053c9982a9a623377f9d5e4de7a73cd44ebf2f3c61'),
# the binaries that Google uses are here:
# https://android.googlesource.com/platform/tools/external/gradle/+/studio-1.5/
('https://services.gradle.org/distributions/gradle-1.4-bin.zip',
'eafae2d614e5475a3bcfd7c5f201db5b963cc1290ee3e8ae791ff0c66757781e'),
('https://dl.google.com/android/repository/android-ndk-r13b-linux-x86_64.zip',
'3524d7f8fca6dc0d8e7073a7ab7f76888780a22841a6641927123146c3ffd29c'),
- ('https://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip',
- '3e622c2c9943964ea44cd56317d0769ed4c811bb4b40dc45b1f6965e4db9aa44'),
+ ('https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip',
+ '0ecc2017802924cf81fffc0f51d342e3e69de6343da892ac9fa1cd79bc106024'),
('https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-linux-x64-android-5.7.0.run',
'f7e55b7970e59bdaabb88cb7afc12e9061e933992bda2f076f52600358644586'),
]
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()
Donate: http://sufficientlysecure.org/index.php/adaway
FlattrID: '369138'
IssueTracker: https://github.com/dschuermann/ad-away/issues
-License: GPLv3
+License: GPL-3.0
Litecoin: null
MaintainerNotes: ''
Name: null
Donate: null
FlattrID: null
IssueTracker: https://github.com/SMSSecure/SMSSecure/issues
-License: GPLv3
+License: GPL-3.0
Litecoin: null
MaintainerNotes: ''
Name: null
Donate: http://www.videolan.org/contribute.html#money
FlattrID: null
IssueTracker: http://www.videolan.org/support/index.html#bugs
-License: GPLv3
+License: GPL-3.0
Litecoin: null
MaintainerNotes: 'Instructions and dependencies here: http://wiki.videolan.org/AndroidCompile
Categories:Development,GuardianProject
-License:GPLv3
+License:GPL-3.0
Web Site:https://dev.guardianproject.info/projects/checkey
Source Code:https://github.com/guardianproject/checkey
Issue Tracker:https://dev.guardianproject.info/projects/checkey/issues
★ 致用户:我们还缺少你喜欢的功能?发现了一个 bug?请告诉我们!我们乐于听取您的意见。请发送电子邮件至: support@guardianproject.info 或者加入我们的聊天室 https://guardianproject.info/contact
IssueTracker: https://dev.guardianproject.info/projects/urzip/issues
-License: GPLv3
+License: GPL-3.0
Repo: https://github.com/guardianproject/urzip.git
RepoType: git
SourceCode: https://github.com/guardianproject/urzip
Categories:Development
-License:GPLv3
+License:GPL-3.0
Source Code:https://github.com/eighthave/urzip
Bitcoin:1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
Categories:Development
-License:GPLv3
+License:GPL-3.0
Source Code:https://github.com/eighthave/urzip
Bitcoin:1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
Categories:Development
-License:GPLv3
+License:GPL-3.0
Source Code:https://github.com/eighthave/urzip
Bitcoin:1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
"Donate": "http://sufficientlysecure.org/index.php/adaway",
"FlattrID": "369138",
"IssueTracker": "https://github.com/dschuermann/ad-away/issues",
- "License": "GPLv3",
+ "License": "GPL-3.0",
"Provides": "org.sufficientlysecure.adaway",
"Repo": "https://github.com/dschuermann/ad-away.git",
"RepoType": "git",
Categories:Phone & SMS
-License:GPLv3
+License:GPL-3.0
Web Site:http://www.smssecure.org
Source Code:https://github.com/SMSSecure/SMSSecure
Issue Tracker:https://github.com/SMSSecure/SMSSecure/issues
Categories:
- Multimedia
-License: GPLv3
+License: GPL-3.0
WebSite: http://www.videolan.org/vlc/download-android.html
SourceCode: http://git.videolan.org/?p=vlc-ports/android.git;a=summary
IssueTracker: "http://www.videolan.org/support/index.html#bugs"
<id>fake.ota.update</id>
<added>2016-03-10</added>
<lastupdated>2016-03-10</lastupdated>
- <name>fake.ota.update_1234.zip</name>
+ <name>fake.ota.update_1234</name>
<summary>Tests whether OTA ZIP files are being include</summary>
<desc><p>F-Droid can make use of system privileges or permissions to install, update and remove applications on its own. The only way to obtain those privileges is to become a system app.</p><p>This is where the Privileged Extension comes in - being a separate app and much smaller, it can be installed as a system app and communicate with the main app via AIDL IPC.</p><p>This has several advantages:</p><ul><li> Reduced disk usage in the system partition</li><li> System updates don't remove F-Droid</li><li> The process of installing into system via root is safer</li></ul><p>This is packaged as an OTA (Over-The-Air) update ZIP file. It must be installed using TWRP or other Android recovery that can flash updates to the system from the /data/data/org.fdroid.fdroid folder on the /data partition. The standalone APK is called F-Droid Privileged Extension.</p></desc>
<license>Apache-2.0</license>
<summary></summary>
<icon>obb.main.oldversion.1444412523.png</icon>
<desc><p>No description available</p></desc>
- <license>GPLv3</license>
+ <license>GPL-3.0</license>
<categories>Development</categories>
<category>Development</category>
<web></web>
<summary></summary>
<icon>obb.main.twoversions.1101617.png</icon>
<desc><p>No description available</p></desc>
- <license>GPLv3</license>
+ <license>GPL-3.0</license>
<categories>Development</categories>
<category>Development</category>
<web></web>
<application id="obb.mainpatch.current">
<id>obb.mainpatch.current</id>
<added>2016-04-23</added>
- <lastupdated>2016-04-23</lastupdated>
+ <lastupdated>2017-06-01</lastupdated>
<name>OBB Main/Patch Current</name>
<summary></summary>
<icon>obb.mainpatch.current.1619.png</icon>
<desc><p>No description available</p></desc>
- <license>GPLv3</license>
+ <license>GPL-3.0</license>
<categories>Development</categories>
<category>Development</category>
<web></web>
<summary>一个实用工具,获取已安装在您的设备上的应用的有关信息</summary>
<icon>info.guardianproject.urzip.100.png</icon>
<desc><p>It’s Urzip 是一个获得已安装 APK 相关信息的实用工具。它从您的设备上已安装的所有应用开始,一键触摸即可显示 APK 的指纹,并且提供到达 virustotal.com 和 androidobservatory.org 的快捷链接,让您方便地了解特定 APK 的档案。它还可以让您导出签名证书和生成 ApkSignaturePin Pin 文件供 TrustedIntents 库使用。</p><p>★ Urzip 支持下列语言: Deutsch, English, español, suomi, 日本語, 한국어, Norsk, português (Portugal), Русский, Slovenščina, Türkçe 没看到您的语言?帮忙翻译本应用吧: https://www.transifex.com/projects/p/urzip</p><p>★ 致用户:我们还缺少你喜欢的功能?发现了一个 bug?请告诉我们!我们乐于听取您的意见。请发送电子邮件至: support@guardianproject.info 或者加入我们的聊天室 https://guardianproject.info/contact</p></desc>
- <license>GPLv3</license>
+ <license>GPL-3.0</license>
<categories>Development,GuardianProject,1,2.0</categories>
<category>Development</category>
<web>https://dev.guardianproject.info/projects/urzip</web>
echo 'WARNING: Skipping `fdroid build` test since android-23 is missing!'
fi
+#------------------------------------------------------------------------------#
+echo_header 'copy git import and run `fdroid scanner` on it'
+
+REPOROOT=`create_test_dir`
+cd $REPOROOT
+touch config.py
+cp $WORKSPACE/examples/fdroid-icon.png $REPOROOT/
+mkdir metadata
+echo "Auto Name:Just A Test" > metadata/org.fdroid.ci.test.app.txt
+echo "Web Site:" >> metadata/org.fdroid.ci.test.app.txt
+echo "Build:0.3,300" >> metadata/org.fdroid.ci.test.app.txt
+echo " commit=0.3" >> metadata/org.fdroid.ci.test.app.txt
+echo " subdir=app" >> metadata/org.fdroid.ci.test.app.txt
+echo " gradle=yes" >> metadata/org.fdroid.ci.test.app.txt
+echo "" >> metadata/org.fdroid.ci.test.app.txt
+echo "Repo:https://gitlab.com/fdroid/ci-test-app.git" >> metadata/org.fdroid.ci.test.app.txt
+echo "Repo Type:git" >> metadata/org.fdroid.ci.test.app.txt
+mkdir build
+cp -a $WORKSPACE/tests/tmp/importer build/org.fdroid.ci.test.app
+ls -l build/org.fdroid.ci.test.app
+$fdroid scanner org.fdroid.ci.test.app --verbose
+
#------------------------------------------------------------------------------#
echo_header "copy tests/repo, generate java/gpg keys, update, and gpgsign"
sed -i --expression='s,timestamp="[0-9]*",timestamp="1480431575",' repo/index.xml
diff $WORKSPACE/tests/repo/index.xml repo/index.xml
+
+#------------------------------------------------------------------------------#
+echo_header 'rename apks with `fdroid update --rename-apks`, --nosign for speed'
+
+REPOROOT=`create_test_dir`
+cd $REPOROOT
+cp $WORKSPACE/tests/keystore.jks $REPOROOT/
+$fdroid init --keystore keystore.jks --repo-keyalias=sova
+echo 'keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py
+echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py
+echo "accepted_formats = ['txt', 'yml']" >> config.py
+echo 'keydname = "CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US"' >> config.py
+test -d metadata || mkdir metadata
+cp $WORKSPACE/tests/metadata/info.guardianproject.urzip.yml metadata/
+test -d repo || mkdir repo
+cp $WORKSPACE/tests/urzip.apk "repo/asdfiuhk urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234 ö.apk"
+$fdroid update --rename-apks --pretty --nosign
+test -e repo/info.guardianproject.urzip_100.apk
+grep -F 'info.guardianproject.urzip_100.apk' repo/index-v1.json repo/index.xml
+cp $WORKSPACE/tests/urzip-release.apk repo/
+$fdroid update --rename-apks --pretty --nosign
+test -e repo/info.guardianproject.urzip_100.apk
+test -e repo/info.guardianproject.urzip_100_b4964fd.apk
+grep -F 'info.guardianproject.urzip_100.apk' repo/index-v1.json repo/index.xml
+grep -F 'info.guardianproject.urzip_100_b4964fd.apk' repo/index-v1.json
+! grep -F 'info.guardianproject.urzip_100_b4964fd.apk' repo/index.xml
+cp $WORKSPACE/tests/urzip-release.apk repo/
+$fdroid update --rename-apks --pretty --nosign
+test -e repo/info.guardianproject.urzip_100.apk
+test -e repo/info.guardianproject.urzip_100_b4964fd.apk
+test -e duplicates/repo/info.guardianproject.urzip_100_b4964fd.apk
+grep -F 'info.guardianproject.urzip_100.apk' repo/index-v1.json repo/index.xml
+grep -F 'info.guardianproject.urzip_100_b4964fd.apk' repo/index-v1.json
+! grep -F 'info.guardianproject.urzip_100_b4964fd.apk' repo/index.xml
+
+
#------------------------------------------------------------------------------#
echo_header "test metadata checks"
cd $REPOROOT
mkdir repo
mkdir metadata
-echo "License:GPL" >> metadata/fake.txt
+echo "License:GPL-2.0" >> metadata/fake.txt
echo "Summary:Yup still fake" >> metadata/fake.txt
echo "Categories:Internet" >> metadata/fake.txt
echo "Description:" >> metadata/fake.txt
export ANDROID_HOME=$STORED_ANDROID_HOME
+#------------------------------------------------------------------------------#
+echo_header "check duplicate files are properly handled by fdroid update"
+
+REPOROOT=`create_test_dir`
+KEYSTORE=$WORKSPACE/tests/keystore.jks
+cd $REPOROOT
+$fdroid init --keystore $KEYSTORE --repo-keyalias=sova
+echo 'keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py
+echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py
+mkdir $REPOROOT/metadata
+cp -a $WORKSPACE/tests/metadata/obb.mainpatch.current.txt $REPOROOT/metadata
+echo "accepted_formats = ['txt']" >> config.py
+cp $WORKSPACE/tests/repo/obb.mainpatch.current_1619.apk $REPOROOT/repo/
+cp $WORKSPACE/tests/repo/obb.mainpatch.current_1619_another-release-key.apk $REPOROOT/repo/
+$fdroid update --pretty
+grep -F 'obb.mainpatch.current_1619.apk' repo/index.xml repo/index-v1.json
+grep -F 'obb.mainpatch.current_1619_another-release-key.apk' repo/index-v1.json
+! grep -F 'obb.mainpatch.current_1619_another-release-key.apk' repo/index.xml
+# die if there are exact duplicates
+cp $WORKSPACE/tests/repo/obb.mainpatch.current_1619.apk $REPOROOT/repo/duplicate.apk
+! $fdroid update
+
+
#------------------------------------------------------------------------------#
echo_header "setup new repo from scratch using ANDROID_HOME, putting APKs in repo first"
-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
obb.main.twoversions_1101617.apk obb.main.twoversions 2016-06-20
obb.mainpatch.current_1619.apk obb.mainpatch.current 2016-04-23
+obb.mainpatch.current_1619_another-release-key.apk obb.mainpatch.current 2017-06-01
urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk info.guardianproject.urzip 2016-06-23
self.assertTrue(False, 'TypeError!')
def testBadGetsig(self):
+ """getsig() should still be able to fetch the fingerprint of bad signatures"""
# config needed to use jarsigner and keytool
config = dict()
fdroidserver.common.fill_config_defaults(config)
fdroidserver.update.config = config
+
apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
- sig = self.javagetsig(apkfile)
- self.assertIsNone(sig, "sig should be None: " + str(sig))
- pysig = fdroidserver.update.getsig(apkfile)
- self.assertIsNone(pysig, "python sig should be None: " + str(sig))
+ sig = fdroidserver.update.getsig(apkfile)
+ self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
+ "python sig should be: " + str(sig))
apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
- sig = self.javagetsig(apkfile)
- self.assertIsNone(sig, "sig should be None: " + str(sig))
- pysig = fdroidserver.update.getsig(apkfile)
- self.assertIsNone(pysig, "python sig should be None: " + str(sig))
+ sig = fdroidserver.update.getsig(apkfile)
+ self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
+ "python sig should be: " + str(sig))
def testScanApksAndObbs(self):
os.chdir(os.path.join(localmodule, 'tests'))
fdroidserver.update.options = type('', (), {})()
fdroidserver.update.options.clean = True
fdroidserver.update.options.delete_unknown = True
+ fdroidserver.update.options.rename_apks = False
apps = fdroidserver.metadata.read_metadata(xref=True)
knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.scan_apks({}, 'repo', knownapks, False)
- self.assertEqual(len(apks), 6)
+ self.assertEqual(len(apks), 7)
apk = apks[0]
self.assertEqual(apk['minSdkVersion'], '4')
self.assertEqual(apk['targetSdkVersion'], '18')