diff --git a/.gitignore b/.gitignore
index b92ef773..be36e374 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,9 +36,12 @@ makebuildserver.config.py
/tests/archive/categories.txt
/tests/archive/icons*
/tests/archive/index.jar
+/tests/archive/index_unsigned.jar
/tests/archive/index.xml
/tests/archive/index-v1.jar
+/tests/archive/index-v1.json
/tests/repo/index.jar
+/tests/repo/index_unsigned.jar
/tests/repo/index-v1.jar
/tests/repo/info.guardianproject.urzip/
/tests/repo/info.guardianproject.checkey/en-US/phoneScreenshots/checkey-phone.png
diff --git a/fdroidserver/update.py b/fdroidserver/update.py
index 830a2252..ebd29a2c 100644
--- a/fdroidserver/update.py
+++ b/fdroidserver/update.py
@@ -1181,6 +1181,46 @@ def scan_apk_aapt(apk, apkfile):
apk['icons_src'] = _get_apk_icons_src(apkfile, icon_name)
+def _ensure_final_value(packageName, arsc, value):
+ """Ensure incoming value is always the value, not the resid
+
+ androguard will sometimes return the Android "resId" aka
+ Resource ID instead of the actual value. This checks whether
+ the value is actually a resId, then performs the Android
+ Resource lookup as needed.
+
+ """
+ if value:
+ returnValue = value
+ if value[0] == '@':
+ try: # can be a literal value or a resId
+ res_id = int(value.replace("@", "0x"), 16)
+ res_id = arsc.get_id(packageName, res_id)[1]
+ returnValue = arsc.get_string(packageName, res_id)[1]
+ except ValueError:
+ pass
+ return returnValue
+
+
+def _sanitize_sdk_version(value):
+ """Sanitize the raw values from androguard to handle bad values
+
+ minSdkVersion/targetSdkVersion/maxSdkVersion must be integers,
+ but that doesn't stop devs from doing strange things like
+ setting them using Android XML strings.
+
+ https://gitlab.com/souch/SMSbypass/blob/v0.9/app/src/main/AndroidManifest.xml#L29
+ https://gitlab.com/souch/SMSbypass/blob/v0.9/app/src/main/res/values/strings.xml#L27
+ """
+ try:
+ sdk_version = int(value)
+ if sdk_version > 0:
+ return str(sdk_version) # heinous, but this is still str in the codebase
+ except (TypeError, ValueError):
+ pass
+ return None
+
+
def scan_apk_androguard(apk, apkfile):
try:
from androguard.core.bytecodes.apk import APK
@@ -1210,23 +1250,20 @@ def scan_apk_androguard(apk, apkfile):
apk['versionCode'] = int(apkobject.get_androidversion_code())
apk['name'] = apkobject.get_app_name()
- versionName = apkobject.get_androidversion_name()
- if versionName:
- apk['versionName'] = versionName
- if versionName[0] == '@':
- try: # can be a literal value or a resId
- res_id = int(versionName.replace("@", "0x"), 16)
- res_id = arsc.get_id(apk['packageName'], res_id)[1]
- apk['versionName'] = arsc.get_string(apk['packageName'], res_id)[1]
- except ValueError:
- pass
+ apk['versionName'] = _ensure_final_value(apk['packageName'], arsc,
+ apkobject.get_androidversion_name())
- if apkobject.get_max_sdk_version() is not None:
- apk['maxSdkVersion'] = apkobject.get_max_sdk_version()
- if apkobject.get_min_sdk_version() is not None:
- apk['minSdkVersion'] = apkobject.get_min_sdk_version()
- if apkobject.get_target_sdk_version() is not None:
- apk['targetSdkVersion'] = apkobject.get_target_sdk_version()
+ minSdkVersion = _sanitize_sdk_version(apkobject.get_min_sdk_version())
+ if minSdkVersion is not None:
+ apk['minSdkVersion'] = minSdkVersion
+
+ targetSdkVersion = _sanitize_sdk_version(apkobject.get_target_sdk_version())
+ if targetSdkVersion is not None:
+ apk['targetSdkVersion'] = targetSdkVersion
+
+ maxSdkVersion = _sanitize_sdk_version(apkobject.get_max_sdk_version())
+ if maxSdkVersion is not None:
+ apk['maxSdkVersion'] = maxSdkVersion
icon_id_str = apkobject.get_element("application", "icon")
if icon_id_str:
diff --git a/tests/metadata/souch.smsbypass.txt b/tests/metadata/souch.smsbypass.txt
new file mode 100644
index 00000000..6b16e050
--- /dev/null
+++ b/tests/metadata/souch.smsbypass.txt
@@ -0,0 +1,52 @@
+Categories:Phone & SMS
+License:GPL-3.0
+Web Site:https://gitlab.com/souch/SMSbypass
+Source Code:https://gitlab.com/souch/SMSbypass/tree/HEAD
+Issue Tracker:https://gitlab.com/souch/SMSbypass/issues
+Donate:http://rodolphe.souchaud.free.fr/donate
+FlattrID:cad90e036b975ed129a3ce80a0750466
+
+Auto Name:Battery level
+Summary:Filter SMS and show them in a fake app
+Description:
+In order to keep away curious eyes, SMS-bypass filters incoming SMS messages
+before they reach your inbox. Based on bughunter2.smsfilter.
+
+Features:
+
+* Discrete fake app "Battery level": Long tap on Battery percentage will show SMS.
+* 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
+* Add contact from contact list
+* Export messages to a text file
+.
+
+Repo Type:git
+Repo:https://gitlab.com/souch/SMSbypass.git
+
+Build:0.8,5
+ commit=v0.8
+ subdir=app
+ gradle=yes
+ prebuild=sed -i -e '/minSdkVersion/amaxSdkVersion 19\n' build.gradle
+
+Build:0.8b,6
+ disable=don't build, just use as template for AUM, correct VC is 8
+ commit=2bd6164ff6391906af2af2b484de69a4ff926a01
+ subdir=app
+ gradle=yes
+
+Build:0.8.1,8
+ disable=mistagged
+ commit=v0.8.1
+ subdir=app
+ gradle=yes
+
+Build:0.9,9
+ commit=v0.9
+ subdir=app
+ gradle=yes
+
+Auto Update Mode:Version v%v
+Update Check Mode:Tags
+Current Version:0.9
+Current Version Code:9
diff --git a/tests/repo/index-v1.json b/tests/repo/index-v1.json
index cda10cf2..912f610c 100644
--- a/tests/repo/index-v1.json
+++ b/tests/repo/index-v1.json
@@ -21,6 +21,26 @@
]
},
"apps": [
+ {
+ "categories": [
+ "Phone & SMS"
+ ],
+ "suggestedVersionName": "0.9",
+ "suggestedVersionCode": "9",
+ "description": "
In order to keep away curious eyes, SMS-bypass filters incoming SMS messages before they reach your inbox. Based on bughunter2.smsfilter.
Features:
Discrete fake app \"Battery level\": Long tap on Battery percentage will show SMS.
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
Add contact from contact list
Export messages to a text file
",
+ "donate": "http://rodolphe.souchaud.free.fr/donate",
+ "flattrID": "cad90e036b975ed129a3ce80a0750466",
+ "issueTracker": "https://gitlab.com/souch/SMSbypass/issues",
+ "license": "GPL-3.0",
+ "name": "Battery level",
+ "sourceCode": "https://gitlab.com/souch/SMSbypass/tree/HEAD",
+ "summary": "Filter SMS and show them in a fake app",
+ "webSite": "https://gitlab.com/souch/SMSbypass",
+ "added": 1524700800000,
+ "icon": "souch.smsbypass.9.png",
+ "packageName": "souch.smsbypass",
+ "lastUpdated": 1524700800000
+ },
{
"categories": [
"tests"
@@ -525,6 +545,48 @@
"versionCode": 1619,
"versionName": "0.1"
}
+ ],
+ "souch.smsbypass": [
+ {
+ "added": 1524700800000,
+ "apkName": "souch.smsbypass_9.apk",
+ "hash": "80b0ae68a1189baa3ee6717092e3dbf1a4210165f7f7e5f2f9616bd63a2ec01d",
+ "hashType": "sha256",
+ "minSdkVersion": "8",
+ "packageName": "souch.smsbypass",
+ "sig": "e50c99753cd45e2736d52cb49be07581",
+ "signer": "d3aec784b1fd71549fc22c999789122e3639895db6bd585da5835fbe3db6985c",
+ "size": 81295,
+ "targetSdkVersion": "18",
+ "uses-permission": [
+ [
+ "android.permission.RECEIVE_SMS",
+ null
+ ],
+ [
+ "android.permission.SEND_SMS",
+ null
+ ],
+ [
+ "android.permission.READ_CONTACTS",
+ null
+ ],
+ [
+ "android.permission.WRITE_EXTERNAL_STORAGE",
+ null
+ ],
+ [
+ "android.permission.VIBRATE",
+ null
+ ],
+ [
+ "android.permission.READ_EXTERNAL_STORAGE",
+ null
+ ]
+ ],
+ "versionCode": 9,
+ "versionName": "0.9"
+ }
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/repo/index.xml b/tests/repo/index.xml
index ef6988de..9b6ef50a 100644
--- a/tests/repo/index.xml
+++ b/tests/repo/index.xml
@@ -8,6 +8,37 @@
+
+ souch.smsbypass
+ 2018-04-26
+ 2018-04-26
+ Battery level
+ Filter SMS and show them in a fake app
+ souch.smsbypass.9.png
+ <p>In order to keep away curious eyes, SMS-bypass filters incoming SMS messages before they reach your inbox. Based on bughunter2.smsfilter.</p><p>Features:</p><ul><li> Discrete fake app "Battery level": Long tap on Battery percentage will show SMS.</li><li> 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</li><li> Add contact from contact list</li><li> Export messages to a text file</li></ul>
+ GPL-3.0
+ Phone & SMS
+ Phone & SMS
+ https://gitlab.com/souch/SMSbypass
+
+ https://gitlab.com/souch/SMSbypass/issues
+ http://rodolphe.souchaud.free.fr/donate
+ cad90e036b975ed129a3ce80a0750466
+ 0.9
+ 9
+
+ 0.9
+ 9
+ souch.smsbypass_9.apk
+ 80b0ae68a1189baa3ee6717092e3dbf1a4210165f7f7e5f2f9616bd63a2ec01d
+ 81295
+ 8
+ 18
+ 2018-04-26
+ e50c99753cd45e2736d52cb49be07581
+ READ_CONTACTS,READ_EXTERNAL_STORAGE,RECEIVE_SMS,SEND_SMS,VIBRATE,WRITE_EXTERNAL_STORAGE
+
+ duplicate.permisssions2017-12-22
diff --git a/tests/repo/souch.smsbypass_9.apk b/tests/repo/souch.smsbypass_9.apk
new file mode 100644
index 00000000..ce96f299
Binary files /dev/null and b/tests/repo/souch.smsbypass_9.apk differ
diff --git a/tests/stats/known_apks.txt b/tests/stats/known_apks.txt
index ef90c797..392c68ff 100644
--- a/tests/stats/known_apks.txt
+++ b/tests/stats/known_apks.txt
@@ -10,4 +10,5 @@ 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
+souch.smsbypass_9.apk souch.smsbypass 2018-04-26
urzip-; Рахма́нинов, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢尔盖·.apk info.guardianproject.urzip 2016-06-23
diff --git a/tests/update.TestCase b/tests/update.TestCase
index eb59c3d0..f4e02e47 100755
--- a/tests/update.TestCase
+++ b/tests/update.TestCase
@@ -253,7 +253,7 @@ class UpdateTest(unittest.TestCase):
apps = fdroidserver.metadata.read_metadata(xref=True)
knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
- self.assertEqual(len(apks), 13)
+ self.assertEqual(len(apks), 14)
apk = apks[0]
self.assertEqual(apk['packageName'], 'com.politedroid')
self.assertEqual(apk['versionCode'], 3)
@@ -298,7 +298,12 @@ class UpdateTest(unittest.TestCase):
if os.path.basename(os.getcwd()) != 'tests':
raise Exception('This test must be run in the "tests/" subdir')
+ apk_info = fdroidserver.update.scan_apk('repo/souch.smsbypass_9.apk')
+ self.assertIsNone(apk_info.get('maxSdkVersion'))
+ self.assertEqual(apk_info.get('versionName'), '0.9')
+
apk_info = fdroidserver.update.scan_apk('repo/duplicate.permisssions_9999999.apk')
+ self.assertIsNone(apk_info.get('versionName'))
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_launcher.png',
'-1': 'res/drawable/ic_launcher.png'})
@@ -324,14 +329,17 @@ class UpdateTest(unittest.TestCase):
self.assertEqual(apk_info['targetSdkVersion'], '8')
apk_info = fdroidserver.update.scan_apk('org.bitbucket.tickytacky.mirrormirror_4.apk')
+ self.assertEqual(apk_info.get('versionName'), '1.0.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable-mdpi/mirror.png',
'-1': 'res/drawable-mdpi/mirror.png'})
apk_info = fdroidserver.update.scan_apk('repo/info.zwanenburg.caffeinetile_4.apk')
+ self.assertEqual(apk_info.get('versionName'), '1.3')
self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_coffee_on.xml',
'-1': 'res/drawable/ic_coffee_on.xml'})
apk_info = fdroidserver.update.scan_apk('repo/com.politedroid_6.apk')
+ self.assertEqual(apk_info.get('versionName'), '1.5')
self.assertEqual(apk_info['icons_src'], {'120': 'res/drawable-ldpi-v4/icon.png',
'160': 'res/drawable-mdpi-v4/icon.png',
'240': 'res/drawable-hdpi-v4/icon.png',
@@ -339,6 +347,7 @@ class UpdateTest(unittest.TestCase):
'-1': 'res/drawable-mdpi-v4/icon.png'})
apk_info = fdroidserver.update.scan_apk('SpeedoMeterApp.main_1.apk')
+ self.assertEqual(apk_info.get('versionName'), '1.0')
self.assertEqual(apk_info['icons_src'], {})
def test_scan_apk_no_sig(self):
@@ -549,7 +558,7 @@ class UpdateTest(unittest.TestCase):
knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
fdroidserver.update.translate_per_build_anti_features(apps, apks)
- self.assertEqual(len(apks), 13)
+ self.assertEqual(len(apks), 14)
foundtest = False
for apk in apks:
if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3: