Example #1
0
 def createFields(self):
     yield UInt16(self, "signature", "PE optional header signature (0x010b)")
     # TODO: Support PE32+ (signature=0x020b)
     if self["signature"].value != 0x010b:
         raise ParserError("Invalid PE optional header signature")
     yield UInt8(self, "maj_lnk_ver", "Major linker version")
     yield UInt8(self, "min_lnk_ver", "Minor linker version")
     yield filesizeHandler(UInt32(self, "size_code", "Size of code"))
     yield filesizeHandler(UInt32(self, "size_init_data", "Size of initialized data"))
     yield filesizeHandler(UInt32(self, "size_uninit_data", "Size of uninitialized data"))
     yield textHandler(UInt32(self, "entry_point", "Address (RVA) of the code entry point"), hexadecimal)
     yield textHandler(UInt32(self, "base_code", "Base (RVA) of code"), hexadecimal)
     yield textHandler(UInt32(self, "base_data", "Base (RVA) of data"), hexadecimal)
     yield textHandler(UInt32(self, "image_base", "Image base (RVA)"), hexadecimal)
     yield filesizeHandler(UInt32(self, "sect_align", "Section alignment"))
     yield filesizeHandler(UInt32(self, "file_align", "File alignment"))
     yield UInt16(self, "maj_os_ver", "Major OS version")
     yield UInt16(self, "min_os_ver", "Minor OS version")
     yield UInt16(self, "maj_img_ver", "Major image version")
     yield UInt16(self, "min_img_ver", "Minor image version")
     yield UInt16(self, "maj_subsys_ver", "Major subsystem version")
     yield UInt16(self, "min_subsys_ver", "Minor subsystem version")
     yield NullBytes(self, "reserved", 4)
     yield filesizeHandler(UInt32(self, "size_img", "Size of image"))
     yield filesizeHandler(UInt32(self, "size_hdr", "Size of headers"))
     yield textHandler(UInt32(self, "checksum"), hexadecimal)
     yield Enum(UInt16(self, "subsystem"), self.SUBSYSTEM_NAME)
     yield UInt16(self, "dll_flags")
     yield filesizeHandler(UInt32(self, "size_stack_reserve"))
     yield filesizeHandler(UInt32(self, "size_stack_commit"))
     yield filesizeHandler(UInt32(self, "size_heap_reserve"))
     yield filesizeHandler(UInt32(self, "size_heap_commit"))
     yield UInt32(self, "loader_flags")
     yield UInt32(self, "nb_directory", "Number of RVA and sizes")
     for index in xrange(self["nb_directory"].value):
         try:
             name = self.DIRECTORY_NAME[index]
         except KeyError:
             name = "data_dir[%u]" % index
         yield DataDirectory(self, name)
Example #2
0
    def __init__(self, parent, name, desc=None):
        Field.__init__(self, parent, name, description=desc)
        if parent.stream.readBytes(self.absolute_address, 1) != b'/':
            raise ParserError(
                "Unknown PDFName '%s'" %
                parent.stream.readBytes(self.absolute_address, 10))
        size = getElementEnd(parent, offset=1)
        # other_size = getElementEnd(parent, '[')-1
        #  if size is None or (other_size is not None and other_size < size):
        #     size = other_size
        for limit in self.LIMITS:
            other_size = getElementEnd(parent, limit, 1)
            if other_size is not None:
                other_size -= 1
                if size is None or other_size < size:
                    # self.info("New size: %u" % other_size)
                    size = other_size

        self._size = 8 * (size + 1)
        # Value should be without the initial '/' and final ' '
        self.createValue = lambda: parent.stream.readBytes(
            self.absolute_address + 8, size).strip(b' ')
Example #3
0
 def _createFields(self, field_generator):
     if self._first is None:
         for field in field_generator:
             if self._first is not None:
                 break
             yield field
         else:
             raise ParserError("Fragment.setLinks not called")
     else:
         field = None
     if self._first is not self:
         link = Link(self, "first", None)
         link._getValue = lambda: self._first
         yield link
     if self._next:
         link = Link(self, "next", None)
         link.createValue = self._getNext
         yield link
     if field:
         yield field
     for field in field_generator:
         yield field
Example #4
0
 def __init__(self, parent, name, description=None):
     FieldSet.__init__(self, parent, name, description)
     self._size = (self["size"].value + 3 * 4) * 8
     if MAX_CHUNK_SIZE < (self._size // 8):
         raise ParserError("PNG: Chunk is too big (%s)" %
                           humanFilesize(self._size // 8))
     tag = self["tag"].value
     self.desc_func = None
     self.value_func = None
     if tag in self.TAG_INFO:
         self._name, self.parse_func, desc, value_func = self.TAG_INFO[tag]
         if value_func:
             self.value_func = value_func
             self.createValue = self.createValueFunc
         if desc:
             if isinstance(desc, str):
                 self._description = desc
             else:
                 self.desc_func = desc
     else:
         self._description = ""
         self.parse_func = None
Example #5
0
    def createFields(self):
        yield UInt32(self, "unknown", description="Always 1")
        yield BudHeader(self, "header")
        self.seekByte(self['header/allocator_offset'].value + 4)
        yield BudAllocator(self,
                           "allocator",
                           size=self['header/allocator_size'].value * 8)
        for dir in self['allocator'].array('dir'):
            if dir['name'].value == 'DSDB':
                break
        else:
            raise ParserError("DSDB not found.")
        offs, size = self.getBlock(dir['block'].value)
        self.seekByte(offs + 4)
        yield DSDB(self, "dsdb", size=size * 8)

        blocks = [self['dsdb/root_block'].value]
        while blocks:
            block = blocks.pop()
            offs, size = self.getBlock(block)
            self.seekByte(offs + 4)
            node = BTNode(self, "node[%d]" % block, size=size * 8)
            yield node
            if node['last_block'].value != 0:
                new_blocks = []
                for block in node.array('child_block'):
                    new_blocks.append(block.value)
                new_blocks.append(node['last_block'].value)
                blocks.extend(reversed(new_blocks))  # dfs
                # blocks = new_blocks[::-1] + blocks # bfs

        for i, fl in enumerate(self['allocator'].array('freelist')):
            if fl['count'].value == 0:
                continue
            for offs in fl.array('offset'):
                size = min(1 << i, self.size // 8 - offs.value - 4)
                if size > 0:
                    self.seekByte(offs.value + 4)
                    yield RawBytes(self, "free[]", size)
Example #6
0
 def createFields(self):
     yield UInt32(self, "width", "Width in pixel")
     yield UInt32(self, "height", "Height in pixel")
     yield UInt32(self, "offset", "Offset")
     offset = self["offset"].value
     if offset == 0:
         return
     data_offsets = []
     while (self.absolute_address + self.current_size) // 8 < offset:
         chunk = UInt32(self, "data_offset[]", "Data offset")
         yield chunk
         if chunk.value == 0:
             break
         data_offsets.append(chunk)
     if (self.absolute_address + self.current_size) // 8 != offset:
         raise ParserError("Problem with level offset.")
     previous = offset
     for chunk in data_offsets:
         data_offset = chunk.value
         size = data_offset - previous
         yield RawBytes(self, "data[]", size, "Data content of %s" % chunk.name)
         previous = data_offset
Example #7
0
    def createFields(self):
        yield PropID(self, "id")

        yield PropID(self, "folder_marker")
        assert self['folder_marker'].value == kFolder
        yield SZUInt64(self, "num_folders")

        # Get generic info
        num = self["num_folders"].value
        self.info("%u folders" % num)
        yield UInt8(self, "is_external")

        if self['is_external'].value:
            yield SZUInt64(self, "folder_data_offset",
                           "Offset to folder data within data stream")
        else:
            # Read folder items
            for folder_index in range(num):
                yield Folder(self, "folder[]")

        yield PropID(self, "unpacksize_marker")
        assert self['unpacksize_marker'].value == kCodersUnPackSize
        for folder_index in range(num):
            folder = self["folder[%u]" % folder_index]
            for index in range(folder.out_streams):
                yield SZUInt64(self,
                               "unpack_size[%d][%d]" % (folder_index, index))

        # Extract digests
        while not self.eof:
            uid = ReadNextByte(self)
            if uid == kEnd:
                yield PropID(self, "end_marker")
                break
            elif uid == kCRC:
                yield Digests(self, "digests", num)
            else:
                raise ParserError("Unexpected ID (%i)" % uid)
Example #8
0
def parseAVIStreamHeader(self):
    if self["size"].value != 56:
        raise ParserError("Invalid stream header size")
    yield String(self,
                 "stream_type",
                 4,
                 "Stream type four character code",
                 charset="ASCII")
    field = String(self,
                   "fourcc",
                   4,
                   "Stream four character code",
                   strip=" \0",
                   charset="ASCII")
    if self["stream_type"].value == "vids":
        yield Enum(field, video_fourcc_name, lambda text: text.upper())
    else:
        yield field
    yield UInt32(self, "flags", "Stream flags")
    yield UInt16(self, "priority", "Stream priority")
    yield String(self,
                 "language",
                 2,
                 "Stream language",
                 charset="ASCII",
                 strip="\0")
    yield UInt32(self, "init_frames", "InitialFrames")
    yield UInt32(self, "scale", "Time scale")
    yield UInt32(self, "rate", "Divide by scale to give frame rate")
    yield UInt32(self, "start", "Stream start time (unit: rate/scale)")
    yield UInt32(self, "length", "Stream length (unit: rate/scale)")
    yield UInt32(self, "buf_size", "Suggested buffer size")
    yield UInt32(self, "quality", "Stream quality")
    yield UInt32(self, "sample_size", "Size of samples")
    yield UInt16(self, "left", "Destination rectangle (left)")
    yield UInt16(self, "top", "Destination rectangle (top)")
    yield UInt16(self, "right", "Destination rectangle (right)")
    yield UInt16(self, "bottom", "Destination rectangle (bottom)")
Example #9
0
 def createFields(self):
     yield UInt16(self, "count", "Number of entries")
     count = self["count"].value
     if count == 0:
         raise ParserError("IFDs cannot be empty.")
     for i in range(count):
         yield self.EntryClass(self, "entry[]")
     yield UInt32(self, "next", "Offset to next IFD")
     for i in range(count):
         entry = self['entry[%d]' % i]
         if 'offset' not in entry:
             continue
         self.seekByte(entry['offset'].value + self.base_addr // 8,
                       relative=False)
         count = entry['count'].value
         name = "value[%s]" % i
         if issubclass(entry.value_cls, Bytes):
             yield entry.value_cls(self, name, count)
         else:
             if count > 1:
                 name += "[]"
             for i in range(count):
                 yield entry.value_cls(self, name)
Example #10
0
 def createFields(self):
     yield String(self, "signature", 4, "8BIM signature", charset="ASCII")
     if self["signature"].value != "8BIM":
         raise ParserError(
             "Stream doesn't look like 8BIM item (wrong signature)!")
     yield textHandler(UInt16(self, "tag"), hexadecimal)
     if self.stream.readBytes(self.absolute_address + self.current_size, 4) != b"\0\0\0\0":
         yield PascalString8(self, "name")
         size = 2 + (self["name"].size // 8) % 2
         yield NullBytes(self, "name_padding", size)
     else:
         yield String(self, "name", 4, strip="\0")
     yield UInt16(self, "size")
     size = alignValue(self["size"].value, 2)
     if not size:
         return
     if self.handler:
         if issubclass(self.handler, FieldSet):
             yield self.handler(self, "content", size=size * 8)
         else:
             yield self.handler(self, "content")
     else:
         yield RawBytes(self, "content", size)
Example #11
0
    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)
Example #12
0
 def _feedLinks(self):
     while self._first is None and self.readMoreFields(1):
         pass
     if self._first is None:
         raise ParserError("first is None")
     return self
Example #13
0
 def createFields(self):
     yield Bits(self, "block_type", 3)
     yield Bits(self, "block_size", 24)
     self.uncompressed_size = self["block_size"].value
     self.compression_level = self.root.compr_level
     self.window_size = self.WINDOW_SIZE[self.compression_level]
     self.block_type = self["block_type"].value
     curlen = len(self.parent.uncompressed_data)
     if self.block_type in (1, 2):  # Verbatim or aligned offset block
         if self.block_type == 2:
             for i in range(8):
                 yield Bits(self, "aligned_len[]", 3)
             aligned_tree = build_tree(
                 [self['aligned_len[%d]' % i].value for i in range(8)])
         yield LZXPreTreeEncodedTree(self, "main_tree_start", 256)
         yield LZXPreTreeEncodedTree(self, "main_tree_rest",
                                     self.window_size * 8)
         main_tree = build_tree(self["main_tree_start"].lengths +
                                self["main_tree_rest"].lengths)
         yield LZXPreTreeEncodedTree(self, "length_tree", 249)
         length_tree = build_tree(self["length_tree"].lengths)
         current_decoded_size = 0
         while current_decoded_size < self.uncompressed_size:
             if (curlen + current_decoded_size) % 32768 == 0 and (
                     curlen + current_decoded_size) != 0:
                 padding = paddingSize(self.address + self.current_size, 16)
                 if padding:
                     yield PaddingBits(self, "padding[]", padding)
             field = HuffmanCode(self, "main_code[]", main_tree)
             if field.realvalue < 256:
                 field._description = "Literal value %r" % chr(
                     field.realvalue)
                 current_decoded_size += 1
                 self.parent.uncompressed_data += chr(field.realvalue)
                 yield field
                 continue
             position_header, length_header = divmod(
                 field.realvalue - 256, 8)
             info = self.POSITION_SLOTS[position_header]
             if info[2] == 0:
                 if info[0] == 0:
                     position = self.parent.r0
                     field._description = "Position Slot %i, Position [R0] (%i)" % (
                         position_header, position)
                 elif info[0] == 1:
                     position = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R1] (%i)" % (
                         position_header, position)
                 elif info[0] == 2:
                     position = self.parent.r2
                     self.parent.r2 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R2] (%i)" % (
                         position_header, position)
                 else:
                     position = info[0] - 2
                     self.parent.r2 = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position %i" % (
                         position_header, position)
             else:
                 field._description = "Position Slot %i, Positions %i to %i" % (
                     position_header, info[0] - 2, info[1] - 2)
             if length_header == 7:
                 field._description += ", Length Values 9 and up"
                 yield field
                 length_field = HuffmanCode(self, "length_code[]",
                                            length_tree)
                 length = length_field.realvalue + 9
                 length_field._description = "Length Code %i, total length %i" % (
                     length_field.realvalue, length)
                 yield length_field
             else:
                 field._description += ", Length Value %i (Huffman Code %i)" % (
                     length_header + 2, field.value)
                 yield field
                 length = length_header + 2
             if info[2]:
                 if self.block_type == 1 or info[2] < 3:  # verbatim
                     extrafield = Bits(
                         self,
                         "position_extra[%s" % field.name.split('[')[1],
                         info[2])
                     position = extrafield.value + info[0] - 2
                     extrafield._description = "Position Extra Bits (%i), total position %i" % (
                         extrafield.value, position)
                     yield extrafield
                 else:  # aligned offset
                     position = info[0] - 2
                     if info[2] > 3:
                         extrafield = Bits(
                             self, "position_verbatim[%s" %
                             field.name.split('[')[1], info[2] - 3)
                         position += extrafield.value * 8
                         extrafield._description = "Position Verbatim Bits (%i), added position %i" % (
                             extrafield.value, extrafield.value * 8)
                         yield extrafield
                     if info[2] >= 3:
                         extrafield = HuffmanCode(
                             self, "position_aligned[%s" %
                             field.name.split('[')[1], aligned_tree)
                         position += extrafield.realvalue
                         extrafield._description = "Position Aligned Bits (%i), total position %i" % (
                             extrafield.realvalue, position)
                         yield extrafield
                 self.parent.r2 = self.parent.r1
                 self.parent.r1 = self.parent.r0
                 self.parent.r0 = position
             self.parent.uncompressed_data = extend_data(
                 self.parent.uncompressed_data, length, position)
             current_decoded_size += length
     elif self.block_type == 3:  # Uncompressed block
         padding = paddingSize(self.address + self.current_size, 16)
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         else:
             yield PaddingBits(self, "padding[]", 16)
         self.endian = LITTLE_ENDIAN
         yield UInt32(self, "r[]", "New value of R0")
         yield UInt32(self, "r[]", "New value of R1")
         yield UInt32(self, "r[]", "New value of R2")
         self.parent.r0 = self["r[0]"].value
         self.parent.r1 = self["r[1]"].value
         self.parent.r2 = self["r[2]"].value
         yield RawBytes(self, "data", self.uncompressed_size)
         self.parent.uncompressed_data += self["data"].value
         if self["block_size"].value % 2:
             yield PaddingBits(self, "padding", 8)
     else:
         raise ParserError("Unknown block type %d!" % self.block_type)
Example #14
0
 def createFields(self):
     yield textHandler(Bits(self, "blockheader", 48, "Block header"),
                       hexadecimal)
     if self["blockheader"].value != 0x314159265359:  # pi
         raise ParserError("Invalid block header!")
     yield textHandler(UInt32(self, "crc32", "CRC32 for this block"),
                       hexadecimal)
     yield Bit(self, "randomized", "Is this block randomized?")
     yield Bits(self, "orig_bwt_pointer", 24,
                "Starting pointer into BWT after untransform")
     yield GenericVector(
         self, "huffman_used_map", 16, Bit, 'block_used',
         "Bitmap showing which blocks (representing 16 literals each) are in use"
     )
     symbols_used = []
     for index, block_used in enumerate(
             self["huffman_used_map"].array('block_used')):
         if block_used.value:
             start_index = index * 16
             field = Bzip2Bitmap(
                 self, "huffman_used_bitmap[%i]" % index, 16, start_index,
                 "Bitmap for block %i (literals %i to %i) showing which symbols are in use"
                 % (index, start_index, start_index + 15))
             yield field
             for i, used in enumerate(field):
                 if used.value:
                     symbols_used.append(start_index + i)
     yield Bits(self, "huffman_groups", 3,
                "Number of different Huffman tables in use")
     yield Bits(self, "selectors_used", 15,
                "Number of times the Huffman tables are switched")
     yield Bzip2Selectors(self, "selectors_list",
                          self["huffman_groups"].value)
     trees = []
     for group in range(self["huffman_groups"].value):
         field = Bzip2Lengths(self, "huffman_lengths[]",
                              len(symbols_used) + 2)
         yield field
         trees.append(field.tree)
     counter = 0
     rle_run = 0
     selector_tree = None
     while True:
         if counter % 50 == 0:
             select_id = self["selectors_list"].array("selector_list")[
                 counter // 50].realvalue
             selector_tree = trees[select_id]
         field = HuffmanCode(self, "huffman_code[]", selector_tree)
         if field.realvalue in [0, 1]:
             # RLE codes
             if rle_run == 0:
                 rle_power = 1
             rle_run += (field.realvalue + 1) * rle_power
             rle_power <<= 1
             field._description = "RLE Run Code %i (for %r); Total accumulated run %i (Huffman Code %i)" % (
                 field.realvalue, chr(
                     symbols_used[0]), rle_run, field.value)
         elif field.realvalue == len(symbols_used) + 1:
             field._description = "Block Terminator (%i) (Huffman Code %i)" % (
                 field.realvalue, field.value)
             yield field
             break
         else:
             rle_run = 0
             move_to_front(symbols_used, field.realvalue - 1)
             field._description = "Literal %r (value %i) (Huffman Code %i)" % (
                 chr(symbols_used[0]), field.realvalue, field.value)
         yield field
         if field.realvalue == len(symbols_used) + 1:
             break
         counter += 1
Example #15
0
def readBoolean(self, content_size):
    if content_size != 1:
        raise ParserError("Overlong boolean: got %s bytes, expected 1 byte" %
                          content_size)
    yield textHandler(UInt8(self, "value"),
                      lambda field: str(bool(field.value)))
Example #16
0
    def createFields(self):
        superblock = self["/superblock"]

        # Compute number of block and inodes
        block_count = superblock["blocks_per_group"].value
        inode_count = superblock["inodes_per_group"].value
        block_index = self.descriptor.uniq_id * block_count
        inode_index = self.descriptor.uniq_id * inode_count
        if (block_count % 8) != 0:
            raise ParserError("Invalid block count")
        if (inode_count % 8) != 0:
            raise ParserError("Invalid inode count")
        block_count = min(block_count,
                          superblock["blocks_count"].value - block_index)
        inode_count = min(inode_count,
                          superblock["inodes_count"].value - inode_index)

        bitmap_block_size = self.root.block_size * 8
        block_bitmap_size = (block_count + bitmap_block_size -
                             1) // bitmap_block_size * bitmap_block_size
        inode_bitmap_size = (inode_count + bitmap_block_size -
                             1) // bitmap_block_size * bitmap_block_size

        self.seekBlock(self.descriptor["block_bitmap"].value)
        yield BlockBitmap(self, "block_bitmap", block_index, block_count,
                          block_bitmap_size, "Block bitmap")

        self.seekBlock(self.descriptor["inode_bitmap"].value)
        yield InodeBitmap(self, "inode_bitmap", inode_index, inode_count,
                          inode_bitmap_size, "Inode bitmap")

        self.seekBlock(self.descriptor["inode_table"].value)
        yield InodeTable(self, "inode_table", inode_index, inode_count)

        inode_bitmap = self['inode_bitmap']
        for i, inode in enumerate(self['inode_table'].array('inode')):
            if not inode_bitmap['item[%d]' % i].value:
                continue
            if inode['blocks'].value == 0:
                continue
            blocks = inode.array('block')
            if inode['mode/file_type'].display == 'Directory':
                parser = Directory
            else:
                parser = None
            group = FragmentGroup(parser=parser)
            for b in range(12):
                if not blocks[b].value:
                    continue
                self.seekBlock(blocks[b].value)
                yield CustomFragment(self,
                                     "inode[%d]block[]" % i,
                                     self.root.block_size * 8,
                                     None,
                                     group=group)
            if blocks[12].value:
                # indirect block
                self.seekBlock(blocks[12].value)
                indirect = IndirectBlock(self, "inode[%d]indirect" % i,
                                         self.root.block_size)
                yield indirect
                for b in indirect.array('block'):
                    if not b.value:
                        continue
                    self.seekBlock(b.value)
                    yield CustomFragment(self,
                                         "inode[%d]block[]" % i,
                                         self.root.block_size * 8,
                                         None,
                                         group=group)
            if blocks[13].value:
                # TODO: double-indirect block
                pass
            if blocks[14].value:
                # TODO: triple-indirect block
                pass
Example #17
0
 def createFields(self):
     yield Bit(self, "final", "Is this the final block?")  # BFINAL
     yield Enum(
         Bits(self, "compression_type", 2),  # BTYPE
         {
             0: "None",
             1: "Fixed Huffman",
             2: "Dynamic Huffman",
             3: "Reserved"
         })
     if self["compression_type"].value == 0:  # no compression
         padding = paddingSize(self.current_size + self.absolute_address,
                               8)  # align on byte boundary
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         yield Int16(self, "len")
         yield Int16(self, "nlen", "One's complement of len")
         if self["len"].value != ~self["nlen"].value:
             raise ParserError(
                 "len must be equal to the one's complement of nlen!")
         if self["len"].value:  # null stored blocks produced by some encoders (e.g. PIL)
             yield RawBytes(self, "data", self["len"].value,
                            "Uncompressed data")
         return
     elif self["compression_type"].value == 1:  # Fixed Huffman
         length_tree = {}  # (size, huffman code): value
         distance_tree = {}
         for i in xrange(144):
             length_tree[(8, i + 48)] = i
         for i in xrange(144, 256):
             length_tree[(9, i + 256)] = i
         for i in xrange(256, 280):
             length_tree[(7, i - 256)] = i
         for i in xrange(280, 288):
             length_tree[(8, i - 88)] = i
         for i in xrange(32):
             distance_tree[(5, i)] = i
     elif self["compression_type"].value == 2:  # Dynamic Huffman
         yield Bits(self, "huff_num_length_codes", 5,
                    "Number of Literal/Length Codes, minus 257")
         yield Bits(self, "huff_num_distance_codes", 5,
                    "Number of Distance Codes, minus 1")
         yield Bits(self, "huff_num_code_length_codes", 4,
                    "Number of Code Length Codes, minus 4")
         code_length_code_lengths = [0] * 19  # confusing variable name...
         for i in self.CODE_LENGTH_ORDER[:self["huff_num_code_length_codes"]
                                         .value + 4]:
             field = Bits(self, "huff_code_length_code[%i]" % i, 3,
                          "Code lengths for the code length alphabet")
             yield field
             code_length_code_lengths[i] = field.value
         code_length_tree = build_tree(code_length_code_lengths)
         length_code_lengths = []
         distance_code_lengths = []
         for numcodes, name, lengths in (
             (self["huff_num_length_codes"].value + 257, "length",
              length_code_lengths),
             (self["huff_num_distance_codes"].value + 1, "distance",
              distance_code_lengths)):
             while len(lengths) < numcodes:
                 field = HuffmanCode(self, "huff_%s_code[]" % name,
                                     code_length_tree)
                 value = field.realvalue
                 if value < 16:
                     prev_value = value
                     field._description = "Literal Code Length %i (Huffman Code %i)" % (
                         value, field.value)
                     yield field
                     lengths.append(value)
                 else:
                     info = {
                         16: (3, 6, 2),
                         17: (3, 10, 3),
                         18: (11, 138, 7)
                     }[value]
                     if value == 16:
                         repvalue = prev_value
                     else:
                         repvalue = 0
                     field._description = "Repeat Code %i, Repeating value (%i) %i to %i times (Huffman Code %i)" % (
                         value, repvalue, info[0], info[1], field.value)
                     yield field
                     extrafield = Bits(
                         self, "huff_%s_code_extra[%s" %
                         (name, field.name.split('[')[1]), info[2])
                     num_repeats = extrafield.value + info[0]
                     extrafield._description = "Repeat Extra Bits (%i), total repeats %i" % (
                         extrafield.value, num_repeats)
                     yield extrafield
                     lengths += [repvalue] * num_repeats
         length_tree = build_tree(length_code_lengths)
         distance_tree = build_tree(distance_code_lengths)
     else:
         raise ParserError("Unsupported compression type 3!")
     while True:
         field = HuffmanCode(self, "length_code[]", length_tree)
         value = field.realvalue
         if value < 256:
             field._description = "Literal Code %r (Huffman Code %i)" % (
                 chr(value), field.value)
             yield field
             self.uncomp_data += chr(value)
         if value == 256:
             field._description = "Block Terminator Code (256) (Huffman Code %i)" % field.value
             yield field
             break
         elif value > 256:
             info = self.LENGTH_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Length Code %i, Value %i (Huffman Code %i)" % (
                     value, info[0], field.value)
                 length = info[0]
                 yield field
             else:
                 field._description = "Length Code %i, Values %i to %i (Huffman Code %i)" % (
                     value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(
                     self, "length_extra[%s" % field.name.split('[')[1],
                     info[2])
                 length = extrafield.value + info[0]
                 extrafield._description = "Length Extra Bits (%i), total length %i" % (
                     extrafield.value, length)
                 yield extrafield
             field = HuffmanCode(self, "distance_code[]", distance_tree)
             value = field.realvalue
             info = self.DISTANCE_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Distance Code %i, Value %i (Huffman Code %i)" % (
                     value, info[0], field.value)
                 distance = info[0]
                 yield field
             else:
                 field._description = "Distance Code %i, Values %i to %i (Huffman Code %i)" % (
                     value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(
                     self, "distance_extra[%s" % field.name.split('[')[1],
                     info[2])
                 distance = extrafield.value + info[0]
                 extrafield._description = "Distance Extra Bits (%i), total length %i" % (
                     extrafield.value, distance)
                 yield extrafield
             self.uncomp_data = extend_data(self.uncomp_data, length,
                                            distance)
Example #18
0
def getCharset(field):
    try:
        key = field.value
        return ID3_StringCharset.charset_name[key]
    except KeyError:
        raise ParserError("ID3v2: Invalid charset (%s)." % key)