import os
import struct
import sys
def int_to_str(int_n):
buf = ""
i = 0
while i < 4:
a = ((int_n >> (3 - i) * 8) & 0xff)
if a != 0:
buf = buf + chr(a)
i = i + 1
return buf
resolutions = {-2: "nodpi", -1: "anydpi", 120: "sdpi", 160: "mdpi", 213: "tvdpi", 240: "ldpi", 320: "xldpi",
480: "xxldpi", 640: "xxxldpi"}
orientations = {0: "vertical", 1: "horizontal"}
devices = {0: "phone", 1: "tablet", 2: "car", 3: "pc", 4: "tv", 5: "speaker", 6: "wearable", 7: "glasses", 8: "headset"}
night_modes = {0: "dark", 1: "light"}
def parse_limit_key(limit_key):
key_str = ""
key_ = limit_key
if key_ == "":
key_ = "base"
key_str = "base"
key_sets = key_.split("-")
last_key_type = -1
for key_item in key_sets:
if key_item == "base":
continue
key_s = key_item.split(":")
if int(key_s[0]) == 0 or int(key_s[0]) == 1 or int(key_s[0]) == 5:
i = int(key_s[1])
if key_str == "":
key_str = key_str + int_to_str(i)
elif last_key_type == 0 or last_key_type == 1 or last_key_type == 5:
key_str = "{}_{}".format(key_str, int_to_str(i))
else:
key_str = "{}-{}".format(key_str, int_to_str(i))
last_key_type = int(key_s[0])
elif int(key_s[0]) == 2:
k = int(key_s[1])
if (k & 0x80000000) != 0:
a = (0xffffffff ^ k) + 1
k = -1 * a
if key_str == "":
key_str = key_str + resolutions.get(k)
else:
key_str = "{}-{}".format(key_str, resolutions.get(k))
elif int(key_s[0]) == 3:
if key_str == "":
key_str = key_str + orientations.get(int(key_s[1]))
else:
key_str = "{}-{}".format(key_str, orientations.get(int(key_s[1])))
elif int(key_s[0]) == 4:
if key_str == "":
key_str = key_str + devices.get(int(key_s[1]))
else:
key_str = "{}-{}".format(key_str, devices.get(int(key_s[1])))
elif int(key_s[0]) == 6:
if key_str == "":
key_str = key_str + night_modes.get(int(key_s[1]))
else:
key_str = "{}-{}".format(key_str, night_modes.get(int(key_s[1])))
elif int(key_s[0]) == 7:
i = int(key_s[1])
if key_str == "":
key_str = "{}mcc{}".format(key_str, str(i))
else:
key_str = "{}_mcc{}".format(key_str, str(i))
elif int(key_s[0]) == 8:
i = int(key_s[1])
if key_str == "":
key_str = "{}mnc{:0>2d}".format(key_str, i)
else:
key_str = "{}_mnc{:0>2d}".format(key_str, i)
else:
raise Exception("invalid key={}".format(str(int(key_s[0]))))
return key_str
def open_new_resource_index(file_path):
if not os.path.exists(file_path):
raise Exception("not found:" + file_path)
with open(file_path, "rb") as fp_resource_index:
header = fp_resource_index.read(128)
length = fp_resource_index.read(4)
key_count = fp_resource_index.read(4)
pri_key_count = struct.unpack("i", key_count)[0]
index_one = 0
private_index = {}
while index_one < pri_key_count:
buf = fp_resource_index.read(4)
p_key_tag = struct.unpack("4s", buf)[0]
buf = fp_resource_index.read(4)
p_data_offset = struct.unpack("I", buf)[0]
buf = fp_resource_index.read(4)
p_key_count = struct.unpack("I", buf)[0]
i = 0
key_str = ""
while i < p_key_count:
buf = fp_resource_index.read(8)
p_key_type = struct.unpack("I", buf[0:4])[0]
p_value = struct.unpack("I", buf[4:8])[0]
if key_str == "":
key_str = "{}:{}".format(str(p_key_type), str(p_value))
else:
key_str = "{}-{}:{}".format(key_str, str(p_key_type), str(p_value))
i = i + 1
private_index[key_str] = p_data_offset
index_one = index_one + 1
c = 0
idss_cache = {}
while c < pri_key_count:
pos = fp_resource_index.tell()
idss_buf = fp_resource_index.read(4)
idss_tag = struct.unpack("4s", idss_buf)[0]
idss_buf = fp_resource_index.read(4)
idss_count = struct.unpack("I", idss_buf)[0]
i = 0
idss_index = {}
while i < idss_count:
buf = fp_resource_index.read(4)
p_id = struct.unpack("I", buf)[0]
buf = fp_resource_index.read(4)
p_offset = struct.unpack("I", buf)[0]
idss_index[p_id] = p_offset
i = i + 1
idss_cache[pos] = idss_index
c = c + 1
third_data = {}
d_data = {}
d_pos = fp_resource_index.tell()
d_buf = fp_resource_index.read(4)
while len(d_buf) > 0:
d_size = struct.unpack("I", d_buf)[0]
d_buf = fp_resource_index.read(d_size)
d_res_type = struct.unpack("I", d_buf[0:4])[0]
d_value_len_l = struct.unpack("B", d_buf[8:9])[0]
d_value_len_h = struct.unpack("B", d_buf[9:10])[0]
d_value_len = d_value_len_l + d_value_len_h * 256
d_value = ""
if d_res_type == 10 or d_res_type == 11 or d_res_type == 16 or d_res_type == 17 or d_res_type == 22:
tmp = d_buf[10:10 + d_value_len]
d_d_pos = 0
while d_d_pos < d_value_len - 1:
d_d_value_len_l = struct.unpack("B", tmp[0 + d_d_pos:1 + d_d_pos])[0]
d_d_value_len_h = struct.unpack("B", tmp[1 + d_d_pos:2 + d_d_pos])[0]
d_d_value_len = d_d_value_len_l + d_d_value_len_h * 256
d_value = "{}<{}>".format(d_value, str(tmp[2 + d_d_pos:2 + d_d_value_len + d_d_pos]))
d_d_pos = d_d_pos + 2 + d_d_value_len + 1
else:
d_value = d_buf[10:10 + d_value_len - 1].decode("utf-8")
d_name_len_l = struct.unpack("B", d_buf[10 + d_value_len:11 + d_value_len])[0]
d_name_len_h = struct.unpack("B", d_buf[11 + d_value_len:12 + d_value_len])[0]
d_name_len = d_name_len_l + d_name_len_h * 256
d_name = str(d_buf[12 + d_value_len:12 + d_value_len + d_name_len - 1].decode("utf-8"))
d_data[d_pos] = [d_value, d_name]
d_pos = fp_resource_index.tell()
d_buf = fp_resource_index.read(4)
for key_, key_offset in private_index.items():
third_data[key_] = {}
idss_sets = idss_cache.get(key_offset)
for id_, offset in idss_sets.items():
id_sets = d_data.get(offset)
third_data[key_][id_] = id_sets
return third_data
def is_new_module(file_path):
if not os.path.exists(file_path):
raise Exception("not found:" + file_path)
with open(file_path, "rb") as fp:
version = fp.read(128)
version_str = version.decode('utf-8').rstrip('\x00')
return version_str.startswith("RestoolV2")
def dump(file_path, out_path):
out_file = os.open(out_path, os.O_WRONLY | os.O_CREAT, 0o664)
if is_new_module(file_path):
from resource_index_v2 import open_new_resource_index_v2
third_data = open_new_resource_index_v2(file_path)
else:
third_data = open_new_resource_index(file_path)
for key_, ids_ in third_data.items():
key_str = parse_limit_key(key_)
if "zh_CN" == key_str:
continue
os.write(out_file, str.encode("keyconfig:{}\n".format(key_)))
os.write(out_file, str.encode("{}\n".format(key_str)))
for id_, idsets in ids_.items():
os.write(out_file, str.encode("id:{}, '{}' '{}'\n".format(str(id_), idsets[0], str(idsets[1]))))
os.close(out_file)