""" t3SINI.py Provides a class representing a t3 image file. """ VERSION = "1.0" import struct, time class FutureVersionError: pass class MalformedFileError: pass T3VERSION = 1 REFERENCESIG = "T3-image\015\012\032" class T3Image: """ A t3 image file. """ def __init__(self, file, options={"ALL": True}): self.filestream = open(file, "rb") self.filestreamidx = 0 self.blocks = [] self.options = options self.lastcpdf = None self.mcld = None self.functionList = [] # try: self.read() # except struct.error: # raise MalformedFileError self.build_pools() self.build_obj_dict() def get_block(self, blocktype): """ Returns one of the block classes or None if we're not currently interested in that type of block. The advantage of doing it this way is that we only have to bother reading or importing blocks that we do care about. For example, if we were simply running through a t3 file in order to rip any resources it contained, we could put "MRES" in self.allowed_blocktypes and ignore all others. """ if "ALL" not in self.options.keys(): if blocktype not in self.options.keys(): return None exec("import t3" + blocktype) return eval("t3" + blocktype + "." + blocktype + "_Block") def read(self): self.filestream.seek(0) self.read_header() while True: blockattrs = self.read_block_header() # get the appropriate class for the block blockclass = self.get_block(blockattrs["s_blocktype"]) # add an instance of it to self.blocks if blockclass == None: self.filestream.seek(self.filestream.tell() + blockattrs["i_size"]) else: self.blocks.append(blockclass(self.filestream, self, blockattrs)) if blockattrs["s_blocktype"] == "CPDF": self.lastcpdf = self.blocks[-1] # if the block we just added was the last one, we exit if blockattrs["s_blocktype"] == "EOF": break # if saveafterEOF is a key in the options passed to us, we save all the # data to a file with name of the value of options[key]. fn = self.options.get("saveafterEOF", False) if fn: f = open(fn, "wb") f.write(self.filestream.read()) f.close() def read_header(self): """ Reads the header of a t3 image file, saving various data to the instance. """ sigbytes = self.filestream.read(11) self.b_sigOK = (sigbytes == REFERENCESIG) uint2bytes = self.filestream.read(2) self.i_version = struct.unpack(" T3VERSION: raise FutureVersionError reserved = self.filestream.read(32) self.s_reservedFutureBytes = repr(reserved[:28]) self.s_reservedCompilerBytes = repr(reserved[28:]) self.b_reservedZeroBytesAreZero = (reserved[:28] == "\000" * 28) self.s_timestamp = self.filestream.read(24) self.struct_timestamp = time.strptime(self.s_timestamp) self.filestreamidx += 69 def read_block_header(self): """ Read the header of a block. This initialises various data that is common to all blocktypes. This should be called before examining the block's actual contents. """ headerdict = {} headerdict["s_blocktype"] = self.filestream.read(4).strip() headerdict["i_size"] = struct.unpack("