import acrort
import tempfile
import os
import os.path
import json
import subprocess
import stat
import shutil
import urllib.request
import urllib.parse
_CHUNK_SIZE = 16384
def _get_filename(response):
for element in response.getheader('Content-Disposition', '').split():
parts = element.split('=')
if parts[0].lower() == 'filename':
return parts[1][1:-1]
filename = os.path.basename(urllib.parse.urlparse(response.url).path)
return filename or 'unknown'
def _download_file(url, destination_dir, capath=None):
response = urllib.request.urlopen(url, capath=capath)
filename = _get_filename(response)
with open(os.path.join(destination_dir, filename), mode='wb') as f:
data = response.read(_CHUNK_SIZE)
while data:
f.write(data)
data = response.read(_CHUNK_SIZE)
def _open_file(url, capath=None):
response = urllib.request.urlopen(url, capath=capath)
return response.readall()
def _get_url_scheme(url):
return urllib.parse.urlparse(url).scheme
def _update(config_url, capath=None):
if _get_url_scheme(config_url) != 'https':
raise Exception('Only https urls are supported')
update_config = json.loads(_open_file(config_url, capath=capath).decode()) #utf8 expected
file_list = update_config.get('files')
if not file_list:
raise Exception('Update config contains no files.')
start = update_config.get("start")
if not start:
raise Exception('Update config contains no entry point.')
temp_dir = tempfile.mkdtemp(prefix='acroupdate')
try:
for file_url in file_list:
if _get_url_scheme(file_url) != 'https':
raise Exception('Only https urls are supported')
_download_file(file_url, temp_dir, capath=capath)
file_to_exec = os.path.join(temp_dir, start[0])
start[0] = file_to_exec
os.chmod(file_to_exec, stat.S_IXUSR | stat.S_IRUSR)
subprocess.Popen(start, cwd=temp_dir)
except:
shutil.rmtree(temp_dir)
raise
def _get_cert_path():
hive = acrort.registry.open_system_hive(hive=acrort.registry.HIVE_HKLM)
curl_key = hive.subkeys.get(
key_name='Software\\{}\\BackupAndRecovery\\Settings\\Curl'.format(acrort.common.BRAND_NAME))
if curl_key:
val = curl_key.values.get(value_name='CaCertificatesLocation')
if val:
return val.data
def start_command(*args, **kwargs):
""" The command expects update configuration url as input.
Update configuration is a json of form:
{
"files": ["url1", "url2", ....],
"start": ["executable_file", "arg1", "arg2", ....]
}
"""
ctx = acrort.remoting.CommandContext(*args, **kwargs)
_update(ctx.argument.ref, capath=_get_cert_path())
|