Passed
Push — master ( 816317...cc1553 )
by John
03:01
created

bbarchivist.networkutilstcl.check_prep()   A

Complexity

Conditions 1

Size

Total Lines 32
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 8
dl 0
loc 32
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
#!/usr/bin/env python3
2 5
"""This module is used for network connections for TCL tools."""
3
4 5
import base64  # encoding
5 5
import binascii  # encoding
6 5
import hashlib  # salt
7 5
import random  # salt
8 5
import time  # salt
9 5
import zlib  # encoding
10
11 5
import requests  # downloading
12 5
from bbarchivist import networkutils  # network tools
13 5
from bbarchivist import xmlutilstcl  # xml work
14 5
from bbarchivist.bbconstants import TCLMASTERS  # lookup servers
15
16 5
__author__ = "Thurask"
17 5
__license__ = "WTFPL v2"
18 5
__copyright__ = "2018 Thurask"
19
20
21 5
def tcl_master():
22
    """
23
    Get a random master server.
24
    """
25 5
    return random.choice(TCLMASTERS)
26
27
28 5
def tcl_default_id(devid):
29
    """
30
    Get an IMEI or a serial number or something.
31
32
    :param devid: Return default if this is None.
33
    :type devid: str
34
    """
35 5
    if devid is None:
36 5
        devid = "543212345000000"
37 5
    return devid
38
39
40 5
def check_prep(curef, mode=4, fvver="AAA000", cltp=2010, cktp=2, rtd=1, chnl=2, devid=None):
41
    """
42
    Prepare variables for TCL update check.
43
44
    :param curef: PRD of the phone variant to check.
45
    :type curef: str
46
47
    :param mode: 4 if downloading autoloaders, 2 if downloading OTA deltas.
48
    :type mode: int
49
50
    :param fvver: Initial software version, must be specific if downloading OTA deltas.
51
    :type fvver: str
52
53
    :param cltp: 2010 to always show latest version, 10 to show actual updates. Default is 2010.
54
    :type cltp: int
55
56
    :param cktp: 2 if checking manually, 1 if checking automatically. Default is 2.
57
    :type cktp: int
58
59
    :param rtd: 2 if rooted, 1 if not. Default is 1.
60
    :type rtd: int
61
62
    :param chnl: 2 if checking on WiFi, 1 if checking on mobile. Default is 2.
63
    :type chnl: int
64
65
    :param devid: Serial number/IMEI. Default is fake, not that it matters.
66
    :type devid: str
67
    """
68 5
    devid = tcl_default_id(devid)
69 5
    geturl = "http://{0}/check.php".format(tcl_master())
70 5
    params = {"id": devid, "curef": curef, "fv": fvver, "mode": mode, "type": "Firmware", "cltp": cltp, "cktp": cktp, "rtd": rtd, "chnl": chnl}
71 5
    return geturl, params
72
73
74 5
@networkutils.pem_wrapper
75 5
@networkutils.try_try_again
76 5
def tcl_check(curef, session=None, mode=4, fvver="AAA000", export=False):
77
    """
78
    Check TCL server for updates.
79
80
    :param curef: PRD of the phone variant to check.
81
    :type curef: str
82
83
    :param session: Requests session object, default is created on the fly.
84
    :type session: requests.Session()
85
86
    :param mode: 4 if downloading autoloaders, 2 if downloading OTA deltas.
87
    :type mode: int
88
89
    :param fvver: Initial software version, must be specific if downloading OTA deltas.
90
    :type fvver: str
91
92
    :param export: Whether to export XML response to file. Default is False.
93
    :type export: bool
94
    """
95 5
    sess = networkutils.generic_session(session)
96 5
    geturl, params = check_prep(curef, mode, fvver)
97 5
    req = sess.get(geturl, params=params)
98 5
    if req.status_code == 200:
99 5
        req.encoding = "utf-8"
100 5
        response = req.text
101 5
        if export:
102 5
            salt = tcl_salt()
103 5
            xmlutilstcl.dump_tcl_xml(response, salt)
104
    else:
105 5
        response = None
106 5
    return response
107
108
109 5
def tcl_salt():
110
    """
111
    Generate salt value for TCL server tools.
112
    """
113 5
    millis = round(time.time() * 1000)
114 5
    tail = "{0:06d}".format(random.randint(0, 999999))
115 5
    return "{0}{1}".format(str(millis), tail)
116
117
118 5
def unpack_vdkey():
119
    """
120
    Draw the curtain back.
121
    """
122 5
    vdkey = b"eJwdjwEOwDAIAr8kKFr//7HhmqXp8AIIDrYAgg8byiUXrwRJRXja+d6iNxu0AhUooDCN9rd6rDLxmGIakUVWo3IGCTRWqCAt6X4jGEIUAxgN0eYWnp+LkpHQAg/PsO90ELsy0Npm/n2HbtPndFgGEV31R9OmT4O4nrddjc3Qt6nWscx7e+WRHq5UnOudtjw5skuV09pFhvmqnOEIs4ljPeel1wfLYUF4\n"
123 5
    vdk = zlib.decompress(binascii.a2b_base64(vdkey))
124 5
    return vdk.decode("utf-8")
125
126
127 5
def vkhash(curef, tvver, fwid, salt, mode=4, fvver="AAA000", cltp=2010, devid=None):
128
    """
129
    Generate hash from TCL update server variables.
130
131
    :param curef: PRD of the phone variant to check.
132
    :type curef: str
133
134
    :param tvver: Target software version.
135
    :type tvver: str
136
137
    :param fwid: Firmware ID for desired download file.
138
    :type fwid: str
139
140
    :param salt: Salt hash.
141
    :type salt: str
142
143
    :param mode: 4 if downloading autoloaders, 2 if downloading OTA deltas.
144
    :type mode: int
145
146
    :param fvver: Initial software version, must be specific if downloading OTA deltas.
147
    :type fvver: str
148
149
    :param cltp: 2010 to always show latest version, 10 to show actual updates. Default is 2010.
150
    :type cltp: int
151
152
    :param devid: Serial number/IMEI. Default is fake, not that it matters.
153
    :type devid: str
154
    """
155 5
    vdk = unpack_vdkey()
156 5
    devid = tcl_default_id(devid)
157 5
    query = "id={0}&salt={1}&curef={2}&fv={3}&tv={4}&type={5}&fw_id={6}&mode={7}&cltp={8}{9}".format(devid, salt, curef, fvver, tvver, "Firmware", fwid, mode, cltp, vdk)
158 5
    engine = hashlib.sha1()
159 5
    engine.update(bytes(query, "utf-8"))
160 5
    return engine.hexdigest()
161
162
163 5
def download_request_prep(curef, tvver, fwid, salt, vkh, mode=4, fvver="AAA000", cltp=2010, devid=None):
164
    """
165
    Prepare variables for download server check.
166
167
    :param curef: PRD of the phone variant to check.
168
    :type curef: str
169
170
    :param tvver: Target software version.
171
    :type tvver: str
172
173
    :param fwid: Firmware ID for desired download file.
174
    :type fwid: str
175
176
    :param salt: Salt hash.
177
    :type salt: str
178
179
    :param vkh: VDKey-based hash.
180
    :type vkh: str
181
182
    :param mode: 4 if downloading autoloaders, 2 if downloading OTA deltas.
183
    :type mode: int
184
185
    :param fvver: Initial software version, must be specific if downloading OTA deltas.
186
    :type fvver: str
187
188
    :param cltp: 2010 to always show latest version, 10 to show actual updates. Default is 2010.
189
    :type cltp: int
190
191
    :param devid: Serial number/IMEI. Default is fake, not that it matters.
192
    :type devid: str
193
    """
194 5
    devid = tcl_default_id(devid)
195 5
    posturl = "http://{0}/download_request.php".format(tcl_master())
196 5
    params = {"id": devid, "curef": curef, "fv": fvver, "mode": mode, "type": "Firmware", "tv": tvver, "fw_id": fwid, "salt": salt, "vk": vkh, "cltp": cltp}
197 5
    if mode == 4:
198 5
        params["foot"] = 1
199 5
    return posturl, params
200
201
202 5
@networkutils.pem_wrapper
203 5
@networkutils.try_try_again
204 5
def tcl_download_request(curef, tvver, fwid, salt, vkh, session=None, mode=4, fvver="AAA000", export=False):
205
    """
206
    Check TCL server for download URLs.
207
208
    :param curef: PRD of the phone variant to check.
209
    :type curef: str
210
211
    :param tvver: Target software version.
212
    :type tvver: str
213
214
    :param fwid: Firmware ID for desired download file.
215
    :type fwid: str
216
217
    :param salt: Salt hash.
218
    :type salt: str
219
220
    :param vkh: VDKey-based hash.
221
    :type vkh: str
222
223
    :param session: Requests session object, default is created on the fly.
224
    :type session: requests.Session()
225
226
    :param mode: 4 if downloading autoloaders, 2 if downloading OTA deltas.
227
    :type mode: int
228
229
    :param fvver: Initial software version, must be specific if downloading OTA deltas.
230
    :type fvver: str
231
232
    :param export: Whether to export XML response to file. Default is False.
233
    :type export: bool
234
    """
235 5
    sess = networkutils.generic_session(session)
236 5
    posturl, params = download_request_prep(curef, tvver, fwid, salt, vkh, mode, fvver)
237 5
    req = sess.post(posturl, data=params)
238 5
    if req.status_code == 200:
239 5
        req.encoding = "utf-8"
240 5
        response = req.text
241 5
        if export:
242 5
            xmlutilstcl.dump_tcl_xml(response, salt)
243
    else:
244 5
        response = None
245 5
    return response
246
247
248 5
def encrypt_header_prep(address, encslave):
249
    """
250
    Prepare variables for encrypted header check.
251
252
    :param address: File URL minus host.
253
    :type address: str
254
255
    :param encslave: Server hosting header script.
256
    :type encslave: str
257
    """
258 5
    encs = {b"YWNjb3VudA==" : b"emhlbmdodWEuZ2Fv", b"cGFzc3dvcmQ=": b"cWFydUQ0b2s="}
259 5
    params = {base64.b64decode(key): base64.b64decode(val) for key, val in encs.items()}
260 5
    params[b"address"] = bytes(address, "utf-8")
261 5
    posturl = "http://{0}/encrypt_header.php".format(encslave)
262 5
    return posturl, params
263
264
265 5
@networkutils.pem_wrapper
266 5
def encrypt_header(address, encslave, session=None):
267
    """
268
    Check encrypted header.
269
270
    :param address: File URL minus host.
271
    :type address: str
272
273
    :param encslave: Server hosting header script.
274
    :type encslave: str
275
276
    :param session: Requests session object, default is created on the fly.
277
    :type session: requests.Session()
278
    """
279 5
    sess = networkutils.generic_session(session)
280 5
    posturl, params = encrypt_header_prep(address, encslave)
281 5
    req = sess.post(posturl, data=params)
282 5
    if req.status_code == 206:  # partial
283 5
        contentlength = int(req.headers["Content-Length"])
284 5
        sentinel = "HEADER FOUND" if contentlength == 4194320 else "NO HEADER FOUND"
285
    else:
286 5
        sentinel = None
287 5
    return sentinel
288
289
290 5
@networkutils.pem_wrapper
291
def remote_prd_info():
292
    """
293
    Get list of remote OTA versions.
294
    """
295 5
    dburl = "https://tclota.birth-online.de/json_lastupdates.php"
296 5
    req = requests.get(dburl)
297 5
    reqj = req.json()
298 5
    otadict = {val["curef"]: val["last_ota"] for val in reqj.values() if val["last_ota"] is not None}
299
    return otadict
300