You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
#!/usr/bin/env python2.7
|
|
|
|
import os
|
|
import sys
|
|
import glob
|
|
import shutil
|
|
import urllib2
|
|
import hashlib
|
|
import subprocess
|
|
|
|
|
|
EXTERNAL_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
if os.path.exists("/init.qcom.rc"):
|
|
# android
|
|
APKPATCH = os.path.join(EXTERNAL_PATH, 'tools/apkpatch_android')
|
|
SIGNAPK = os.path.join(EXTERNAL_PATH, 'tools/signapk_android')
|
|
else:
|
|
APKPATCH = os.path.join(EXTERNAL_PATH, 'tools/apkpatch')
|
|
SIGNAPK = os.path.join(EXTERNAL_PATH, 'tools/signapk')
|
|
|
|
APKS = {
|
|
'com.waze': {
|
|
'src': 'https://apkcache.s3.amazonaws.com/com.waze_1021278.apk',
|
|
'src_sha256': 'f00957e93e2389f9e30502ac54994b98ac769314b0963c263d4e8baa625ab0c2',
|
|
'patch': 'com.waze.apkpatch',
|
|
'out_sha256': 'fee880a91a44c738442cd05fd1b6d9b5817cbf755aa61c86325ada2bc443d5cf'
|
|
},
|
|
'com.spotify.music': {
|
|
'src': 'https://apkcache.s3.amazonaws.com/com.spotify.music_24382006.apk',
|
|
'src_sha256': '0610fea68ee7ba5f8e4e0732ad429d729dd6cbb8bc21222c4c99db6cb09fbff4',
|
|
'patch': 'com.spotify.music.apkpatch',
|
|
'out_sha256': '5a3d6f478c7e40403a98ccc8906d7e0ae12b06543b41f5df52149dd09c647c11'
|
|
},
|
|
}
|
|
|
|
def sha256_path(path):
|
|
with open(path, 'rb') as f:
|
|
return hashlib.sha256(f.read()).hexdigest()
|
|
|
|
def remove(path):
|
|
try:
|
|
os.remove(path)
|
|
except OSError:
|
|
pass
|
|
|
|
def process(download, patch):
|
|
# clean up any junk apks
|
|
for out_apk in glob.glob(os.path.join(EXTERNAL_PATH, 'out/*.apk')):
|
|
app = os.path.basename(out_apk)[:-4]
|
|
if app not in APKS:
|
|
print "remove junk", out_apk
|
|
remove(out_apk)
|
|
|
|
complete = True
|
|
for k,v in APKS.iteritems():
|
|
apk_path = os.path.join(EXTERNAL_PATH, 'out', k+'.apk')
|
|
print "checking", apk_path
|
|
if os.path.exists(apk_path) and sha256_path(apk_path) == v['out_sha256']:
|
|
# nothing to do
|
|
continue
|
|
|
|
complete = False
|
|
|
|
remove(apk_path)
|
|
|
|
src_path = os.path.join(EXTERNAL_PATH, 'src', v['src_sha256'])
|
|
if not os.path.exists(src_path) or sha256_path(src_path) != v['src_sha256']:
|
|
if not download:
|
|
continue
|
|
|
|
print "downloading", v['src'], "to", src_path
|
|
# download it
|
|
resp = urllib2.urlopen(v['src'])
|
|
data = resp.read()
|
|
with open(src_path, 'wb') as src_f:
|
|
src_f.write(data)
|
|
|
|
if sha256_path(src_path) != v['src_sha256']:
|
|
print "download was corrupted..."
|
|
continue
|
|
|
|
if not patch:
|
|
continue
|
|
|
|
# ignoring lots of TOCTTOU here...
|
|
|
|
apk_temp = "/tmp/"+k+".patched"
|
|
remove(apk_temp)
|
|
apk_temp2 = "/tmp/"+k+".signed"
|
|
remove(apk_temp2)
|
|
|
|
try:
|
|
print "patching", v['patch']
|
|
subprocess.check_call([APKPATCH, 'apply', src_path, apk_temp, os.path.join(EXTERNAL_PATH, v['patch'])])
|
|
print "signing", apk_temp
|
|
subprocess.check_call([SIGNAPK,
|
|
os.path.join(EXTERNAL_PATH, 'tools/certificate.pem'), os.path.join(EXTERNAL_PATH, 'tools/key.pk8'),
|
|
apk_temp, apk_temp2])
|
|
|
|
out_sha256 = sha256_path(apk_temp2) if os.path.exists(apk_temp2) else None
|
|
|
|
if out_sha256 == v['out_sha256']:
|
|
print "done", apk_path
|
|
shutil.move(apk_temp2, apk_path)
|
|
else:
|
|
print "patch was corrupted", apk_temp2, out_sha256
|
|
finally:
|
|
remove(apk_temp)
|
|
remove(apk_temp2)
|
|
|
|
return complete
|
|
|
|
if __name__ == "__main__":
|
|
ret = True
|
|
if len(sys.argv) == 2 and sys.argv[1] == "download":
|
|
ret = process(True, False)
|
|
elif len(sys.argv) == 2 and sys.argv[1] == "patch":
|
|
ret = process(False, True)
|
|
else:
|
|
ret = process(True, True)
|
|
sys.exit(0 if ret else 1)
|
|
|