def createUnpaddedFields(self): yield String(self, "title", 28, strip='\0') yield textHandler(UInt8(self, "marker[]"), hexadecimal) for field in self.getFileVersionField(): yield field yield UInt16(self, "num_orders") yield UInt16(self, "num_instruments") yield UInt16(self, "num_patterns") for field in self.getFirstProperties(): yield field yield String(self, "marker[]", 4) for field in self.getLastProperties(): yield field yield GenericVector(self, "channel_settings", 32, ChannelSettings, "channel") # Orders yield GenericVector(self, "orders", self.getNumOrders(), UInt8, "order") for field in self.getHeaderEndFields(): yield field
def createFields(self): yield String(self, "name", 20, strip='\0') yield GenericVector(self, "samples", 31, SampleInfo, "info") yield UInt8(self, "length") yield UInt8(self, "played_patterns_count") yield GenericVector(self, "patterns", 128, UInt8, "position") yield String(self, "type", 4)
def createFields(self): yield String(self, "array_start", 1) while self.stream.readBytes(self.absolute_address + self.current_size, 1) != ']': for field in parsePDFType(self): yield field yield String(self, "array_end", 1)
def createFields(self): yield String(self, "header_id", 4, "DataBase Header Markup (\"mhbd\")", charset="ISO-8859-1") yield UInt32(self, "header_length", "Header Length") yield UInt32(self, "entry_length", "Entry Length") yield UInt32(self, "unknown[]") yield UInt32(self, "version_number", "Version Number") yield UInt32(self, "child_number", "Number of Children") yield UInt64(self, "id", "ID for this database") yield UInt16(self, "unknown[]") yield UInt32(self, "unknown[]") yield UInt64(self, "unknown[]") yield UInt16(self, "unknown[]") yield UInt16(self, "hashing_scheme[]", "Algorithm used to calculate the database hash") yield NullBytes(self, "unknown[]", 20) yield String(self, "language_id", 2, "Language ID") yield UInt64(self, "persistent_id", "Library Persistent ID") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield RawBytes(self, "hash[]", 20) yield Int32(self, "timezone_offset[]", "Timezone offset in seconds") yield UInt16(self, "unknown[]") yield RawBytes(self, "iphone_hash[]", 45) size = self["header_length"].value - self.current_size / 8 if size > 0: yield NullBytes(self, "padding", size) for i in range(self["child_number"].value): yield DataSet(self, "dataset[]") padding = self.seekByte(self["entry_length"].value, "entry padding") if padding: yield padding
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 createFields(self): yield String(self, "signature", 4, "AVI header (RIFF)", charset="ASCII") yield filesizeHandler(UInt32(self, "filesize", "File size")) yield String(self, "type", 4, "Content type (\"AVI \", \"WAVE\", ...)", charset="ASCII") # Choose chunk type depending on file type try: chunk_cls = self.VALID_TYPES[self["type"].value][0] except KeyError: chunk_cls = Chunk # Parse all chunks up to filesize while self.current_size < self["filesize"].value * 8 + 8: yield chunk_cls(self, "chunk[]") if not self.eof: yield RawBytes(self, "padding[]", (self.size - self.current_size) // 8)
def createFields(self): while self.stream.readBytes(self.absolute_address + self.current_size, 1) == b'%': size = getLineEnd(self, 4) if size == 2: yield String(self, "crc32_comment", 1) yield textHandler(UInt16(self, "crc32"), hexadecimal) elif size == 4: yield String(self, "crc32_comment", 1) yield textHandler(UInt32(self, "crc32"), hexadecimal) elif self.stream.readBytes( self.absolute_address + self.current_size, size).isalpha(): yield String(self, "comment[]", size) else: RawBytes(self, "unknown_data[]", size) yield LineEnd(self, "line_end[]") # abs_offset = self.current_size//8 # TODO: yield objects that read offsets and deduce size from # "/cross_ref_table/sub_section[]/entries/item[]" offsets = [] for subsection in self.array("/cross_ref_table/sub_section"): for obj in subsection.array("entries/item"): if "byte_offset" in obj: # Could be inserted already sorted offsets.append(obj["byte_offset"].value) offsets.append(self["/cross_ref_table"].absolute_address // 8) offsets.sort() for index in range(len(offsets) - 1): yield Catalog(self, "object[]", size=offsets[index + 1] - offsets[index])
def createFields(self): addr = self.absolute_address len = self.stream.searchBytesLength(b':', 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")) 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 createFields(self): yield Bits(self, "version", 4) yield Bits(self, "instance", 12) yield Enum(UInt16(self, "type"), PowerPointDocument.OBJ_TYPES) yield UInt32(self, "length") self._size = self["length"].value * 8 + 64 obj_type = self["type"].display obj_len = self["length"].value # type 1064 (RoundTripCustomTableStyles12) may appear to be a # container, but it is not. if self["version"].value == 0xF and self["type"].value != 1064: while (self.current_size) // 8 < obj_len + 8: yield PowerPointDocument.PowerPointObject(self, "object[]") elif obj_len: if obj_type == "FontEntityAtom": yield String(self, "data", obj_len, charset="UTF-16-LE", truncate="\0", strip="\0") elif obj_type == "TextCharsAtom": yield String(self, "data", obj_len, charset="UTF-16-LE") elif obj_type == "TextBytesAtom": yield String(self, "data", obj_len, charset="ASCII") elif hasattr(PowerPointDocument, obj_type): field = getattr(PowerPointDocument, obj_type)(self, "data") field._size = obj_len * 8 yield field else: yield RawBytes(self, "data", obj_len)
def createFields(self): yield String(self, "signature", 17, "XM signature", charset="ASCII") yield String(self, "title", 20, "XM title", charset="ASCII", strip=' ') yield UInt8(self, "marker", "Marker (0x1A)") yield String(self, "tracker_name", 20, "XM tracker name", charset="ASCII", strip=' ') yield UInt8(self, "format_minor") yield UInt8(self, "format_major") yield filesizeHandler(UInt32(self, "header_size", "Header size (276)")) yield UInt16(self, "song_length", "Length in patten order table") yield UInt16(self, "restart", "Restart position") yield UInt16(self, "channels", "Number of channels (2,4,6,8,10,...,32)") yield UInt16(self, "patterns", "Number of patterns (max 256)") yield UInt16(self, "instruments", "Number of instruments (max 128)") yield Bit(self, "amiga_ftable", "Amiga frequency table") yield Bit(self, "linear_ftable", "Linear frequency table") yield Bits(self, "unused", 14) yield UInt16(self, "tempo", "Default tempo") yield UInt16(self, "bpm", "Default BPM") yield GenericVector(self, "pattern_order", 256, UInt8, "order")
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 createFields(self): yield String(self, "signature", 4, 'Format signature (".snd")', charset="ASCII") yield UInt32(self, "data_ofs", "Data offset") yield filesizeHandler(UInt32(self, "data_size", "Data size")) yield Enum(UInt32(self, "codec", "Audio codec"), self.CODEC_NAME) yield displayHandler( UInt32(self, "sample_rate", "Number of samples/second"), humanFrequency) yield UInt32(self, "channels", "Number of interleaved channels") size = self["data_ofs"].value - self.current_size // 8 if 0 < size: yield String(self, "info", size, "Information", strip=" \0", charset="ISO-8859-1") size = min(self["data_size"].value, (self.size - self.current_size) // 8) yield RawBytes(self, "audio_data", size, "Audio data")
def createFields(self): yield ZipVersion(self, "version_made_by", "Version made by") # yield from ZipStartCommonFields(self) # PY3 for field in ZipStartCommonFields(self): yield field # Check unicode status charset = zipGetCharset(self) yield UInt16(self, "comment_length", "Comment length") yield UInt16(self, "disk_number_start", "Disk number start") yield UInt16(self, "internal_attr", "Internal file attributes") yield UInt32(self, "external_attr", "External file attributes") yield UInt32(self, "offset_header", "Relative offset of local header") yield String(self, "filename", self["filename_length"].value, "Filename", charset=charset) if 0 < self["extra_length"].value: yield ExtraFields(self, "extra", size=self["extra_length"].value * 8, description="Extra fields") if 0 < self["comment_length"].value: yield String(self, "comment", self["comment_length"].value, "Comment", charset=charset)
def createFields(self): size = self._size // 8 # TODO: Strings charset? if self.stream.readBytes(self.absolute_address, 9) == b"PeakValue": yield String(self, "text", 9, "Text") size -= 9 yield String(self, "content", size, "Content")
def createFields(self): yield Bytes(self, "jmp", 3, "Jump instruction (to skip over header on boot)") yield String(self, "oem_name", 8, "OEM Name (padded with spaces)", charset="ASCII") yield UInt16(self, "sector_size", "Bytes per sector") yield UInt8(self, "cluster_size", "Sectors per cluster") yield UInt16(self, "reserved_sectors", "Reserved sector count (including boot sector)") yield UInt8(self, "fat_nb", "Number of file allocation tables") yield UInt16(self, "max_root", "Maximum number of root directory entries") yield UInt16(self, "sectors1", "Total sectors (if zero, use 'sectors2')") yield UInt8(self, "media_desc", "Media descriptor") yield UInt16(self, "fat_size", "Sectors per FAT") yield UInt16(self, "track_size", "Sectors per track") yield UInt16(self, "head_nb", "Number of heads") yield UInt32(self, "hidden", "Hidden sectors") yield UInt32(self, "sectors2", "Total sectors (if greater than 65535)") if self.parent.version == 32: yield UInt32(self, "fat32_size", "Sectors per FAT") yield UInt16(self, "fat_flags", "FAT Flags") yield UInt16(self, "version", "Version") yield UInt32(self, "root_start", "Cluster number of root directory start") yield UInt16(self, "inf_sector", "Sector number of FS Information Sector") yield UInt16(self, "boot_copy", "Sector number of a copy of this boot sector") yield NullBytes(self, "reserved[]", 12, "Reserved") yield UInt8(self, "phys_drv", "Physical drive number") yield NullBytes(self, "reserved[]", 1, 'Reserved ("current head")') yield UInt8(self, "sign", "Signature") yield textHandler(UInt32(self, "serial", "ID (serial number)"), hexadecimal) yield String(self, "label", 11, "Volume Label", strip=' ', charset="ASCII") yield String(self, "fs_type", 8, "FAT file system type", strip=' ', charset="ASCII") yield Bytes(self, "code", 510 - self.current_size // 8, "Operating system boot code") yield Bytes(self, "trail_sig", 2, "Signature (0x55 0xAA)")
def createFields(self): yield textHandler(UInt32(self, "plugin_id1"), hexadecimal) yield textHandler(UInt32(self, "plugin_id2"), hexadecimal) yield UInt32(self, "input_routing") yield UInt32(self, "output_routing") yield GenericVector(self, "routing_info", 4, UInt32, "reserved") yield String(self, "name", 32, strip='\0') yield String(self, "dll_name", 64, desc="Original DLL name", strip='\0')
def createFields(self): yield Enum(UInt8(self, "charset"), self.charset_desc) yield String(self, "lang", 3, "Language", charset="ASCII") charset = getCharset(self["charset"]) yield CString(self, "title", "Title", charset=charset, strip=self.STRIP) size = (self.size - self.current_size) // 8 if not size: return yield String(self, "text", size, "Text", charset=charset, strip=self.STRIP)
def createFields(self): yield String(self, "marker", 5, MAGIC) length = getLineEnd(self, 4) if length is not None: # self.info("Found at position %08X" % len) yield String(self, "version", length - 1) yield LineEnd(self, "line_end") else: self.warning("Can't determine version!")
def createFields(self): yield String(self, "dict_start", 2) while not self.eof: addr = self.absolute_address + self.current_size if self.stream.readBytes(addr, 2) != b'>>': yield from parsePDFType(self) else: break yield String(self, "dict_end", 2)
def createFields(self): yield String(self, "signature", 4, "Signature (FORM)", charset="ASCII") yield filesizeHandler(UInt32(self, "filesize")) yield String(self, "type", 4, "Form type (AIFF or AIFC)", charset="ASCII") while not self.eof: yield Chunk(self, "chunk[]")
def createFields(self): yield String(self, "start", 1, "Dictionary start delimiter (d)", charset="ASCII") while self.stream.readBytes(self.absolute_address + self.current_size, 1) != b"e": yield DictionaryItem(self, "item[]") yield String(self, "end", 1, "Dictionary end delimiter")
def createFields(self): yield UInt32(self, "inodes_count", "Total inode count") yield UInt32(self, "blocks_count", "Total block count") yield UInt32(self, "r_blocks_count", "Reserved (superuser-only) block count") yield UInt32(self, "free_blocks_count", "Free block count") yield UInt32(self, "free_inodes_count", "Free inode count") yield UInt32(self, "first_data_block", "First data block") yield UInt32(self, "log_block_size", "Block size = 2**(10+log_block_size)") yield UInt32(self, "log_frag_size", "Cluster size = 2**log_frag_size") yield UInt32(self, "blocks_per_group", "Blocks per group") yield UInt32(self, "frags_per_group", "Fragments per group") yield UInt32(self, "inodes_per_group", "Inodes per group") yield TimestampUnix32(self, "mtime", "Mount time") yield TimestampUnix32(self, "wtime", "Write time") yield UInt16(self, "mnt_count", "Mount count since the last fsck") yield UInt16(self, "max_mnt_count", "Max mount count before fsck is needed") yield UInt16(self, "magic", "Magic number (0xEF53)") yield Enum(UInt16(self, "state", "File system state"), self.state_desc) yield Enum(UInt16(self, "errors", "Behaviour when detecting errors"), self.error_handling_desc) yield UInt16(self, "minor_rev_level", "Minor revision level") yield TimestampUnix32(self, "last_check", "Time of last check") yield textHandler(UInt32(self, "check_interval", "Maximum time between checks"), self.postMaxTime) yield Enum(UInt32(self, "creator_os", "Creator OS"), self.os_name) yield Enum(UInt32(self, "rev_level", "Revision level"), self.revision_levels) yield UInt16(self, "def_resuid", "Default uid for reserved blocks") yield UInt16(self, "def_resgid", "Default gid for reserved blocks") yield UInt32(self, "first_ino", "First non-reserved inode") yield UInt16(self, "inode_size", "Size of inode structure") yield UInt16(self, "block_group_nr", "Block group # of this superblock") yield FeatureCompatFlags(self, "feature_compat", "Compatible feature set (can mount even if these features are unsupported)") yield FeatureIncompatFlags(self, "feature_incompat", "Incompatible feature set (must support all features to mount)") yield FeatureROCompatFlags(self, "feature_ro_compat", "Read-only compatible feature set (can only mount r/o if a feature is unsupported)") yield UUID(self, "uuid", "128-bit UUID for volume") yield String(self, "volume_name", 16, "Volume name", strip="\0") yield String(self, "last_mounted", 64, "Directory where last mounted", strip="\0") yield UInt32(self, "compression", "For compression (algorithm usage bitmap)") yield UInt8(self, "prealloc_blocks", "Number of blocks to try to preallocate") yield UInt8(self, "prealloc_dir_blocks", "Number to preallocate for directories") yield UInt16(self, "reserved_gdt_blocks", "Number of reserved GDT entries for future expansion") yield RawBytes(self, "journal_uuid", 16, "UUID of journal superblock") yield UInt32(self, "journal_inum", "Inode number of journal file") yield UInt32(self, "journal_dev", "Device number of journal file (if ext_journal feature is set)") yield UInt32(self, "last_orphan", "Start of list of orphaned inodes to delete") # ext3 stuff yield RawBytes(self, "hash_seed", 16, "Seeds used for the directory indexing hash algorithm") yield Enum(UInt8(self, "def_hash_version", "Default hash version for directory indexing"), self.htree_hash_algo_desc) yield UInt8(self, "jnl_backup_type", "Does jnl_blocks contain a backup of i_block and i_size?") yield UInt16(self, "desc_size", "Size of group descriptors (if 64bit feature is set)") yield DefaultMountOptionFlags(self, "default_mount_opts", "Default mount options") yield UInt32(self, "first_meta_bg", "First metablock block group (if meta_bg feature is set)") yield TimestampUnix32(self, "mkfs_time", "When the filesystem was created") yield RawBytes(self, "jnl_blocks", 17 * 4, "Backup of the journal inode's i_block and i_size") yield PaddingBytes(self, "reserved[]", (1024 << self['log_block_size'].value) - self.current_size // 8)
def createFields(self): yield Enum(textHandler(UInt32(self, "type"), hexadecimal), self.ATTR_NAME) yield UInt32(self, "size") yield UInt8(self, "non_resident", "Non-resident flag") yield UInt8(self, "name_length", "Name length in bytes") yield UInt16(self, "name_offset", "Name offset") yield UInt16(self, "flags") yield textHandler(UInt16(self, "attribute_id"), hexadecimal) if self['non_resident'].value: yield UInt64(self, "runlist_start", "Starting Virtual Cluster Number of the runlist") yield UInt64(self, "runlist_stop", "Ending Virtual Cluster Number of the runlist") yield UInt16(self, "runlist_offset", "Offset to the runlist") yield UInt16(self, "compression_unit", "Compression unit size") yield UInt32(self, "unused[]") yield UInt64(self, "size_allocated", "Allocated size of the attribute content") yield UInt64(self, "size_actual", "Actual size of the attribute content") yield UInt64(self, "size_initialized", "Initialized size of the attribute content") if self['name_length'].value: padding = self.seekByte(self['name_offset'].value) if padding: yield padding yield String(self, "name", self['name_length'].value * 2, charset="UTF-16-LE") padding = self.seekByte(self['runlist_offset'].value) if padding: yield padding yield RunList(self, "runlist") else: yield UInt32(self, "length_attr", "Length of the Attribute") yield UInt16(self, "offset_attr", "Offset of the Attribute") yield UInt8(self, "indexed_flag") if self['name_length'].value: padding = self.seekByte(self['name_offset'].value) if padding: yield padding yield String(self, "name", self['name_length'].value * 2, charset="UTF-16-LE") padding = self.seekByte(self['offset_attr'].value) if padding: yield padding if self._parser: yield from self._parser(self) else: size = self["length_attr"].value if size: yield RawBytes(self, "data", size) size = (self.size - self.current_size) // 8 if size: yield PaddingBytes(self, "end_padding", size)
def createFields(self): yield String(self, "sectname", 16, strip="\0") yield String(self, "segname", 16, strip="\0") yield textHandler(UInt32(self, "addr"), hexadecimal) yield textHandler(UInt32(self, "size"), hexadecimal) yield textHandler(UInt32(self, "offset"), hexadecimal) yield textHandler(UInt32(self, "align"), hexadecimal) yield textHandler(UInt32(self, "reloff"), hexadecimal) yield UInt32(self, "nreloc") yield UInt32(self, "flags") yield UInt32(self, "reserved1") yield UInt32(self, "reserved2")
def createFields(self): yield UInt8(self, "version", "Version") yield NullBits(self, "flags", 24) yield String(self, "creator", 4) yield String(self, "subtype", 4) yield String(self, "manufacturer", 4) yield UInt32(self, "res_flags") yield UInt32(self, "res_flags_mask") if self.root.is_mpeg4: yield CString(self, "name", charset="UTF-8") else: yield PascalString8(self, "name")
def createFields(self): yield self.getType() yield String(self, "filename", 12, strip='\0') yield from self.getInstrumentFields() yield String(self, "name", 28, strip='\0') yield String(self, "marker", 4, "Either 'SCRS' or '(empty)'", strip='\0')
def createFields(self): yield String(self, "header_id", 4, "Data Object Header Markup (\"mhod\")", charset="ISO-8859-1") yield UInt32(self, "header_length", "Header Length") yield UInt32(self, "entry_length", "Entry Length") yield Enum(UInt32(self, "type", "type"), self.type_name) if (self["type"].value == 15) or (self["type"].value == 16): yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield String(self, "string", self._size // 8 - self["header_length"].value, "String Data", charset="UTF-8") elif (self["type"].value == 52): yield UInt32(self, "unknown[]", "unk1") yield UInt32(self, "unknown[]", "unk2") yield Enum(UInt32(self, "sort_index_type", "Sort Index Type"), self.mhod52_sort_index_type_name) yield UInt32(self, "entry_count", "Entry Count") indexes_size = self["entry_count"].value * 4 padding_offset = self["entry_length"].value - indexes_size padding = self.seekByte(padding_offset, "header padding") if padding: yield padding for i in range(self["entry_count"].value): yield UInt32(self, "index[" + str(i) + "]", "Index of the " + str(i) + "nth mhit") elif (self["type"].value < 15) or (self["type"].value > 17) or (self["type"].value >= 200): yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield UInt32(self, "position", "Position") yield UInt32(self, "length", "String Length in bytes") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield String(self, "string", self["length"].value, "String Data", charset="UTF-16-LE") else: padding = self.seekByte(self["header_length"].value, "header padding") if padding: yield padding padding = self.seekBit(self._size, "entry padding") if padding: yield padding
def createFields(self): yield UInt16(self, "length", "Length of this string") if self["length"].value: if self.root.hasUnicodeNames(): yield String(self, "data", self["length"].value * 2, charset="UTF-16-LE") else: yield String(self, "data", self["length"].value, charset="ASCII")
def createFields(self): yield UInt8(self, "size") self._size = (self['size'].value + 1) * 8 yield Enum(UInt8(self, "type"), self.STREAMTYPE) if self['type'].display.startswith('V'): # Video yield Enum( Bits(self, "resolution", 4), { 1: '480i', 2: '576i', 3: '480p', 4: '1080i', 5: '720p', 6: '1080p', 7: '576p' }) yield Enum( Bits(self, "fps", 4), { 1: '24/1.001', 2: '24', 3: '25', 4: '30/1.001', 6: '50', 7: '60/1.001' }) yield Enum(UInt8(self, "aspect_ratio"), { 0x20: '4:3', 0x30: '16:9' }) elif self['type'].display.startswith('A'): # Audio yield Enum(Bits(self, "channel_layout", 4), { 1: 'Mono', 3: 'Stereo', 6: 'Multi', 12: 'Combi' }) yield Enum( Bits(self, "sample_rate", 4), { 1: '48KHz', 4: '96KHz', 5: '192KHz', 12: '48-192KHz', 14: '48-96KHz' }) yield Enum(String(self, "language", 3), ISO639_2) elif self['type'].display.startswith('T'): # Text subtitle yield UInt8(self, "unknown[]") yield Enum(String(self, "language", 3), ISO639_2) elif self['type'].display.startswith('S'): # Graphics yield Enum(String(self, "language", 3), ISO639_2) else: pass
def createFields(self): yield String(self, "signature", 3, "IDv1 signature (\"TAG\")", charset="ASCII") if self["signature"].value != "TAG": raise MatchError( "Stream doesn't look like ID3v1 (wrong signature)!") # TODO: Charset of below strings? yield String(self, "song", 30, "Song title", strip=" \0", charset="ISO-8859-1") yield String(self, "author", 30, "Author", strip=" \0", charset="ISO-8859-1") yield String(self, "album", 30, "Album title", strip=" \0", charset="ISO-8859-1") yield String(self, "year", 4, "Year", strip=" \0", charset="ISO-8859-1") # TODO: Write better algorithm to guess ID3v1 version version = self.getVersion() if version in ("v1.1", "v1.1b"): if version == "v1.1b": # ID3 v1.1b yield String(self, "comment", 29, "Comment", strip=" \0", charset="ISO-8859-1") yield UInt8(self, "track_nb", "Track number") else: # ID3 v1.1 yield String(self, "comment", 30, "Comment", strip=" \0", charset="ISO-8859-1") yield Enum(UInt8(self, "genre", "Genre"), self.GENRE_NAME) else: # ID3 v1.0 yield String(self, "comment", 31, "Comment", strip=" \0", charset="ISO-8859-1")