Last active
March 12, 2020 17:22
-
-
Save lifthrasiir/4ce6e3ce2b62919e7ec5c8a0d7d3705e to your computer and use it in GitHub Desktop.
Android Cell Broadcasting Identifier Ranges (https://docs.google.com/spreadsheets/d/1GktvvMGxyuI62O_WyrtYPdY_tSljcf9ySrMAkoVnbC8)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 2020-02-13 Kang Seonghoon | |
# Public Domain | |
import os | |
import xml.etree.ElementTree as ET | |
from collections import namedtuple | |
class Entry(namedtuple('Entry', 'category emergency lang')): | |
def __repr__(self): | |
return f'{self.category}{"!" if self.emergency else ""}{"#" if self.lang else ""}' | |
CATEGORIES = { | |
'cmas_presidential_alerts_channels_range_strings': 'cmas1', | |
'cmas_alert_extreme_channels_range_strings': 'cmas2', | |
'cmas_alerts_severe_range_strings': 'cmas3', | |
'cmas_amber_alerts_channels_range_strings': 'amber', | |
'required_monthly_test_range_strings': 'monthly', | |
'exercise_alert_range_strings': 'exercise', | |
'operator_defined_alert_range_strings': 'operator', | |
'etws_alerts_range_strings': 'etws', | |
'etws_test_alerts_range_strings': 'etwstest', | |
'additional_cbs_channels_strings': 'cbs', | |
'emergency_alerts_channels_range_strings': 'alert', | |
'public_safety_messages_channels_range_strings': 'safety', | |
'state_local_test_alert_range_strings': 'cmastest', | |
'geo_fencing_trigger_messages_range_strings': 'geofence', | |
'alert_reminder_interval_values': None, | |
'alert_reminder_interval_active_values': None, | |
} | |
def handleitem(s, category): | |
ids, _, flags = s.partition(':') | |
idstart, _, idend = ids.partition('-') | |
idend = int(idend or idstart, 0) | |
idstart = int(idstart, 0) | |
emergency = None | |
lang = False | |
for flag in flags.split(','): | |
key, _, value = flag.strip().partition('=') | |
if key == 'rat': | |
if value != 'gsm': return | |
elif key == 'emergency': | |
emergency = value == 'true' | |
elif key == 'filter_language': | |
lang = True | |
return idstart, idend, Entry(category=category, emergency=emergency, lang=lang) | |
def handlexml(xmlpath): | |
tree = ET.parse(xmlpath) | |
entries = {} | |
for e in tree.findall('string-array'): | |
category = CATEGORIES[e.attrib['name']] | |
if not category: continue | |
ientries = {} | |
for item in e.findall('item'): | |
entry = handleitem(item.text, category) | |
if not entry: continue | |
idstart, idend, entry = entry | |
for i in range(idstart, idend + 1): | |
if i < 40960: # XXX | |
ientries[i] = entry | |
entries[category] = ientries | |
return entries | |
def tocolumns(entries): | |
columns = {} | |
for ientries in entries.values(): | |
for i, entry in ientries.items(): | |
assert i not in columns | |
columns[i] = entry | |
return columns | |
def main(): | |
baseentries = handlexml(os.path.join('values', 'config.xml')) | |
basecolumns = tocolumns(baseentries) | |
allcolumns = {} | |
for root, dirs, files in os.walk('.', followlinks=True): | |
dirname = os.path.basename(root) | |
if dirname == 'values': continue | |
if 'config.xml' not in files: continue | |
xmlpath = os.path.join(root, 'config.xml') | |
entries = handlexml(xmlpath) | |
if entries: | |
entries = dict(baseentries, **entries) | |
allcolumns[dirname] = dict((k, '<>' if basecolumns.get(k) == v else v) for k, v in tocolumns(entries).items()) | |
allcolumns['values'] = basecolumns | |
allids = sorted(set().union(*[entries.keys() for entries in allcolumns.values()])) | |
maxdirlen = max(len(k) for k in allcolumns.keys()) | |
def z(s): return '\t'.join(s.split()) | |
print(z('.' + ' ' * (maxdirlen + 3) + ''.join('%-12d' % id for id in allids))) | |
for k, entries in sorted(allcolumns.items()): | |
print(z(k.ljust(maxdirlen + 4) + ''.join('%-12s' % str(entries.get(id, '.')) for id in allids))) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment