signindex: add JSON check for entry.json

Ran this to generate/refresh the test index files:
`cd tests; ../fdroid update --nosign --pretty`

* converts config.py description to a single line, since the values are no
  longer stripped, so this give the same output.

closes #835
This commit is contained in:
Hans-Christoph Steiner 2023-02-17 12:39:15 +01:00 committed by Jochen Sprickerhof
parent 6e2b4f65c2
commit 0c9f62a5fe
11 changed files with 1048 additions and 31 deletions

11
.gitignore vendored
View File

@ -42,16 +42,21 @@ makebuildserver.config.py
/tests/OBBMainPatchCurrent.apk
/tests/OBBMainTwoVersions.apk
/tests/archive/categories.txt
/tests/archive/diff/[1-9]*.json
/tests/archive/entry.jar
/tests/archive/entry.json
/tests/archive/icons*
/tests/archive/index-v1.jar
/tests/archive/index-v1.json
/tests/archive/index-v2.json
/tests/archive/index.css
/tests/archive/index.html
/tests/archive/index.jar
/tests/archive/index.png
/tests/archive/index_unsigned.jar
/tests/archive/index.xml
/tests/archive/index-v1.jar
/tests/archive/index-v1.json
/tests/archive/index_unsigned.jar
/tests/metadata/org.videolan.vlc/en-US/icon*.png
/tests/repo/diff/[1-9]*.json
/tests/repo/index.css
/tests/repo/index.html
/tests/repo/index.jar

View File

@ -642,8 +642,10 @@ include tests/repo/com.politedroid_4.apk
include tests/repo/com.politedroid_5.apk
include tests/repo/com.politedroid_6.apk
include tests/repo/duplicate.permisssions_9999999.apk
include tests/repo/entry.json
include tests/repo/fake.ota.update_1234.zip
include tests/repo/index-v1.json
include tests/repo/index-v2.json
include tests/repo/index.xml
include tests/repo/info.zwanenburg.caffeinetile_4.apk
include tests/repo/main.1101613.obb.main.twoversions.obb

View File

@ -121,27 +121,43 @@ def sign_jar(jar, use_old_algs=False):
def sign_index(repodir, json_name):
"""Sign index-v1.json to make index-v1.jar.
"""Sign data file like entry.json to make a signed JAR like entry.jar.
The data file like index-v1.json means that there is unsigned
data. That file is then stuck into a jar and signed by the
signing process. This is a bit different than sign_jar, which is
used for index.jar: that creates index.xml then puts that in a
index_unsigned.jar, then that file is signed.
This also checks to make sure that the JSON files are intact
before signing them. Broken JSON files should never be signed, so
taking some extra time and failing hard is the preferred
option. This signing process can happen on an entirely separate
machine and file tree, so this ensures that nothing got broken
during transfer.
This is a bit different than index.jar: instead of their being index.xml
and index_unsigned.jar, the presence of index-v1.json means that there is
unsigned data. That file is then stuck into a jar and signed by the
signing process. index-v1.json is never published to the repo. It is
included in the binary transparency log, if that is enabled.
"""
json_file = os.path.join(repodir, json_name)
with open(json_file, encoding="utf-8") as fp:
data = json.load(fp)
if json_name == 'entry.json':
index_file = os.path.join(repodir, data['index']['name'].lstrip('/'))
sha256 = common.sha256sum(index_file)
if sha256 != data['index']['sha256']:
raise FDroidException(
_('%s has bad SHA-256: %s') % (index_file, sha256)
)
with open(index_file) as fp:
index = json.load(fp)
if not isinstance(index, dict):
raise FDroidException(_('%s did not produce a dict!') % index_file)
elif json_name == 'index-v1.json':
[metadata.App(app) for app in data["apps"]]
name, ext = common.get_extension(json_name)
index_file = os.path.join(repodir, json_name)
# Test if index is valid
with open(index_file, encoding="utf-8") as fp:
index = json.load(fp)
# TODO: add test for index-v2
if "apps" in index:
[metadata.App(app) for app in index["apps"]]
jar_file = os.path.join(repodir, name + '.jar')
with zipfile.ZipFile(jar_file, 'w', zipfile.ZIP_DEFLATED) as jar:
jar.write(index_file, json_name)
jar.write(json_file, json_name)
if json_name in ('index.xml', 'index-v1.json'):
sign_jar(jar_file, use_old_algs=True)

View File

@ -1,12 +1,9 @@
# TODO convert to config.yml!
repo_url = "https://MyFirstFDroidRepo.org/fdroid/repo"
repo_name = "My First F-Droid Repo Demo"
repo_description = """
This is a repository of apps to be used with F-Droid. Applications in this
repository are either official binaries built by the original application
developers, or are binaries built from source by the admin of f-droid.org
using the tools on https://gitlab.com/u/fdroid.
"""
repo_description = """This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid."""
archive_older = 3
archive_url = "https://f-droid.org/archive"
@ -32,3 +29,5 @@ update_stats = True
install_list = 'org.adaway'
uninstall_list = ('com.android.vending', 'com.facebook.orca', )
repo_key_sha256 = "f49af3f11efddf20dffd70f5e3117b9976674167adca280e6b1932a0601b26f6"

11
tests/repo/entry.json Normal file
View File

@ -0,0 +1,11 @@
{
"timestamp": 1676634233000,
"version": 20002,
"index": {
"name": "/index-v2.json",
"sha256": "da1d651eb7bbc27d2334819c591baa5afb70b01397849de515dade624a96de6d",
"size": 32946,
"numPackages": 10
},
"diffs": {}
}

View File

@ -1,6 +1,6 @@
{
"repo": {
"timestamp": 1502845383782,
"timestamp": 1676634233000,
"version": 20002,
"name": "My First F-Droid Repo Demo",
"icon": "icon.png",
@ -698,4 +698,4 @@
}
]
}
}
}

920
tests/repo/index-v2.json Normal file
View File

@ -0,0 +1,920 @@
{
"repo": {
"name": {
"en-US": "My First F-Droid Repo Demo"
},
"description": {
"en-US": "This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid."
},
"icon": {
"en-US": {
"name": "/icons/icon.png",
"sha256": "b1f27fa87f8cabca50cdcd462a0f500d79d883b965a498d0e49eea560b39be1f",
"size": 715
}
},
"address": "https://MyFirstFDroidRepo.org/fdroid/repo",
"mirrors": [
{
"url": "https://MyFirstFDroidRepo.org/fdroid/repo",
"isPrimary": true
},
{
"url": "http://foobarfoobarfoobar.onion/fdroid/repo"
},
{
"url": "https://foo.bar/fdroid/repo"
}
],
"timestamp": 1676634233000,
"requests": {
"install": [
"org.adaway"
],
"uninstall": [
"com.android.vending",
"com.facebook.orca"
]
}
},
"packages": {
"com.politedroid": {
"metadata": {
"added": 1498176000000,
"categories": [
"Time"
],
"issueTracker": "https://github.com/miguelvps/PoliteDroid/issues",
"lastUpdated": 1498176000000,
"license": "GPL-3.0-only",
"sourceCode": "https://github.com/miguelvps/PoliteDroid",
"name": {
"en-US": "Polite Droid"
},
"summary": {
"en-US": "Calendar tool"
},
"description": {
"en-US": "Activates silent mode during calendar events."
},
"icon": {
"en-US": {
"name": "/icons/com.politedroid.6.png",
"sha256": "edf8d30b97a06821337e267168b131a6a16d81df9e7007e017778f9781f5c8f3",
"size": 559
}
},
"preferredSigner": "32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
},
"versions": {
"70c2f776a2bac38a58a7d521f96ee0414c6f0fb1de973c3ca8b10862a009247d": {
"added": 1498176000000,
"file": {
"name": "/com.politedroid_6.apk",
"sha256": "70c2f776a2bac38a58a7d521f96ee0414c6f0fb1de973c3ca8b10862a009247d",
"size": 16578,
"ipfsCIDv1": "bafybeidvgxrq77qr7yqkcnykdfvszsxjqc5kzt6ya5k7r666wriadrylt4"
},
"manifest": {
"versionName": "1.5",
"versionCode": 6,
"usesSdk": {
"minSdkVersion": 14,
"targetSdkVersion": 21
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
},
"usesPermission": [
{
"name": "android.permission.READ_CALENDAR"
},
{
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
}
]
},
"antiFeatures": {
"NoSourceSince": {}
}
},
"5bdbfa071cca4b8d05ced41d6b28763595d6e8096cca5bbf0f9253c9a2622e5d": {
"added": 1498176000000,
"file": {
"name": "/com.politedroid_5.apk",
"sha256": "5bdbfa071cca4b8d05ced41d6b28763595d6e8096cca5bbf0f9253c9a2622e5d",
"size": 18817,
"ipfsCIDv1": "bafybeifbrio5rumqvgfd5sihs7yihux2yktfvd5i7jimlgrwchzcvi6ldu"
},
"manifest": {
"versionName": "1.4",
"versionCode": 5,
"usesSdk": {
"minSdkVersion": 3,
"targetSdkVersion": 10
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
},
"usesPermission": [
{
"name": "android.permission.READ_CALENDAR"
},
{
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
}
]
},
"antiFeatures": {
"NoSourceSince": {}
}
},
"c809bdff83715fbf919f3840ee09869b038e209378b906e135ee40d3f0e1f075": {
"added": 1498176000000,
"file": {
"name": "/com.politedroid_4.apk",
"sha256": "c809bdff83715fbf919f3840ee09869b038e209378b906e135ee40d3f0e1f075",
"size": 18489,
"ipfsCIDv1": "bafybeicridbev22c2rt3lwbfsrkafcf3yepak7kpvk6zgbayrxls2mmwim"
},
"manifest": {
"versionName": "1.3",
"versionCode": 4,
"usesSdk": {
"minSdkVersion": 3,
"targetSdkVersion": 3
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
},
"usesPermission": [
{
"name": "android.permission.READ_CALENDAR"
},
{
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
},
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.READ_PHONE_STATE"
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE"
}
]
},
"antiFeatures": {
"NoSourceSince": {}
}
},
"665d03d61ebc642289fda697f71a59305b0202b16cafc5ffdae91cbe91f0b25d": {
"added": 1498176000000,
"file": {
"name": "/com.politedroid_3.apk",
"sha256": "665d03d61ebc642289fda697f71a59305b0202b16cafc5ffdae91cbe91f0b25d",
"size": 17552,
"ipfsCIDv1": "bafybeib7arokhivttalcnq5ieu5fx5pzn7vo5qpmdiozqodzhb4ba53nd4"
},
"manifest": {
"versionName": "1.2",
"versionCode": 3,
"usesSdk": {
"minSdkVersion": 3,
"targetSdkVersion": 3
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
},
"usesPermission": [
{
"name": "android.permission.READ_CALENDAR"
},
{
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
},
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.READ_PHONE_STATE"
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE"
}
]
},
"antiFeatures": {
"NoSourceSince": {}
}
}
}
},
"duplicate.permisssions": {
"metadata": {
"added": 1513900800000,
"categories": [
"tests"
],
"lastUpdated": 1513900800000,
"name": {
"en-US": "Duplicate Permisssions"
},
"summary": {
"en-US": "Test app for all possible <uses-permissions>"
},
"icon": {
"en-US": {
"name": "/icons/duplicate.permisssions.9999999.png",
"sha256": "fb0f3bb45312b53e349a762b67af4f48d010a38a245f75c3a0b152097d7b067f",
"size": 1301
}
},
"preferredSigner": "659e1fd284549f70d13fb02c620100e27eeea3420558cce62b0f5d4cf2b77d84"
},
"versions": {
"8367857fe75f85321ce2c344b34804d0bc193707f6ba03710d025d9030803434": {
"added": 1513900800000,
"file": {
"name": "/duplicate.permisssions_9999999.apk",
"sha256": "8367857fe75f85321ce2c344b34804d0bc193707f6ba03710d025d9030803434",
"size": 27446,
"ipfsCIDv1": "bafybeicucr4lk7fynyde4fpxubudpl6m6wqnuq2j6vjroutjyryw24en3u"
},
"manifest": {
"versionName": "",
"versionCode": 9999999,
"usesSdk": {
"minSdkVersion": 18,
"targetSdkVersion": 27
},
"signer": {
"sha256": [
"659e1fd284549f70d13fb02c620100e27eeea3420558cce62b0f5d4cf2b77d84"
]
},
"usesPermission": [
{
"name": "android.permission.INTERNET"
},
{
"name": "android.permission.ACCESS_NETWORK_STATE"
},
{
"name": "android.permission.ACCESS_WIFI_STATE"
},
{
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
},
{
"name": "android.permission.INTERNET"
},
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE",
"maxSdkVersion": 18
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE",
"maxSdkVersion": 18
}
],
"usesPermissionSdk23": [
{
"name": "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS",
"maxSdkVersion": 27
},
{
"name": "android.permission.REQUEST_INSTALL_PACKAGES"
}
]
}
}
}
},
"fake.ota.update": {
"metadata": {
"added": 1457568000000,
"categories": [
"System"
],
"issueTracker": "https://gitlab.com/fdroid/privileged-extension/issues",
"lastUpdated": 1457568000000,
"license": "Apache-2.0",
"sourceCode": "https://gitlab.com/fdroid/privileged-extension",
"webSite": "https://f-droid.org",
"name": {
"en-US": "fake.ota.update_1234"
},
"summary": {
"en-US": "Tests whether OTA ZIP files are being include"
},
"description": {
"en-US": "F-Droid can make use of system privileges or permissions to\ninstall, update and remove applications on its own. The only way to obtain those\nprivileges is to become a system app.\n\nThis is where the Privileged Extension comes in - being a separate app and much\nsmaller, it can be installed as a system app and communicate with the main app\nvia AIDL IPC.\n\nThis has several advantages:\n\n* Reduced disk usage in the system partition\n* System updates don't remove F-Droid\n* The process of installing into system via root is safer\n\nThis is packaged as an OTA (Over-The-Air) update ZIP file. It must be installed\nusing TWRP or other Android recovery that can flash updates to the system from\nthe /data/data/org.fdroid.fdroid folder on the /data partition. The standalone\nAPK is called F-Droid Privileged Extension."
},
"donate": [
"https://f-droid.org/about"
]
},
"versions": {
"897a92a4ccff4f415f6ba275b2af16d4ecaee60a983b215bddcb9f8964e7a24c": {
"added": 1457568000000,
"file": {
"name": "/fake.ota.update_1234.zip",
"sha256": "897a92a4ccff4f415f6ba275b2af16d4ecaee60a983b215bddcb9f8964e7a24c",
"size": 233
},
"manifest": {
"versionName": "897a92a",
"versionCode": 1234
}
}
}
},
"info.guardianproject.urzip": {
"metadata": {
"added": 1466640000000,
"categories": [
"Development",
"GuardianProject",
"1",
"2.0"
],
"issueTracker": "https://dev.guardianproject.info/projects/urzip/issues",
"lastUpdated": 1466640000000,
"license": "GPL-3.0-only",
"sourceCode": "https://github.com/guardianproject/urzip",
"webSite": "https://dev.guardianproject.info/projects/urzip",
"featureGraphic": {
"en-US": {
"name": "/info.guardianproject.urzip/en-US/featureGraphic_GFRT5BovZsENGpJq1HqPODGWBRPWQsx25B95Ol5w_wU=.png",
"sha256": "185453e41a2f66c10d1a926ad47a8f3831960513d642cc76e41f793a5e70ff05",
"size": 36027
}
},
"authorWebSite": "https://guardianproject.info",
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
"openCollective": "f-droid-just-testing",
"name": {
"en-US": "title"
},
"summary": {
"en-US": "一个实用工具,获取已安装在您的设备上的应用的有关信息"
},
"description": {
"en-US": "Its Urzip 是一个获得已安装 APK 相关信息的实用工具。它从您的设备上已安装的所有应用开始,一键触摸即可显示 APK 的指纹,并且提供到达 virustotal.com 和 androidobservatory.org 的快捷链接,让您方便地了解特定 APK 的档案。它还可以让您导出签名证书和生成 ApkSignaturePin Pin 文件供 TrustedIntents 库使用。\n\n★ Urzip 支持下列语言: Deutsch, English, español, suomi, 日本語, 한국어, Norsk, português (Portugal), Русский, Slovenščina, Türkçe\n没看到您的语言帮忙翻译本应用吧\nhttps://www.transifex.com/projects/p/urzip\n\n★ 致用户:我们还缺少你喜欢的功能?发现了一个 bug请告诉我们我们乐于听取您的意见。请发送电子邮件至: support@guardianproject.info 或者加入我们的聊天室 https://guardianproject.info/contact\n"
},
"video": {
"en-US": "video"
},
"icon": {
"en-US": {
"name": "/info.guardianproject.urzip/en-US/icon_NJXNzMcyf-v9i5a1ElJi0j9X1LvllibCa48xXYPlOqQ=.png",
"sha256": "3495cdccc7327febfd8b96b5125262d23f57d4bbe59626c26b8f315d83e53aa4",
"size": 1413
}
},
"preferredSigner": "32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
},
"versions": {
"15c0ec72c74a3791f42cdb43c57df0fb11a4dbb656851bbb8cf05b26a8372789": {
"added": 1466640000000,
"file": {
"name": "/urzip-; Рахма́, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢·.apk",
"sha256": "15c0ec72c74a3791f42cdb43c57df0fb11a4dbb656851bbb8cf05b26a8372789",
"size": 11471,
"ipfsCIDv1": "bafybeig77jwqx243si3gh55iqx4gkcxhltkt6pjimzgigfsk3kshsi6qem"
},
"manifest": {
"versionName": "0.1",
"versionCode": 100,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
}
}
}
}
},
"info.zwanenburg.caffeinetile": {
"metadata": {
"added": 1539129600000,
"categories": [
"Development"
],
"lastUpdated": 1539129600000,
"name": {
"en-US": "Caffeine Tile"
},
"summary": {
"en-US": "Test app for extracting icons when an XML one is default"
},
"preferredSigner": "51cfa5c8a743833ad89acf81cb755936876a5c8b8eca54d1ffdcec0cdca25d0e"
},
"versions": {
"dbbdd7deadb038862f426b71efe4a64df8c3edf25d669e935f349510e16f65db": {
"added": 1539129600000,
"file": {
"name": "/info.zwanenburg.caffeinetile_4.apk",
"sha256": "dbbdd7deadb038862f426b71efe4a64df8c3edf25d669e935f349510e16f65db",
"size": 11740,
"ipfsCIDv1": "bafybeigormhkorw3mk6pkkfk63kkmxpvwylthgj67geulvskc5acr65sym"
},
"manifest": {
"versionName": "1.3",
"versionCode": 4,
"usesSdk": {
"minSdkVersion": 24,
"targetSdkVersion": 25
},
"signer": {
"sha256": [
"51cfa5c8a743833ad89acf81cb755936876a5c8b8eca54d1ffdcec0cdca25d0e"
]
},
"usesPermission": [
{
"name": "android.permission.WAKE_LOCK"
}
]
}
}
}
},
"no.min.target.sdk": {
"metadata": {
"added": 1539129600000,
"categories": [
"Development"
],
"lastUpdated": 1539129600000,
"name": {
"en-US": "No minSdkVersion or targetSdkVersion"
},
"summary": {
"en-US": "An APK without any <uses-sdk> block in AndroidManifest.xml"
},
"icon": {
"en-US": {
"name": "/icons/no.min.target.sdk.987.png",
"sha256": "fb0f3bb45312b53e349a762b67af4f48d010a38a245f75c3a0b152097d7b067f",
"size": 1301
}
},
"preferredSigner": "32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
},
"versions": {
"e2e1dc1d550df2b5bc383860139207258645b5540abeccd305ed8b2cb6459d2c": {
"added": 1539129600000,
"file": {
"name": "/no.min.target.sdk_987.apk",
"sha256": "e2e1dc1d550df2b5bc383860139207258645b5540abeccd305ed8b2cb6459d2c",
"size": 14102,
"ipfsCIDv1": "bafybeidwxseoagnew3gtlasttqovl7ciuwxaud5a5p4a5pzpbrfcfj2gaa"
},
"manifest": {
"versionName": "1.2-fake",
"versionCode": 987,
"usesSdk": {
"minSdkVersion": 3,
"targetSdkVersion": 3
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
},
"usesPermission": [
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.READ_PHONE_STATE"
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE"
}
]
}
}
}
},
"obb.main.oldversion": {
"metadata": {
"added": 1388448000000,
"categories": [
"Development"
],
"lastUpdated": 1388448000000,
"license": "GPL-3.0-only",
"sourceCode": "https://github.com/eighthave/urzip",
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
"liberapay": "12334",
"name": {
"en-US": "OBB Main Old Version"
},
"icon": {
"en-US": {
"name": "/icons/obb.main.oldversion.1444412523.png",
"sha256": "fb0f3bb45312b53e349a762b67af4f48d010a38a245f75c3a0b152097d7b067f",
"size": 1301
}
},
"preferredSigner": "818e469465f96b704e27be2fee4c63ab9f83ddf30e7a34c7371a4728d83b0bc1"
},
"versions": {
"c5f149e526f89c05c62923bdb7bb1e2be5673c46ec85143f41e514340631449c": {
"added": 1388448000000,
"file": {
"name": "/obb.main.oldversion_1444412523.apk",
"sha256": "c5f149e526f89c05c62923bdb7bb1e2be5673c46ec85143f41e514340631449c",
"size": 14323,
"ipfsCIDv1": "bafybeicnwnpiyfke3tbk3nve62meig65vved34i6kesjkksdciff6242ui"
},
"obbMainFile": {
"name": "/main.1434483388.obb.main.oldversion.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1444412523,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"818e469465f96b704e27be2fee4c63ab9f83ddf30e7a34c7371a4728d83b0bc1"
]
},
"usesPermission": [
{
"name": "android.permission.INTERNET"
},
{
"name": "android.permission.ACCESS_NETWORK_STATE",
"maxSdkVersion": 22
},
{
"name": "android.permission.ACCESS_WIFI_STATE"
},
{
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
},
{
"name": "android.permission.CHANGE_NETWORK_STATE"
},
{
"name": "android.permission.CHANGE_WIFI_STATE"
},
{
"name": "android.permission.BLUETOOTH"
},
{
"name": "android.permission.BLUETOOTH_ADMIN",
"maxSdkVersion": 18
},
{
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
},
{
"name": "android.permission.NFC"
}
],
"usesPermissionSdk23": [
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.WRITE_SETTINGS",
"maxSdkVersion": 25
}
]
},
"releaseChannels": [
"Beta"
]
}
}
},
"obb.main.twoversions": {
"metadata": {
"added": 1444608000000,
"categories": [
"Development"
],
"lastUpdated": 1466380800000,
"license": "GPL-3.0-only",
"sourceCode": "https://github.com/eighthave/urzip",
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
"name": {
"en-US": "OBB Main Two Versions"
},
"icon": {
"en-US": {
"name": "/icons/obb.main.twoversions.1101617.png",
"sha256": "d27c9866adeda6dd466628e43c62ccac95a0e9480c4bb095ac7e0b1c2b58a77d",
"size": 1413
}
},
"preferredSigner": "32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
},
"versions": {
"9bc74566f089ef030ac33e7fbd99d92f1a38f363fb499fed138d9e7b774e821c": {
"added": 1466380800000,
"file": {
"name": "/obb.main.twoversions_1101617.apk",
"sha256": "9bc74566f089ef030ac33e7fbd99d92f1a38f363fb499fed138d9e7b774e821c",
"size": 11481,
"ipfsCIDv1": "bafybeiblpfmwololxgsrum337rbbbsqg2gk6hytvt6szf4njubosju3bme"
},
"src": {
"name": "/obb.main.twoversions_1101617_src.tar.gz",
"sha256": "3115241ed53aa047191f64db2c14e609a7dc0a803211f56a9b17e2d027763f9d",
"size": 150
},
"obbMainFile": {
"name": "/main.1101615.obb.main.twoversions.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1101617,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
}
}
},
"7b0b7b9ba248e15751a16e3a0e01e1e24cbb673686c38422030cb75d5c33f0bb": {
"added": 1451606400000,
"file": {
"name": "/obb.main.twoversions_1101615.apk",
"sha256": "7b0b7b9ba248e15751a16e3a0e01e1e24cbb673686c38422030cb75d5c33f0bb",
"size": 11480,
"ipfsCIDv1": "bafybeigglr3iefb3es4lp2sgfacppk3w2qqtuykjgf4actebpalyizef3q"
},
"obbMainFile": {
"name": "/main.1101615.obb.main.twoversions.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1101615,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
}
}
},
"cce97a52ff18d843185be7f22ecb1a557c36b7a9f8ba07a8be94e328e00b35dc": {
"added": 1444608000000,
"file": {
"name": "/obb.main.twoversions_1101613.apk",
"sha256": "cce97a52ff18d843185be7f22ecb1a557c36b7a9f8ba07a8be94e328e00b35dc",
"size": 11477,
"ipfsCIDv1": "bafybeicocjo4khzp2rkui2ltvrhbksrm373lr3pb43ut7hqgbllfjpv6ti"
},
"obbMainFile": {
"name": "/main.1101613.obb.main.twoversions.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1101613,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
}
}
}
}
},
"obb.mainpatch.current": {
"metadata": {
"added": 1461369600000,
"categories": [
"Development"
],
"lastUpdated": 1496275200000,
"license": "GPL-3.0-only",
"sourceCode": "https://github.com/eighthave/urzip",
"featureGraphic": {
"en-US": {
"name": "/obb.mainpatch.current/en-US/featureGraphic_ffhLaojxbGAfu9ROe1MJgK5ux8d0OVc6b65nmvOBaTk=.png",
"sha256": "7df84b6a88f16c601fbbd44e7b530980ae6ec7c77439573a6fae679af3816939",
"size": 24336
}
},
"screenshots": {
"phone": {
"en-US": [
{
"name": "/obb.mainpatch.current/en-US/phoneScreenshots/screenshot-main.png",
"sha256": "719f95f0811e6e6e03e6dbd47553eafe9d8d96b14107e26f2dee3ccdabbdc6bf",
"size": 44990
}
]
},
"sevenInch": {
"en-US": [
{
"name": "/obb.mainpatch.current/en-US/sevenInchScreenshots/screenshot-tablet-main.png",
"sha256": "460c6ce2e5e3987ae6688f398c9093a07802991e7cdee559a578f201189c6630",
"size": 56049
}
]
}
},
"bitcoin": "1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk",
"name": {
"en-US": "OBB Main/Patch Current"
},
"icon": {
"en-US": {
"name": "/obb.mainpatch.current/en-US/icon_WI0pkO3LsklrsTAnRr-OQSxkkoMY41lYe2-fAvXLiLg=.png",
"sha256": "588d2990edcbb2496bb1302746bf8e412c64928318e359587b6f9f02f5cb88b8",
"size": 260113
}
},
"preferredSigner": "32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
},
"versions": {
"eda5fc3ecfdac3252717e36bdbc9820865baeef162264af9ba5db7364f0e7a0c": {
"added": 1461369600000,
"file": {
"name": "/obb.mainpatch.current_1619.apk",
"sha256": "eda5fc3ecfdac3252717e36bdbc9820865baeef162264af9ba5db7364f0e7a0c",
"size": 11479,
"ipfsCIDv1": "bafybeievo4e234mllujityvtjgeltauyfbriszoqddzygmimcm4mo3zyqu"
},
"obbMainFile": {
"name": "/main.1619.obb.mainpatch.current.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"obbPatchFile": {
"name": "/patch.1619.obb.mainpatch.current.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1619,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6"
]
}
}
},
"42e7d6d2f8254aaf9fe95ba6ecc233ee8c3cd543a3e4f3f9ebe1b638221122fa": {
"added": 1496275200000,
"file": {
"name": "/obb.mainpatch.current_1619_another-release-key.apk",
"sha256": "42e7d6d2f8254aaf9fe95ba6ecc233ee8c3cd543a3e4f3f9ebe1b638221122fa",
"size": 10541,
"ipfsCIDv1": "bafybeiatdbzlxairqzvdowevwuy7nk24rknc55jpip2wb2sq4c3f7mtngm"
},
"obbMainFile": {
"name": "/main.1619.obb.mainpatch.current.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"obbPatchFile": {
"name": "/patch.1619.obb.mainpatch.current.obb",
"sha256": "d3eb539a556352f3f47881d71fb0e5777b2f3e9a4251d283c18c67ce996774b7",
"size": 6
},
"manifest": {
"versionName": "0.1",
"versionCode": 1619,
"usesSdk": {
"minSdkVersion": 4,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"ce9e200667f02d96d49891a2e08a3c178870e91853d61bdd33ef5f0b54701aa5"
]
}
}
}
}
},
"souch.smsbypass": {
"metadata": {
"added": 1524700800000,
"categories": [
"Phone & SMS"
],
"issueTracker": "https://gitlab.com/souch/SMSbypass/issues",
"lastUpdated": 1524700800000,
"license": "GPL-3.0-only",
"sourceCode": "https://gitlab.com/souch/SMSbypass/tree/HEAD",
"webSite": "https://gitlab.com/souch/SMSbypass",
"flattrID": "cad90e036b975ed129a3ce80a0750466",
"name": {
"en-US": "Battery level"
},
"summary": {
"en-US": "Filter SMS and show them in a fake app"
},
"description": {
"en-US": "In order to keep away curious eyes, SMS-bypass filters incoming SMS messages\nbefore they reach your inbox. Based on bughunter2.smsfilter.\n\nFeatures:\n\n* Discrete fake app \"Battery level\": Long tap on Battery percentage will show SMS.\n* Filter incoming SMS specified address: redirect the SMS to SMS-bypass messages list; remove SMS arrival sound or vibration; show a discreet notification icon (battery level); vibrate if checked in settings\n* Add contact from contact list\n* Export messages to a text file"
},
"donate": [
"http://rodolphe.souchaud.free.fr/donate"
],
"icon": {
"en-US": {
"name": "/icons/souch.smsbypass.9.png",
"sha256": "8fee034537477fcd40fd33887868786b70258fcf7b9acffaff7436bca8748c8a",
"size": 1558
}
},
"preferredSigner": "d3aec784b1fd71549fc22c999789122e3639895db6bd585da5835fbe3db6985c"
},
"versions": {
"80b0ae68a1189baa3ee6717092e3dbf1a4210165f7f7e5f2f9616bd63a2ec01d": {
"added": 1524700800000,
"file": {
"name": "/souch.smsbypass_9.apk",
"sha256": "80b0ae68a1189baa3ee6717092e3dbf1a4210165f7f7e5f2f9616bd63a2ec01d",
"size": 81295,
"ipfsCIDv1": "bafybeihaccfnt32q2iwfulh2m7jvdivuunlw6t72wa7jfi7igxvqxjqszy"
},
"manifest": {
"versionName": "0.9",
"versionCode": 9,
"usesSdk": {
"minSdkVersion": 8,
"targetSdkVersion": 18
},
"signer": {
"sha256": [
"d3aec784b1fd71549fc22c999789122e3639895db6bd585da5835fbe3db6985c"
]
},
"usesPermission": [
{
"name": "android.permission.RECEIVE_SMS"
},
{
"name": "android.permission.SEND_SMS"
},
{
"name": "android.permission.READ_CONTACTS"
},
{
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
},
{
"name": "android.permission.VIBRATE"
},
{
"name": "android.permission.READ_EXTERNAL_STORAGE"
}
]
}
}
}
}
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<fdroid>
<repo icon="icon.png" name="My First F-Droid Repo Demo" pubkey="308204e1308202c9a003020102020434597643300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303931333230313930395a170d3434303133303230313930395a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a028202010086ef94b5aacf2ba4f38c875f4194b44f5644392e3715575d7c92828577e692c352b567172823851c8c72347fbc9d99684cd7ca3e1db3e4cca126382c53f2a5869fb4c19bdec989b2930501af3e758ff40588915fe96b10076ce3346a193a0277d79e83e30fd8657c20e35260dd085aa32eac7c4b85786ffefbf1555cafe2bc928443430cdbba48cfbe701e12ae86e676477932730d4fc7c00af820aef85038a5b4df084cf6470d110dc4c49ea1b749b80b34709d199b3db516b223625c5de4501e861f7d261b3838f8f616aa78831d618d41d25872dc810c9b2087b5a9e146ca95be740316dcdbcb77314e23ab87d4487913b800b1113c0603ea2294188b71d3e49875df097b56f9151211fc6832f9790c5c83d17481f14ad37915fd164f4fd713f6732a15f4245714b84cd665bdbd085660ea33ad7d7095dcc414f09e3903604a40facc2314a115c0045bb50e9df38efb57e1b8e7cc105f340a26eeb46aba0fa6672953eee7f1f92dcb408e561909bbd4bdf4a4948c4d57c467d21aa238c34ba43be050398be963191fa2b49828bc1e4eeed224b40dbe9dc3e570890a71a974a2f4527edb1b07105071755105edcb2af2f269facfb89180903a572a99b46456e80d4a01685a80b233278805f2c876678e731f4ec4f52075aeef6b2b023efbb8a3637ef507c4c37c27e428152ec1817fcba640ad601cb09f72f0fbe2d274a2410203010001a321301f301d0603551d0e04160414c28bf33dd5a9a17338e5b1d1a6edd8c7d141ed0b300d06092a864886f70d01010b0500038202010084e20458b2aafd7fc27146b0986f9324f4260f244920417a77c9bf15e2e2d22d2725bdd8093ec261c3779c3ca03312516506f9410075b90595b41345956d8eb2786fb5994f195611382c2b99dba13381b0100a30bc9e6e47248bf4325e2f6eec9d789216dc7536e753bf1f4be603d9fa2e6f5e192b4eb988b8cdb0bb1e8668a9225426f7d4636479f73ed24ad1d2657c31e63c93d9679b9080171b3bd1bf10a3b92b80bd790fbf62d3644900cd08eae8b9bf9c2567be98dc8cdd2ae19a8d57a3e3e2de899f81f1279f578989e6af906f80c8c2b67651730ee7e568c1af5bcb845b6d685dc55332a9984aeceaea3b7e883447edf1c76b155d95253e39b9710eaa22efa6c81468829702b5dce7126538f3ca70c2f0ad9a5795435fdb1f715f20d60359ef9a9926c7050116e802df651727447848827815f70bd82af3cedd08783156102d2d8ce995c4c43b8e47e91a3e6927f3505a5d395e6bebb84542c570903eeab4382a1c2151f1471c7a06a34dc4d268d8fa72e93bdcd2dccc4302ecac47b9e7e3d8bc9b46d21cd097874a24d529548018dc190ff568c6aa428f0a5eedff1a347730931c74f19277538e49647a4ad7254f4c1ec7d4da12cce9e1fad9607534e66ab40a56b473d9d7e3d563fd03cad2052bad365c5a29f8ae54f09b60dbca3ea768d7767cbe1c133ca08ce725c1c1370f4aab8e5b6e286f52dc0be8d0982b5a" timestamp="1480431575" url="https://MyFirstFDroidRepo.org/fdroid/repo" version="20002">
<repo icon="icon.png" name="My First F-Droid Repo Demo" pubkey="308204e1308202c9a003020102020434597643300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303931333230313930395a170d3434303133303230313930395a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a028202010086ef94b5aacf2ba4f38c875f4194b44f5644392e3715575d7c92828577e692c352b567172823851c8c72347fbc9d99684cd7ca3e1db3e4cca126382c53f2a5869fb4c19bdec989b2930501af3e758ff40588915fe96b10076ce3346a193a0277d79e83e30fd8657c20e35260dd085aa32eac7c4b85786ffefbf1555cafe2bc928443430cdbba48cfbe701e12ae86e676477932730d4fc7c00af820aef85038a5b4df084cf6470d110dc4c49ea1b749b80b34709d199b3db516b223625c5de4501e861f7d261b3838f8f616aa78831d618d41d25872dc810c9b2087b5a9e146ca95be740316dcdbcb77314e23ab87d4487913b800b1113c0603ea2294188b71d3e49875df097b56f9151211fc6832f9790c5c83d17481f14ad37915fd164f4fd713f6732a15f4245714b84cd665bdbd085660ea33ad7d7095dcc414f09e3903604a40facc2314a115c0045bb50e9df38efb57e1b8e7cc105f340a26eeb46aba0fa6672953eee7f1f92dcb408e561909bbd4bdf4a4948c4d57c467d21aa238c34ba43be050398be963191fa2b49828bc1e4eeed224b40dbe9dc3e570890a71a974a2f4527edb1b07105071755105edcb2af2f269facfb89180903a572a99b46456e80d4a01685a80b233278805f2c876678e731f4ec4f52075aeef6b2b023efbb8a3637ef507c4c37c27e428152ec1817fcba640ad601cb09f72f0fbe2d274a2410203010001a321301f301d0603551d0e04160414c28bf33dd5a9a17338e5b1d1a6edd8c7d141ed0b300d06092a864886f70d01010b0500038202010084e20458b2aafd7fc27146b0986f9324f4260f244920417a77c9bf15e2e2d22d2725bdd8093ec261c3779c3ca03312516506f9410075b90595b41345956d8eb2786fb5994f195611382c2b99dba13381b0100a30bc9e6e47248bf4325e2f6eec9d789216dc7536e753bf1f4be603d9fa2e6f5e192b4eb988b8cdb0bb1e8668a9225426f7d4636479f73ed24ad1d2657c31e63c93d9679b9080171b3bd1bf10a3b92b80bd790fbf62d3644900cd08eae8b9bf9c2567be98dc8cdd2ae19a8d57a3e3e2de899f81f1279f578989e6af906f80c8c2b67651730ee7e568c1af5bcb845b6d685dc55332a9984aeceaea3b7e883447edf1c76b155d95253e39b9710eaa22efa6c81468829702b5dce7126538f3ca70c2f0ad9a5795435fdb1f715f20d60359ef9a9926c7050116e802df651727447848827815f70bd82af3cedd08783156102d2d8ce995c4c43b8e47e91a3e6927f3505a5d395e6bebb84542c570903eeab4382a1c2151f1471c7a06a34dc4d268d8fa72e93bdcd2dccc4302ecac47b9e7e3d8bc9b46d21cd097874a24d529548018dc190ff568c6aa428f0a5eedff1a347730931c74f19277538e49647a4ad7254f4c1ec7d4da12cce9e1fad9607534e66ab40a56b473d9d7e3d563fd03cad2052bad365c5a29f8ae54f09b60dbca3ea768d7767cbe1c133ca08ce725c1c1370f4aab8e5b6e286f52dc0be8d0982b5a" timestamp="1676634233" url="https://MyFirstFDroidRepo.org/fdroid/repo" version="20002">
<description>This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/fdroid.</description>
<mirror>http://foobarfoobarfoobar.onion/fdroid/repo</mirror>
<mirror>https://foo.bar/fdroid/repo</mirror>

View File

@ -300,9 +300,9 @@ v1timestamp=`$sed -n -e 's,.*"timestamp": \([0-9][0-9][0-9][0-9][0-9][0-9][0-9][
test $v0timestamp -eq $v1timestamp
# we can't easily reproduce the timestamps for things, so just hardcode them
$sed -i.tmp -e 's,timestamp="[0-9]*",timestamp="1480431575",' repo/index.xml
$sed -i.tmp -e 's,timestamp="[0-9]*",timestamp="1676634233",' repo/index.xml
diff -uw $WORKSPACE/tests/repo/index.xml repo/index.xml
sed -i --expression='s,"timestamp": [0-9]*,"timestamp": 1502845383782,' repo/index-v1.json
sed -i --expression='s,"timestamp": [0-9]*,"timestamp": 1676634233000,' repo/index-v1.json
diff -uw $WORKSPACE/tests/repo/index-v1.json repo/index-v1.json

View File

@ -18,7 +18,7 @@ print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import apksigcopier, common, signindex, update
from fdroidserver import apksigcopier, common, exception, signindex, update
from pathlib import Path
from unittest.mock import patch
@ -69,6 +69,68 @@ class SignindexTest(unittest.TestCase):
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(str(self.repodir), 'index-v1.json')
def test_sign_entry(self):
entry = 'repo/entry.json'
v2 = 'repo/index-v2.json'
shutil.copy(self.basedir / entry, entry)
shutil.copy(self.basedir / v2, v2)
signindex.sign_index(self.repodir, 'entry.json')
self.assertTrue((self.repodir / 'entry.jar').exists())
def test_sign_entry_corrupt(self):
"""sign_index should exit with error if entry.json is bad JSON"""
entry = 'repo/entry.json'
with open(entry, 'w') as fp:
fp.write('{')
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_sign_entry_corrupt_leave_entry_jar(self):
"""sign_index should not touch existing entry.jar if entry.json is corrupt"""
existing = 'repo/entry.jar'
testvalue = "Don't touch!"
with open(existing, 'w') as fp:
fp.write(testvalue)
with open('repo/entry.json', 'w') as fp:
fp.write('{')
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
with open(existing) as fp:
self.assertEqual(testvalue, fp.read())
def test_sign_corrupt_index_v2_json(self):
"""sign_index should exit with error if index-v2.json JSON is corrupt"""
with open('repo/index-v2.json', 'w') as fp:
fp.write('{"key": "not really an index"')
good_entry = {
"timestamp": 1676583021000,
"version": 20002,
"index": {
"name": "/index-v2.json",
"sha256": common.sha256sum('repo/index-v2.json'),
"size": os.path.getsize('repo/index-v2.json'),
"numPackages": 0,
},
}
with open('repo/entry.json', 'w') as fp:
json.dump(good_entry, fp)
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_sign_index_v2_corrupt_sha256(self):
"""sign_index should exit with error if SHA-256 of file in entry is wrong"""
entry = 'repo/entry.json'
v2 = 'repo/index-v2.json'
shutil.copy(self.basedir / entry, entry)
shutil.copy(self.basedir / v2, v2)
with open(v2, 'a') as fp:
fp.write(' ')
with self.assertRaises(exception.FDroidException, msg='error on bad SHA-256'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_signindex(self):
if common.find_apksigner({}) is None: # TODO remove me for buildserver-bullseye
self.skipTest('SKIPPING test_signindex, apksigner not installed!')

View File

@ -1,3 +1,4 @@
com.example.test.helloworld_1.apk com.example.test.helloworld 2023-02-17
com.politedroid_3.apk com.politedroid 2017-06-23
com.politedroid_4.apk com.politedroid 2017-06-23
com.politedroid_5.apk com.politedroid 2017-06-23
@ -14,3 +15,4 @@ 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
souch.smsbypass_9.apk souch.smsbypass 2018-04-26
urzip-; Рахма́, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢·.apk info.guardianproject.urzip 2016-06-23
v1.v2.sig_1020.apk v1.v2.sig 2023-02-17