Initial Release of IGNCore version 2.5

This commit is contained in:
2021-08-09 13:18:56 +02:00
commit a83d98c47e
910 changed files with 224171 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
import struct
from core.logger import Logger
class MMDBParser:
def __init__(self, filename):
self.filename = filename
self.logger = Logger(__name__)
def get_message_string(self, category_id, instance_id):
with open(self.filename, mode="rb") as file:
categories = self.get_categories(file)
try:
category = next(categories)
while category["id"] != category_id:
category = next(categories)
next_category = next(categories)
except StopIteration:
return None
instance = self.find_entry(file, instance_id, category["offset"], next_category["offset"])
if instance:
file.seek(instance["offset"])
return self.read_string(file)
else:
return None
def get_all_message_strings(self):
with open(self.filename, mode="rb") as file:
categories = iter(list(self.get_categories(file)))
next_category = next(categories)
while True:
try:
category = next_category
next_category = next(categories)
except StopIteration:
break
max_offset = next_category["offset"]
file.seek(category["offset"])
instances = []
while file.tell() < max_offset:
entry = self.read_entry(file)
instances.append(entry)
for instance in instances:
file.seek(instance["offset"])
message_string = self.read_string(file)
print([category["id"], instance["id"], message_string])
def find_entry(self, file, entry_id, min_offset, max_offset):
file.seek(min_offset)
entry = self.read_entry(file)
while file.tell() <= max_offset:
if entry["id"] == entry_id:
return entry
entry = self.read_entry(file)
return None
def get_categories(self, file):
file.seek(4)
num_categories = self.read_int(file)
for i in range(0, num_categories):
yield self.read_entry(file)
def read_entry(self, file):
return {"id": self.read_int(file), "offset": self.read_int(file)}
def read_int(self, file):
return int.from_bytes(file.read(4), byteorder="little")
def read_string(self, file):
message = bytearray()
char = file.read(1)
i = 0
while char and char != b'\x00':
i += 1
message.append(ord(char))
char = file.read(1)
return message.decode("utf-8")
def read_base_85(self, num_str):
n = 0
for i in range(0, 5):
n = n * 85 + num_str[i] - 33
return n
def parse_params(self, param_arr):
args = []
while len(param_arr) > 0:
data_type = chr(param_arr[0])
param_arr = param_arr[1:]
if data_type == "S":
size = param_arr[0] * 256 + param_arr[1]
args.append(param_arr[2:2 + size].decode("utf-8"))
param_arr = param_arr[2 + size:]
elif data_type == "s":
size = param_arr[0] - 1 # size is 1 less than indicated
args.append(param_arr[1:1 + size].decode("utf-8"))
param_arr = param_arr[1 + size:]
elif data_type == "I":
args.append(struct.unpack(">I", param_arr[:4])[0])
param_arr = param_arr[4:]
elif data_type == "i" or data_type == "u":
args.append(self.read_base_85(param_arr[:5]))
param_arr = param_arr[5:]
elif data_type == "R":
category_id = self.read_base_85(param_arr[:5])
instance_id = self.read_base_85(param_arr[5:10])
message = self.get_message_string(category_id, instance_id)
if not message:
raise Exception(f"Could not find message string for category "
f"'{category_id}' and instance '{instance_id}'")
args.append(message)
param_arr = param_arr[10:]
elif data_type == "l":
category_id = 20000
instance_id = struct.unpack(">I", param_arr[:4])[0]
message = self.get_message_string(category_id, instance_id)
if not message:
raise Exception(f"Could not find message string for category "
f"'{category_id}' and instance '{instance_id}'")
args.append(message)
param_arr = param_arr[4:]
elif data_type == "~":
break
else:
raise Exception("Unknown argument type '%s'" % data_type)
return args