def createFields(self): # File data self.signature = None self.central_directory = [] while not self.eof: skip = 0 while True: try: header = self.stream.readBits( self.absolute_address + self.current_size + skip, 32, self.endian) if header in self.CHUNK_TYPES: break skipdelta = self.stream.searchBytes( b'PK', self.absolute_address + self.current_size + skip + 8) if skipdelta is None: if not self.current_size: raise ParserError("Failed to find any zip headers") return skip = skipdelta - (self.absolute_address + self.current_size) except ReadStreamError: if not self.current_size: raise ParserError("Failed to read stream") return if skip: yield RawBytes(self, "unparsed[]", skip // 8) yield textHandler(UInt32(self, "header[]", "Header"), hexadecimal) ftype, fname, fdesc = self.CHUNK_TYPES[header] yield ftype(self, fname, fdesc)
def createFields(self): addr = self.absolute_address len = self.stream.searchBytesLength(':', False, addr, addr + (MAX_STRING_LENGTH + 1) * 8) if len is None: raise ParserError("Torrent: unable to find string separator (':')") if not len: raise ParserError("Torrent: error: no string length!") val = String(self, "length", len, "String length") yield val try: len = int(val.value) except ValueError: len = -1 if len < 0: raise ParserError( "Invalid string length (%s)" % makePrintable(val.value, "ASCII", to_unicode=True)) yield String(self, "separator", 1, "String length/value separator") if not len: self.info("Empty string: len=%i" % len) return if len < 512: yield String(self, "value", len, "String value", charset="ISO-8859-1") else: # Probably raw data yield RawBytes(self, "value", len, "Raw data")
def _addField(self, field): """ Add a field to the field set: * add it into _fields * update _current_size May raise a StopIteration() on error """ if not issubclass(field.__class__, Field): raise ParserError("Field type (%s) is not a subclass of 'Field'!" % field.__class__.__name__) assert isinstance(field._name, str) if field._name.endswith("[]"): self.setUniqueFieldName(field) if config.debug: self.info("[+] DBG: _addField(%s)" % field.name) # required for the msoffice parser if field._address != self._current_size: self.warning("Fix address of %s to %s (was %s)" % (field.path, self._current_size, field._address)) field._address = self._current_size ask_stop = False # Compute field size and check that there is enough place for it self.__is_feeding = True try: _ = field.size except Exception as err: if field.is_field_set and field.current_length and field.eof: self.warning("Error when getting size of '%s': %s" % (field.name, err)) field._stopFeeding() ask_stop = True else: self.warning("Error when getting size of '%s': delete it" % field.name) self.__is_feeding = False raise self.__is_feeding = False # No more place? dsize = self._checkSize(field._address + field.size, False) if (dsize is not None and dsize < 0) or (field.is_field_set and field.size <= 0): if self.autofix and self._current_size: self._fixFieldSize(field, field.size + dsize) else: raise ParserError("Field %s is too large!" % field.path) self._current_size += field.size try: self._fields.append(field._name, field) except UniqKeyError as err: self.warning("Duplicate field name " + str(err)) field._name += "[]" self.setUniqueFieldName(field) self._fields.append(field._name, field) if ask_stop: raise StopIteration()
def parseFontHeader(self): yield UInt16(self, "maj_ver", "Major version") yield UInt16(self, "min_ver", "Minor version") yield UInt16(self, "font_maj_ver", "Font major version") yield UInt16(self, "font_min_ver", "Font minor version") yield textHandler(UInt32(self, "checksum"), hexadecimal) yield Bytes(self, "magic", 4, r"Magic string (\x5F\x0F\x3C\xF5)") if self["magic"].value != "\x5F\x0F\x3C\xF5": raise ParserError("TTF: invalid magic of font header") # Flags yield Bit(self, "y0", "Baseline at y=0") yield Bit(self, "x0", "Left sidebearing point at x=0") yield Bit(self, "instr_point", "Instructions may depend on point size") yield Bit(self, "ppem", "Force PPEM to integer values for all") yield Bit(self, "instr_width", "Instructions may alter advance width") yield Bit(self, "vertical", "e laid out vertically?") yield PaddingBits(self, "reserved[]", 1) yield Bit(self, "linguistic", "Requires layout for correct linguistic rendering?") yield Bit(self, "gx", "Metamorphosis effects?") yield Bit(self, "strong", "Contains strong right-to-left glyphs?") yield Bit(self, "indic", "contains Indic-style rearrangement effects?") yield Bit(self, "lossless", "Data is lossless (Agfa MicroType compression)") yield Bit(self, "converted", "Font converted (produce compatible metrics)") yield Bit(self, "cleartype", "Optimised for ClearType") yield Bits(self, "adobe", 2, "(used by Adobe)") yield UInt16(self, "unit_per_em", "Units per em") if not (16 <= self["unit_per_em"].value <= 16384): raise ParserError("TTF: Invalid unit/em value") yield UInt32(self, "created_high") yield TimestampMac32(self, "created") yield UInt32(self, "modified_high") yield TimestampMac32(self, "modified") yield UInt16(self, "xmin") yield UInt16(self, "ymin") yield UInt16(self, "xmax") yield UInt16(self, "ymax") # Mac style yield Bit(self, "bold") yield Bit(self, "italic") yield Bit(self, "underline") yield Bit(self, "outline") yield Bit(self, "shadow") yield Bit(self, "condensed", "(narrow)") yield Bit(self, "expanded") yield PaddingBits(self, "reserved[]", 9) yield UInt16(self, "lowest", "Smallest readable size in pixels") yield Enum(UInt16(self, "font_dir", "Font direction hint"), DIRECTION_NAME) yield Enum(UInt16(self, "ofst_format"), {0: "short offsets", 1: "long"}) yield UInt16(self, "glyph_format", "(=0)")
def parseNames(self): # Read header yield UInt16(self, "format") if self["format"].value != 0: raise ParserError("TTF (names): Invalid format (%u)" % self["format"].value) yield UInt16(self, "count") yield UInt16(self, "offset") if MAX_NAME_COUNT < self["count"].value: raise ParserError("Invalid number of names (%s)" % self["count"].value) # Read name index entries = [] for index in xrange(self["count"].value): entry = NameHeader(self, "header[]") yield entry entries.append(entry) # Sort names by their offset entries.sort(key=lambda field: field["offset"].value) # Read name value last = None for entry in entries: # Skip duplicates values new = (entry["offset"].value, entry["length"].value) if last and last == new: self.warning("Skip duplicate %s %s" % (entry.name, new)) continue last = (entry["offset"].value, entry["length"].value) # Skip negative offset offset = entry["offset"].value + self["offset"].value if offset < self.current_size // 8: self.warning("Skip value %s (negative offset)" % entry.name) continue # Add padding if any padding = self.seekByte(offset, relative=True, null=True) if padding: yield padding # Read value size = entry["length"].value if size: yield String(self, "value[]", size, entry.description, charset=entry.getCharset()) padding = (self.size - self.current_size) // 8 if padding: yield NullBytes(self, "padding_end", padding)
def createFields(self): yield Bits(self, "sync[]", 2) # =2 if self["sync[0]"].value != 2: raise ParserError("Unknown video elementary data") yield Bits(self, "is_scrambled", 2) yield Bits(self, "priority", 1) yield Bit(self, "alignment") yield Bit(self, "is_copyrighted") yield Bit(self, "is_original") yield Bit(self, "has_pts", "Presentation Time Stamp") yield Bit(self, "has_dts", "Decode Time Stamp") yield Bit(self, "has_escr", "Elementary Stream Clock Reference") yield Bit(self, "has_es_rate", "Elementary Stream rate") yield Bit(self, "dsm_trick_mode") yield Bit(self, "has_copy_info") yield Bit(self, "has_prev_crc", "If True, previous PES packet CRC follows") yield Bit(self, "has_extension") yield UInt8(self, "size") # Time stamps if self["has_pts"].value: yield Bits(self, "sync[]", 4) # =2, or 3 if has_dts=True yield Timestamp(self, "pts") if self["has_dts"].value: if not self["has_pts"].value: raise ParserError("Invalid PTS/DTS values") yield Bits(self, "sync[]", 4) # =1 yield Timestamp(self, "dts") if self["has_escr"].value: yield Bits(self, "sync[]", 2) # =0 yield SCRExt(self, "escr") if self["has_es_rate"].value: yield Bit(self, "sync[]") # =True yield Bits(self, "es_rate", 14) # in units of 50 bytes/second yield Bit(self, "sync[]") # =True if self["has_copy_info"].value: yield Bit(self, "sync[]") # =True yield Bits(self, "copy_info", 7) if self["has_prev_crc"].value: yield textHandler(UInt16(self, "prev_crc"), hexadecimal) # --- Extension --- if self["has_extension"].value: yield VideoExtension1(self, "extension") if self["extension/has_extension2"].value: yield VideoExtension2(self, "extension2")
def __init__(self, parent, name, description=None): Field.__init__(self, parent, name, 8, description) stream = self._parent.stream addr = self.absolute_address value = stream.readBits(addr, 8, BIG_ENDIAN) if 128 <= value: nbits = (value & 127) * 8 if not nbits: raise ParserError("ASN.1: invalid ASN integer size (zero)") if 64 < nbits: # Arbitrary limit to catch errors raise ParserError("ASN.1: ASN integer is limited to 64 bits") self._size = 8 + nbits value = stream.readBits(addr + 8, nbits, BIG_ENDIAN) self.createValue = lambda: value
def createFields(self): yield Header(self, "header") if MAX_NAME_PER_HEADER < self["header/nb_name"].value: raise ParserError("EXE resource: invalid number of name (%s)" % self["header/nb_name"].value) if MAX_INDEX_PER_HEADER < self["header/nb_index"].value: raise ParserError("EXE resource: invalid number of index (%s)" % self["header/nb_index"].value) hdr = self["header"] for index in xrange(hdr["nb_name"].value): yield NameOffset(self, "name[]") for index in xrange(hdr["nb_index"].value): yield IndexOffset(self, "index[]", self.res_type)
def createFields(self): yield Bytes(self, "header", 4, r"PE header signature (PE\0\0)") if self["header"].value != "PE\0\0": raise ParserError("Invalid PE header signature") yield Enum(UInt16(self, "cpu", "CPU type"), self.cpu_name) yield UInt16(self, "nb_section", "Number of sections") yield TimestampUnix32(self, "creation_date", "Creation date") yield UInt32(self, "ptr_to_sym", "Pointer to symbol table") yield UInt32(self, "nb_symbols", "Number of symbols") yield UInt16(self, "opt_hdr_size", "Optional header size") yield Bit(self, "reloc_stripped", "If true, don't contain base relocations.") yield Bit(self, "exec_image", "Executable image?") yield Bit(self, "line_nb_stripped", "COFF line numbers stripped?") yield Bit(self, "local_sym_stripped", "COFF symbol table entries stripped?") yield Bit(self, "aggr_ws", "Aggressively trim working set") yield Bit(self, "large_addr", "Application can handle addresses greater than 2 GB") yield NullBits(self, "reserved", 1) yield Bit(self, "reverse_lo", "Little endian: LSB precedes MSB in memory") yield Bit(self, "32bit", "Machine based on 32-bit-word architecture") yield Bit(self, "is_stripped", "Debugging information removed?") yield Bit( self, "swap", "If image is on removable media, copy and run from swap file") yield PaddingBits(self, "reserved2", 1) yield Bit(self, "is_system", "It's a system file") yield Bit(self, "is_dll", "It's a dynamic-link library (DLL)") yield Bit(self, "up", "File should be run only on a UP machine") yield Bit(self, "reverse_hi", "Big endian: MSB precedes LSB in memory")
def createFields(self): # Read chunk header yield Bytes(self, "signature", 3, r"Property signature (\x8E\xAD\xE8)") if self["signature"].value != "\x8E\xAD\xE8": raise ParserError("Invalid property signature") yield UInt8(self, "version", "Signature version") yield NullBytes(self, "reserved", 4, "Reserved") yield UInt32(self, "count", "Count") yield UInt32(self, "size", "Size") # Read item header items = [] for i in range(0, self["count"].value): item = ItemHeader(self, "item[]") yield item items.append(item) # Sort items by their offset items.sort(key=lambda field: field["offset"].value) # Read item content start = self.current_size // 8 for item in items: offset = item["offset"].value diff = offset - (self.current_size // 8 - start) if 0 < diff: yield NullBytes(self, "padding[]", diff) yield ItemContent(self, "content[]", item) size = start + self["size"].value - self.current_size // 8 if 0 < size: yield NullBytes(self, "padding[]", size)
def __init__(self, *args, **kw): FieldSet.__init__(self, *args, **kw) if not self._size: frame_size = self.getFrameSize() if not frame_size: raise ParserError("MPEG audio: Invalid frame %s" % self.path) self._size = min(frame_size * 8, self.parent.size - self.address)
def __init__(self, parent, name, **kw): FieldSet.__init__(self, parent, name, **kw) code = self["bytecode"].value if code not in self.bytecode_info: raise ParserError('Unknown bytecode %r at position %s' % (code, self.absolute_address // 8)) self.code_info = self.bytecode_info[code] if not name: self._name = self.code_info[0] if code == "l": self.createValue = self.createValueLong elif code in ("i", "I", "f", "g"): self.createValue = lambda: self["value"].value elif code == "T": self.createValue = lambda: True elif code == "F": self.createValue = lambda: False elif code in ("x", "y"): self.createValue = self.createValueComplex elif code in ("s", "t", "u"): self.createValue = self.createValueString self.createDisplay = self.createDisplayString if code == 't': if not hasattr(self.root, 'string_table'): self.root.string_table = [] self.root.string_table.append(self) elif code == 'R': if hasattr(self.root, 'string_table'): self.createValue = self.createValueStringRef
def createFields(self): yield RawBytes(self, "marker", len(self.MAGIC)) yield WhiteSpace(self, "sep[]") yield String(self, "start_attribute_marker", 2) addr = self.absolute_address + self.current_size while self.stream.readBytes(addr, 2) != b'>>': yield WhiteSpace(self, "sep[]") t = PDFName(self, "type[]") yield t name = t.value.decode() self.info("Parsing PDFName '%s'" % name) if name == "Size": yield PDFNumber(self, "size", "Entries in the file cross-reference section") elif name == "Prev": yield PDFNumber(self, "offset") elif name == "Root": yield Catalog(self, "object_catalog") elif name == "Info": yield Catalog(self, "info") elif name == "ID": yield PDFArray(self, "id") elif name == "Encrypt": yield PDFDictionary(self, "decrypt") else: raise ParserError("Don't know trailer type '%s'" % name) addr = self.absolute_address + self.current_size yield String(self, "end_attribute_marker", 2) yield LineEnd(self, "line_end[]") yield String(self, "start_xref", 9) yield LineEnd(self, "line_end[]") yield PDFNumber(self, "cross_ref_table_start_address") yield LineEnd(self, "line_end[]") yield String(self, "end_marker", len(ENDMAGIC)) yield LineEnd(self, "line_end[]")
def seekBit(self, address, name="padding[]", description=None, relative=True, null=False): """ Create a field to seek to specified address, or None if it's not needed. May raise an (ParserError) exception if address is invalid. """ if relative: nbits = address - self._current_size else: nbits = address - (self.absolute_address + self._current_size) if nbits < 0: raise ParserError("Seek error, unable to go back!") if 0 < nbits: if null: return createNullField(self, nbits, name, description) else: return createPaddingField(self, nbits, name, description) else: return None
def createFields(self): # Header yield String(self, "magic", 3, "File magic code", charset="ASCII") yield String(self, "version", 3, "GIF version", charset="ASCII") yield ScreenDescriptor(self, "screen") if self["screen/global_map"].value: bpp = (self["screen/size_global_map"].value + 1) yield PaletteRGB(self, "color_map", 1 << bpp, "Color map") self.color_map = self["color_map"] else: self.color_map = None self.images = [] while True: code = Enum(Character(self, "separator[]", "Separator code"), self.separator_name) yield code code = code.value if code == "!": yield Extension(self, "extensions[]") elif code == ",": yield Image(self, "image[]") elif code == ";": # GIF Terminator break else: raise ParserError("Wrong GIF image separator: 0x%02X" % ord(code))
def __init__(self, *args, **kw): FieldSet.__init__(self, *args, **kw) key = self["type"].value & 31 if self['class'].value == 0: # universal object if key in self.TYPE_INFO: self._name, self._handler, self._description, create_desc = self.TYPE_INFO[ key] if create_desc: self.createDescription = lambda: "%s: %s" % ( self.TYPE_INFO[key][2], create_desc(self)) self._description = None elif key == 31: raise ParserError( "ASN.1 Object: tag bigger than 30 are not supported") else: self._handler = None elif self['form'].value: # constructed: treat as sequence self._name = 'seq[]' self._handler = readSequence self._description = 'constructed object type %i' % key else: # primitive, context/private self._name = 'raw[]' self._handler = readASCIIString self._description = '%s object type %i' % (self['class'].display, key) field = self["size"] self._size = field.address + field.size + field.value * 8
def createFields(self): yield PropID(self, "id") num_folders = self['../unpack_info/num_folders'].value num_unpackstreams = [1] * num_folders while not self.eof: uid = ReadNextByte(self) if uid == kEnd: yield PropID(self, "end_marker") break elif uid == kNumUnPackStream: yield PropID(self, "num_unpackstream_marker") for i in xrange(num_folders): field = SZUInt64(self, "num_unpackstreams[]") yield field num_unpackstreams[i] = field.value elif uid == kSize: yield PropID(self, "size_marker") for i in xrange(num_folders): # The last substream's size is the stream size minus the other substreams. for j in xrange(num_unpackstreams[i] - 1): yield SZUInt64(self, "unpack_size[%d][%d]" % (i, j)) elif uid == kCRC: digests = [] for i in xrange(num_folders): if num_unpackstreams[i] == 1 and 'digests' in self[ '../unpack_info']: continue for j in xrange(num_unpackstreams[i]): digests.append('folder %i, stream %i' % (i, j)) yield Digests(self, "digests", len(digests), digests) else: raise ParserError("Unexpected ID (%i)" % uid)
def __init__(self, parent, ids): FieldSet.__init__(self, parent, "?[]") # Set name id = self['id'].value self.val = ids.get(id) if not self.val: if id == 0xBF: self.val = 'CRC-32[]', Binary elif id == 0xEC: self.val = 'Void[]', Binary elif id == 0x1B538667: self.val = 'SignatureSlot[]', signature else: self.val = 'Unknown[]', Binary self._name = self.val[0] # Compute size size = self['size'] if size.value is not None: self._size = size.address + size.size + size.value * 8 elif self._parent._parent: raise ParserError("Unknown length (only allowed for the last Level 0 element)") elif self._parent._size is not None: self._size = self._parent._size - self.address
def parseTuple(parent): yield UInt32(parent, "count", "Item count") count = parent["count"].value if count < 0: raise ParserError("Invalid tuple/list count") for index in xrange(count): yield Object(parent, "item[]")
def Entry(parent, name): addr = parent.absolute_address + parent.current_size tag = parent.stream.readBytes(addr, 1) if tag not in TAGS: raise ParserError("Torrent: Entry of type %r not handled" % tag) cls = TAGS[tag] return cls(parent, name)
def writeFieldsIn(self, old_field, address, new_fields): """ Can only write in existing fields (address < self._current_size) """ # Check size total_size = sum(field.size for field in new_fields) if old_field.size < total_size: raise ParserError("Unable to write fields at address %s " "(too big)!" % (address)) # Need padding before? replace = [] size = address - old_field.address assert 0 <= size if 0 < size: padding = createPaddingField(self, size) padding._address = old_field.address replace.append(padding) # Set fields address for field in new_fields: field._address = address address += field.size replace.append(field) # Need padding after? size = (old_field.address + old_field.size) - address assert 0 <= size if 0 < size: padding = createPaddingField(self, size) padding._address = address replace.append(padding) self.replaceField(old_field.name, replace)
def createFields(self): if self._m2ts: yield Bits(self, "c", 2) yield Bits(self, "ats", 32 - 2) yield textHandler(UInt8(self, "sync", 8), hexadecimal) if self["sync"].value != 0x47: raise ParserError("MPEG-2 TS: Invalid synchronization byte") yield Bit(self, "has_error") yield Bit(self, "payload_unit_start") yield Bit(self, "priority") yield Enum( textHandler(Bits(self, "pid", 13, "Program identifier"), hexadecimal), self.PID) yield Bits(self, "scrambling_control", 2) yield Bit(self, "has_adaptation") yield Bit(self, "has_payload") yield Bits(self, "counter", 4) if self["has_adaptation"].value: yield AdaptationField(self, "adaptation_field") if self["has_payload"].value: size = 188 if self._m2ts: size += 4 size -= (self.current_size // 8) yield RawBytes(self, "payload", size) if self["has_error"].value: yield RawBytes(self, "error_correction", 16)
def __init__(self, parent, name, desc=None): FieldSet.__init__(self, parent, name, desc) pos = self.stream.searchBytesLength(CrossReferenceTable.MAGIC, False) if pos is None: raise ParserError("Can't find xref starting at %u" % (self.absolute_address // 8)) self._size = 8 * pos - self.absolute_address
def createFields(self): yield textHandler(UInt32(self, "magic", "File information magic (0xFEEF04BD)"), hexadecimal) if self["magic"].value != 0xFEEF04BD: raise ParserError("EXE resource: invalid file info magic") yield Version(self, "struct_ver", "Structure version (1.0)") yield Version(self, "file_ver_ms", "File version MS") yield Version(self, "file_ver_ls", "File version LS") yield Version(self, "product_ver_ms", "Product version MS") yield Version(self, "product_ver_ls", "Product version LS") yield textHandler(UInt32(self, "file_flags_mask"), hexadecimal) yield Bit(self, "debug") yield Bit(self, "prerelease") yield Bit(self, "patched") yield Bit(self, "private_build") yield Bit(self, "info_inferred") yield Bit(self, "special_build") yield NullBits(self, "reserved", 26) yield Enum(textHandler(UInt16(self, "file_os_major"), hexadecimal), MAJOR_OS_NAME) yield Enum(textHandler(UInt16(self, "file_os_minor"), hexadecimal), MINOR_OS_NAME) yield Enum(textHandler(UInt32(self, "file_type"), hexadecimal), FILETYPE_NAME) field = textHandler(UInt32(self, "file_subfile"), hexadecimal) if field.value == FILETYPE_DRIVER: field = Enum(field, DRIVER_SUBTYPE_NAME) elif field.value == FILETYPE_FONT: field = Enum(field, FONT_SUBTYPE_NAME) yield field yield TimestampUnix32(self, "date_ms") yield TimestampUnix32(self, "date_ls")
def __init__(self, parent, name, desc=None): FieldSet.__init__(self, parent, name, description=desc) pos = self.stream.searchBytesLength(Trailer.MAGIC, False) if pos is None: raise ParserError("Can't find '%s' starting at %u" % (Trailer.MAGIC, self.absolute_address // 8)) self._size = 8 * pos - self.absolute_address
def SerializedContent(parent, name, description=None): tc = parent.stream.readBits(parent.absolute_address + parent.current_size, 8, parent.endian) klass = TYPECODE_TABLE.get(tc, None) if klass is None: raise ParserError("Unknown typecode 0x%02x" % tc) return klass(parent, name, description)
def createFields(self): # Headers yield String(self, "header", 6, "Header (Exif\\0\\0)", charset="ASCII") if self["header"].value != "Exif\0\0": raise ParserError("Invalid EXIF signature!") iff_start = self.absolute_address + self.current_size ifds = [] for field in TIFF(self): yield field if isinstance(field, IFD): ifds.append(field) for ifd in ifds: data = {} for i, entry in enumerate(ifd.array('entry')): data[entry['tag'].display] = entry if 'JPEGInterchangeFormat' in data and 'JPEGInterchangeFormatLength' in data: offs = ifd.getEntryValues( data['JPEGInterchangeFormat'])[0].value size = ifd.getEntryValues( data['JPEGInterchangeFormatLength'])[0].value if size == 0: continue self.seekByte(offs + iff_start // 8, relative=False) yield SubFile(self, "thumbnail[]", size, "Thumbnail (JPEG file)", mime_type="image/jpeg")
def TIFF(self): iff_start = self.absolute_address + self.current_size yield String(self, "endian", 2, "Endian ('II' or 'MM')", charset="ASCII") if self["endian"].value not in ("II", "MM"): raise ParserError("Invalid endian!") if self["endian"].value == "II": self.endian = LITTLE_ENDIAN else: self.endian = BIG_ENDIAN yield UInt16(self, "version", "TIFF version number") yield UInt32(self, "img_dir_ofs", "Next image directory offset") offsets = [(self['img_dir_ofs'].value, 'ifd[]', IFD)] while offsets: offset, name, klass = offsets.pop(0) self.seekByte(offset + iff_start // 8, relative=False) ifd = klass(self, name, iff_start) yield ifd for entry in ifd.array('entry'): tag = entry['tag'].value if tag in IFD_TAGS: name, klass = IFD_TAGS[tag] offsets.append( (ifd.getEntryValues(entry)[0].value, name + '[]', klass)) elif tag == IFDEntry.SUBIFD_POINTERS: for val in ifd.getEntryValues(entry): offsets.append((val.value, ifd.name + '[]', IFD)) if ifd['next'].value != 0: offsets.append((ifd['next'].value, 'ifd[]', IFD))
def paletteParse(parent): size = parent["size"].value if (size % 3) != 0: raise ParserError("Palette have invalid size (%s), should be 3*n!" % size) nb_colors = size // 3 for index in xrange(nb_colors): yield RGB(parent, "color[]")
def createFields(self): uid = ReadNextByte(self) if uid == kHeader: yield Header(self, "header", PROP_DESC[uid]) elif uid == kEncodedHeader: yield EncodedHeader(self, "encoded_hdr", PROP_DESC[uid]) else: raise ParserError("Unexpected ID %u" % uid)