from os import listdir import struct import io from .buffer import Buffer from .i18n import splitFileName, getScore, locale class ResourceError(Exception): def __init__(self, code=None): self.code = code class ResourceFile(object): def __init__(self, fileName, buf=None): self.__name = fileName if buf is not None: buffer = buf ownBuffer = False else: buffer = Buffer() ownBuffer = True try: self.__stream = open(self.__name, 'rb') sign = self.__stream.read(4) if sign != b'CRF\x00': raise ResourceError(code='invalid') major = self.readInt() minor = self.readInt() priority = self.readInt() if major != 2 or minor < 0: raise ResourceError(code='incompatible') except ResourceError as e: raise Exception("Invalid resource file: {}".format(e.code)) except IOError as e: raise Exception("Error loading resource file '{}': {}".format(self.__name, e.message)) def readInt(self): return struct.unpack('i', self.__stream.read(4))[0] def readString(self): string = b'' while True: b = self.__stream.read(1) if b == b'\x00' or b == b'': break string += b return string.decode('ascii') def getDirectory(self): try: self.__stream.seek(-8, io.SEEK_END); except IOError: raise Exception("Error reading {} directory".format(self.__name)) start = self.readInt() count = self.readInt() try: self.__stream.seek(start, io.SEEK_SET); except IOError: raise Exception("Error reading {} directory".format(self.__name)) directory = [] try: for i in range(0, count): directory.append({ "name": self.readString(), "unpackedSize": self.readInt(), "offset": self.readInt(), "packedSize": self.readInt(), "level": self.readInt(), "group": self.readString(), }) except IOError: raise Exception("Error reading {} directory".format(self.__name)) return directory class ResourcesCollection: def __init__(self, directories): self.__files = [] self.__buffer = None self.__resources = {} self.loadResourceFiles(directories) self.processFiles() def loadResourceFiles(self, directories): for directory in directories: try: for name in listdir(directory): if not name.startswith('.') and name.endswith('.res'): self.__files.append( ResourceFile(directory + '/' + name, buf=self.__buffer)) except OSError: pass def processFiles(self): for res_file in self.__files: directory = res_file.getDirectory() for de in directory: name, ext, language, country = splitFileName(de['name']) score = getScore(language, country, locale) if score > 0: resName = name + '.' + ext res = self.__resources.get(resName, None) if not res: res = Resource(res_file, score, de, resName) self.__resources[resName] = res if len(de.group) > 0: groups[de.group].append(res) else: res.addVariant(file, score, de) directory.clear()