bbarchivist.xmlutils.carrier_swver_get()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 1
dl 0
loc 10
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python3
2 5
"""This module is used for XML handling."""
3
4 5
import re  # regexes
5
6 5
try:
7 5
    from defusedxml import ElementTree  # safer XML parsing
8 1
except (ImportError, AttributeError):
9 1
    from xml.etree import ElementTree  # XML parsing
10
11 5
__author__ = "Thurask"
12 5
__license__ = "WTFPL v2"
13 5
__copyright__ = "2018-2019 Thurask"
14
15
16 5
def cchecker_get_tags(roottext):
17
    """
18
    Get country and carrier from XML.
19
20
    :param roottext: XML text.
21
    :type roottext: str
22
    """
23 5
    root = ElementTree.fromstring(roottext)
24 5
    for child in root:
25 5
        if child.tag == "country":
26 5
            country = child.get("name")
27 5
        if child.tag == "carrier":
28 5
            carrier = child.get("name")
29 5
    return country, carrier
30
31
32 5
def prep_available_bundle(device, npc):
33
    """
34
    Prepare bundle query XML.
35
36
    :param device: Hexadecimal hardware ID.
37
    :type device: str
38
39
    :param npc: MCC + MNC (see `func:bbarchivist.networkutils.return_npc`)
40
    :type npc: int
41
    """
42 5
    query = '<?xml version="1.0" encoding="UTF-8"?><availableBundlesRequest version="1.0.0" authEchoTS="1366644680359"><deviceId><pin>0x2FFFFFB3</pin></deviceId><clientProperties><hardware><id>0x{0}</id><isBootROMSecure>true</isBootROMSecure></hardware><network><vendorId>0x0</vendorId><homeNPC>0x{1}</homeNPC><currentNPC>0x{1}</currentNPC></network><software><currentLocale>en_US</currentLocale><legalLocale>en_US</legalLocale><osVersion>10.0.0.0</osVersion><radioVersion>10.0.0.0</radioVersion></software></clientProperties><updateDirectives><bundleVersionFilter></bundleVersionFilter></updateDirectives></availableBundlesRequest>'.format(device, npc)
43 5
    return query
44
45
46 5
def parse_available_bundle(roottext):
47
    """
48
    Get bundles from XML.
49
50
    :param roottext: XML text.
51
    :type roottext: str
52
    """
53 5
    root = ElementTree.fromstring(roottext)
54 5
    package = root.find('./data/content')
55 5
    bundlelist = [child.attrib["version"] for child in package]
56 5
    return bundlelist
57
58
59 5
def carrier_swver_get(root):
60
    """
61
    Get software release from carrier XML.
62
63
    :param root: ElementTree we're barking up.
64
    :type root: xml.etree.ElementTree.ElementTree
65
    """
66 5
    for child in root.iter("softwareReleaseMetadata"):
67 5
        swver = child.get("softwareReleaseVersion")
68 5
    return swver
69
70
71 5
def carrier_child_fileappend(child, files, baseurl, blitz=False):
72
    """
73
    Append bar file links to a list from a child element.
74
75
    :param child: Child element in use.
76
    :type child: xml.etree.ElementTree.Element
77
78
    :param files: Filelist.
79
    :type files: list(str)
80
81
    :param baseurl: Base URL, URL minus the filename.
82
    :type baseurl: str
83
84
    :param blitz: Whether or not to create a blitz package. False by default.
85
    :type blitz: bool
86
    """
87 5
    if not blitz:
88 5
        files.append(baseurl + child.get("path"))
89
    else:
90 5
        if child.get("type") not in ["system:radio", "system:desktop", "system:os"]:
91 5
            files.append(baseurl + child.get("path"))
92 5
    return files
93
94
95 5
def carrier_child_finder(root, files, baseurl, blitz=False):
96
    """
97
    Extract filenames, radio and OS from child elements.
98
99
    :param root: ElementTree we're barking up.
100
    :type root: xml.etree.ElementTree.ElementTree
101
102
    :param files: Filelist.
103
    :type files: list(str)
104
105
    :param baseurl: Base URL, URL minus the filename.
106
    :type baseurl: str
107
108
    :param blitz: Whether or not to create a blitz package. False by default.
109
    :type blitz: bool
110
    """
111 5
    osver = radver = ""
112 5
    for child in root.iter("package"):
113 5
        files = carrier_child_fileappend(child, files, baseurl, blitz)
114 5
        if child.get("type") == "system:radio":
115 5
            radver = child.get("version")
116 5
        elif child.get("type") == "system:desktop":
117 5
            osver = child.get("version")
118 5
        elif child.get("type") == "system:os":
119 5
            osver = child.get("version")
120 5
    return osver, radver, files
121
122
123 5
def parse_carrier_xml(data, blitz=False):
124
    """
125
    Parse the response to a carrier update request and return the juicy bits.
126
127
    :param data: The data to parse.
128
    :type data: xml
129
130
    :param blitz: Whether or not to create a blitz package. False by default.
131
    :type blitz: bool
132
    """
133 5
    root = ElementTree.fromstring(data)
134 5
    sw_exists = root.find('./data/content/softwareReleaseMetadata')
135 5
    swver = "N/A" if sw_exists is None else ""
136 5
    if sw_exists is not None:
137 5
        swver = carrier_swver_get(root)
138 5
    files = []
139 5
    package_exists = root.find('./data/content/fileSets/fileSet')
140 5
    osver = radver = ""
141 5
    if package_exists is not None:
142 5
        baseurl = "{0}/".format(package_exists.get("url"))
143 5
        osver, radver, files = carrier_child_finder(root, files, baseurl, blitz)
144 5
    return swver, osver, radver, files
145
146
147 5
def prep_carrier_query(npc, device, upg, forced):
148
    """
149
    Prepare carrier query XML.
150
151
    :param npc: MCC + MNC (see `func:return_npc`)
152
    :type npc: int
153
154
    :param device: Hexadecimal hardware ID.
155
    :type device: str
156
157
    :param upg: "upgrade" or "repair".
158
    :type upg: str
159
160
    :param forced: Force a software release.
161
    :type forced: str
162
    """
163 5
    query = '<?xml version="1.0" encoding="UTF-8"?><updateDetailRequest version="2.2.1" authEchoTS="1366644680359"><clientProperties><hardware><pin>0x2FFFFFB3</pin><bsn>1128121361</bsn><imei>004401139269240</imei><id>0x{0}</id></hardware><network><homeNPC>0x{1}</homeNPC><iccid>89014104255505565333</iccid></network><software><currentLocale>en_US</currentLocale><legalLocale>en_US</legalLocale></software></clientProperties><updateDirectives><allowPatching type="REDBEND">true</allowPatching><upgradeMode>{2}</upgradeMode><provideDescriptions>false</provideDescriptions><provideFiles>true</provideFiles><queryType>NOTIFICATION_CHECK</queryType></updateDirectives><pollType>manual</pollType><resultPackageSetCriteria><softwareRelease softwareReleaseVersion="{3}" /><releaseIndependent><packageType operation="include">application</packageType></releaseIndependent></resultPackageSetCriteria></updateDetailRequest>'.format(device, npc, upg, forced)
164 5
    return query
165
166
167 5
def prep_sr_lookup(osver):
168
    """
169
    Prepare software lookup XML.
170
171
    :param osver: OS version to lookup, 10.x.y.zzzz.
172
    :type osver: str
173
    """
174 5
    query = '<?xml version="1.0" encoding="UTF-8"?><srVersionLookupRequest version="2.0.0" authEchoTS="1366644680359"><clientProperties><hardware><pin>0x2FFFFFB3</pin><bsn>1140011878</bsn><imei>004402242176786</imei><id>0x8D00240A</id><isBootROMSecure>true</isBootROMSecure></hardware><network><vendorId>0x0</vendorId><homeNPC>0x60</homeNPC><currentNPC>0x60</currentNPC><ecid>0x1</ecid></network><software><currentLocale>en_US</currentLocale><legalLocale>en_US</legalLocale><osVersion>{0}</osVersion><omadmEnabled>false</omadmEnabled></software></clientProperties></srVersionLookupRequest>'.format(osver)
175 5
    return query
176
177 5
def parse_sr_lookup(reqtext):
178
    """
179
    Take the text of a software lookup request response and parse it as XML.
180
181
    :param reqtext: Response text, hopefully XML formatted.
182
    :type reqtext: str
183
    """
184 5
    try:
185 5
        root = ElementTree.fromstring(reqtext)
186 5
    except ElementTree.ParseError:
187 5
        packtext = "SR not in system"
188
    else:
189 5
        packtext = sr_lookup_extractor(root)
190 5
    return packtext
191
192
193 5
def sr_lookup_extractor(root):
194
    """
195
    Take an ElementTree and extract a software release from it.
196
197
    :param root: ElementTree we're barking up.
198
    :type root: xml.etree.ElementTree.ElementTree
199
    """
200 5
    reg = re.compile(r"(\d{1,4}\.)(\d{1,4}\.)(\d{1,4}\.)(\d{1,4})")
201 5
    packages = root.findall('./data/content/')
202 5
    for package in packages:
203 5
        if package.text is not None:
204 5
            match = reg.match(package.text)
205 5
            packtext = package.text if match else "SR not in system"
206
            return packtext
207