# -*- coding: utf-8 -*- import binascii import hashlib import random import time import zlib from collections import OrderedDict from math import floor from .. import devices from .tclrequest import TclRequest from .tclresult import DownloadResult VDKEY_B64Z = b"eJwdjwEOwDAIAr8kKFr//7HhmqXp8AIIDrYAgg8byiUXrwRJRXja+d6iNxu0AhUooDCN9rd6rDLxmGIakUVWo3IGCTRWqCAt6X4jGEIUAxgN0eYWnp+LkpHQAg/PsO90ELsy0Npm/n2HbtPndFgGEV31R9OmT4O4nrddjc3Qt6nWscx7e+WRHq5UnOudtjw5skuV09pFhvmqnOEIs4ljPeel1wfLYUF4\n" def get_salt(): """Generate cryptographic salt.""" millis = floor(time.time() * 1000) tail = "{:06d}".format(random.randint(0, 999999)) return "{}{}".format(str(millis), tail) def get_vk2(params_dict, cltp): """Generate salted hash of API parameters.""" params_dict["cltp"] = cltp query = "" for key, val in params_dict.items(): if query: query += "&" query += key + "=" + str(val) vdk = zlib.decompress(binascii.a2b_base64(VDKEY_B64Z)) query += vdk.decode("utf-8") engine = hashlib.sha1() engine.update(bytes(query, "utf-8")) hexhash = engine.hexdigest() return hexhash class DownloadRequest(TclRequest): def __init__(self, device: devices.Device, tvver: str, fw_id: str): super().__init__() self.uri = "/download_request.php" self.method = "POST" self.device = device self.tvver = tvver self.fw_id = fw_id def get_headers(self): return {"User-Agent": self.device.ua} def get_params(self): params = OrderedDict() params["id"] = self.device.imei params["salt"] = get_salt() params["curef"] = self.device.curef params["fv"] = self.device.fwver params["tv"] = self.tvver params["type"] = self.device.type params["fw_id"] = self.fw_id params["mode"] = self.device.mode params["vk"] = get_vk2(params, self.device.cltp) params["cltp"] = self.device.cltp params["cktp"] = self.device.cktp params["rtd"] = self.device.rtd if self.device.mode == self.device.MODE_STATES["FULL"]: params["foot"] = 1 params["chnl"] = self.device.chnl return params def is_done(self, http_status: int, contents: str) -> bool: if http_status == 200: self.response = contents self.result = DownloadResult(contents) self.success = True return True elif http_status not in [500, 502, 503]: # Errors OTHER than 500, 502 or 503 are probably # errors where we don't need to retry self.error = "HTTP {}".format(http_status) self.success = False return True return False