def initialize(self): self.attrs = {} stream = io.BytesIO(self.stream) tag = Tag(stream) if tag.id != 0xF503: raise LRFParseError("Bad block content") obj = self._document.objects[tag.dword] if isinstance(obj, SimpleText): self.name = 'SimpleTextBlock' self.textstyle_id = obj.style_id elif isinstance(obj, Text): self.name = 'TextBlock' self.textstyle_id = obj.style_id elif isinstance(obj, Image): self.name = 'ImageBlock' for attr in ('x0', 'x1', 'y0', 'y1', 'xsize', 'ysize', 'refstream'): self.attrs[attr] = getattr(obj, attr) self.refstream = self._document.objects[self.attrs['refstream']] elif isinstance(obj, Button): self.name = 'ButtonBlock' else: raise LRFParseError("Unexpected block type: " + obj.__class__.__name__) self.content = obj for attr in self.extra_attrs: if hasattr(self, attr): self.attrs[attr] = getattr(self, attr)
def read_stream(self, tag, stream): if self.stream_read: raise LRFParseError('There can be only one stream per object') if not hasattr(self, 'stream_flags'): raise LRFParseError('Stream flags not initialized') self.stream = stream.read(self.stream_size) if self.stream_flags & 0x200 != 0: l = len(self.stream) key = self._scramble_key & 0xFF if key != 0 and key <= 0xF0: key = l % key + 0xF else: key = 0 if l > 0x400 and (isinstance(self, ImageStream) or isinstance( self, Font) or isinstance(self, SoundStream)): l = 0x400 self.stream = self.descramble_buffer(self.stream, l, key) if self.stream_flags & 0x100 != 0: decomp_size = struct.unpack("<I", self.stream[:4])[0] self.stream = zlib.decompress(self.stream[4:]) if len(self.stream) != decomp_size: raise LRFParseError("Stream decompressed size is wrong!") if stream.read(2) != b'\x06\xF5': print("Warning: corrupted end-of-stream tag at %08X; skipping it" % (stream.tell() - 2)) self.end_stream(None, None)
def get_object(document, stream, id, offset, size, scramble_key): stream.seek(offset) start_tag = Tag(stream) if start_tag.id != 0xF500: raise LRFParseError('Bad object start') obj_id, obj_type = struct.unpack("<IH", start_tag.contents) if obj_type < len(object_map) and object_map[obj_type] is not None: return object_map[obj_type](document, stream, obj_id, scramble_key, offset+size-Tag.tags[0][0]) raise LRFParseError("Unknown object type: %02X!" % obj_type)
def to_html(self): s = '' open_containers = collections.deque() in_p = False for c in self.content: if isinstance(c, unicode_type): s += c elif c is None: p = open_containers.pop() s += p.close_html() else: if c.name == 'P': in_p = True elif c.name == 'CR': s += '<br />' if in_p else '<p>' else: s += c.to_html() if not c.self_closing: open_containers.append(c) if len(open_containers) > 0: raise LRFParseError('Malformed text stream %s' % ([ i.name for i in open_containers if isinstance(i, Text.TextTag) ], )) return s
def __init__(self, stream): self.offset = stream.tell() tag_id = struct.unpack("<BB", stream.read(2)) if tag_id[1] != 0xF5: raise LRFParseError("Bad tag ID %02X at %d"%(tag_id[1], self.offset)) if tag_id[0] not in self.__class__.tags: raise LRFParseError("Unknown tag ID: F5%02X" % tag_id[0]) self.id = 0xF500 + tag_id[0] size, self.name = self.__class__.tags[tag_id[0]] if isinstance(size, string_or_bytes): parser = getattr(self, size + '_parser') self.contents = parser(stream) else: self.contents = stream.read(size)
def tag_78_parser(self, stream): pos = stream.tell() res = [] res.append(struct.unpack("<I", stream.read(4))[0]) tag = Tag(stream) if tag.id != 0xF516: raise LRFParseError("Bad tag 78 at %08X" % pos) res.append(tag.contents) res.append(struct.unpack("<H", stream.read(2))[0]) return res
def handle_tag(self, tag, stream, tag_map=None): if tag_map is None: tag_map = self.__class__.tag_map if tag.id in tag_map: h = tag_map[tag.id] val = LRFObject.tag_to_val(h, self, tag, stream) if h[1] != '' and h[0] != '': setattr(self, h[0], val) else: raise LRFParseError("Unknown tag in %s: %s" % (self.__class__.__name__, str(tag)))
def handle_tag(self, tag): if tag.id in self.tag_map: action = self.tag_map[tag.id] if isinstance(action, string_or_bytes): func, args = action, tuple([]) else: func, args = action[0], (action[1],) getattr(self, func)(tag, *args) else: raise LRFParseError("Unknown tag in %s: %s" % (self.__class__.__name__, str(tag)))
def handle_tag(self, tag): if tag.id in self.tag_map: action = self.tag_map[tag.id] if isinstance(action, unicode_type): func, args = action, () else: func, args = action[0], (action[1], ) getattr(self, func)(tag, *args) else: raise LRFParseError("Unknown tag in %s: %s" % (self.__class__.__name__, unicode_type(tag)))
def handle_tag(self, tag): if tag.id in self.tag_map: action = self.tag_map[tag.id] if isinstance(action, str): func, args = action, () else: func, args = action[0], (action[1], ) getattr(self, func)(tag, *args) else: raise LRFParseError( f"Unknown tag in {self.__class__.__name__}: {str(tag)}")
def __str__(self): s = '<Button objid="%s">\n' % (self.id, ) if self.button_flags & 0x10 != 0: s += '<PushButton ' if 2 in self.refimage: s += 'refimage="%s" ' % (self.refimage[2], ) s = s.rstrip() + '>\n' s += '<JumpTo refpage="%s" refobj="%s" />\n' % self.jump_action(2) s += '</PushButton>\n' else: raise LRFParseError('Unsupported button type') s += '</Button>\n' return s
def __str__(self): s = u'' open_containers = collections.deque() for c in self.content: if isinstance(c, string_or_bytes): s += prepare_string_for_xml(c).replace('\0', '') elif c is None: if open_containers: p = open_containers.pop() s += u'</%s>'%(p.name,) else: s += unicode_type(c) if not c.self_closing: open_containers.append(c) if len(open_containers) > 0: if len(open_containers) == 1: s += u'</%s>'%(open_containers[0].name,) else: raise LRFParseError('Malformed text stream %s'%([i.name for i in open_containers if isinstance(i, Text.TextTag)],)) return s
def dummy_parser(self, stream): raise LRFParseError("Unknown tag at %08X" % stream.tell())
def fget(self): if len(self.contents) != 4: raise LRFParseError("Bad parameter for tag ID: %04X" % self.id) return struct.unpack("<I", self.contents)[0]