Exemplo n.º 1
0
    def createFields(self):
        # Header
        yield NullBytes(self, "zero_vector", 16)
        yield GUID(self, "fs_guid")
        yield UInt64(self, "volume_len")
        yield String(self, "signature", 4)
        yield UInt32(self, "attributes")
        yield UInt16(self, "header_len")
        yield UInt16(self, "checksum")
        yield UInt16(self, "ext_header_offset")
        yield UInt8(self, "reserved")
        yield UInt8(self, "revision")
        while True:
            bm = BlockMap(self, "block_map[]")
            yield bm
            if bm['num_blocks'].value == 0 and bm['len'].value == 0:
                break
        # TODO must handle extended header

        # Content
        while not self.eof:
            padding = paddingSize(self.current_size // 8, 8)
            if padding:
                yield PaddingBytes(self, "padding[]", padding)
            yield File(self, "file[]")
Exemplo n.º 2
0
    def createFields(self):
        yield UInt16(self, "size", "Node size (in bytes)")
        yield UInt16(self, "data_size")
        yield Enum(UInt16(self, "type"), self.TYPE_NAME)
        yield CString(self, "name", charset="UTF-16-LE")

        size = paddingSize(self.current_size // 8, 4)
        if size:
            yield NullBytes(self, "padding[]", size)
        size = self["data_size"].value
        if size:
            if self["type"].value == self.TYPE_STRING:
                if self.is_32bit:
                    size *= 2
                yield String(self, "value", size, charset="UTF-16-LE", truncate="\0")
            elif self["name"].value == "VS_VERSION_INFO":
                yield VersionInfoBinary(self, "value", size=size * 8)
                if self["value/file_flags_mask"].value == 0:
                    self.is_32bit = False
            else:
                yield RawBytes(self, "value", size)
        while 12 <= (self.size - self.current_size) // 8:
            yield VersionInfoNode(self, "node[]", self.is_32bit)
        size = (self.size - self.current_size) // 8
        if size:
            yield NullBytes(self, "padding[]", size)
Exemplo n.º 3
0
 def createFields(self):
     yield textHandler(UInt32(self, "crc32"), hexadecimal)
     yield UInt16(self, "size")
     yield UInt16(
         self, "uncompressed_size",
         "If this is 0, this block is continued in a subsequent cabinet")
     if self["/flags/has_reserved"].value and self[
             "/reserved_data_size"].value:
         yield RawBytes(self, "reserved_data",
                        self["/reserved_data_size"].value,
                        "Per-datablock reserved area")
     compr_method = self.parent.folder["compr_method"].value
     if compr_method == 0:  # Uncompressed
         yield RawBytes(self, "data", self["size"].value, "Folder Data")
         self.parent.uncompressed_data += self["data"].value
     elif compr_method == 1:  # MSZIP
         yield String(self, "mszip_signature", 2, "MSZIP Signature (CK)")
         yield DeflateBlock(self, "deflate_block",
                            self.parent.uncompressed_data)
         padding = paddingSize(self.current_size, 8)
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         self.parent.uncompressed_data = self["deflate_block"].uncomp_data
     elif compr_method == 2:  # Quantum
         yield RawBytes(self, "compr_data", self["size"].value,
                        "Compressed Folder Data")
     elif compr_method == 3:  # LZX
         group = getattr(self.parent.folder, "lzx_group", None)
         field = CustomFragment(self, "data", self["size"].value * 8,
                                LZXStream, "LZX data fragment", group)
         if group is None:
             field.group.args["compr_level"] = self.parent.folder[
                 "compr_level"].value
         self.parent.folder.lzx_group = field.group
         yield field
Exemplo n.º 4
0
 def createFields(self):
     dictionary = {}
     self.nbits = self.startbits
     CLEAR_CODE = 2**self.nbits
     END_CODE = CLEAR_CODE + 1
     compress_code = CLEAR_CODE + 2
     obuf = []
     output = []
     while True:
         if compress_code >= 2**self.nbits:
             self.nbits += 1
         code = Bits(self, "code[]", self.nbits)
         if code.value == CLEAR_CODE:
             if compress_code == 2**(self.nbits - 1):
                 # this fixes a bizarre edge case where the reset code could
                 # appear just after the bits incremented. Apparently, the
                 # correct behaviour is to express the reset code with the
                 # old number of bits, not the new...
                 code = Bits(self, "code[]", self.nbits - 1)
             self.nbits = self.startbits + 1
             dictionary = {}
             compress_code = CLEAR_CODE + 2
             obuf = []
             code._description = "Reset Code (LZW code %i)" % code.value
             yield code
             continue
         elif code.value == END_CODE:
             code._description = "End of Information Code (LZW code %i)" % code.value
             yield code
             break
         if code.value < CLEAR_CODE:  # literal
             if obuf:
                 chain = obuf + [code.value]
                 dictionary[compress_code] = chain
                 compress_code += 1
             obuf = [code.value]
             output.append(code.value)
             code._description = "Literal Code %i" % code.value
         elif code.value >= CLEAR_CODE + 2:
             if code.value in dictionary:
                 chain = dictionary[code.value]
                 code._description = "Compression Code %i (found in dictionary as %s)" % (
                     code.value, rle_repr(chain))
             else:
                 chain = obuf + [obuf[0]]
                 code._description = "Compression Code %i (not found in dictionary; guessed to be %s)" % (
                     code.value, rle_repr(chain))
             dictionary[compress_code] = obuf + [chain[0]]
             compress_code += 1
             obuf = chain
             output += chain
         code._description += "; Current Decoded Length %i" % len(output)
         yield code
     padding = paddingSize(self.current_size, 8)
     if padding:
         yield NullBits(self, "padding[]", padding)
Exemplo n.º 5
0
 def createFields(self):
     yield Bits(self, "nbits", 5)
     nbits = self["nbits"].value
     if not nbits:
         raise ParserError("SWF parser: Invalid RECT field size (0)")
     yield Bits(self, "xmin", nbits, "X minimum in twips")
     yield Bits(self, "xmax", nbits, "X maximum in twips")
     yield Bits(self, "ymin", nbits, "Y minimum in twips")
     yield Bits(self, "ymax", nbits, "Y maximum in twips")
     size = paddingSize(self.current_size, 8)
     if size:
         yield NullBits(self, "padding", size)
Exemplo n.º 6
0
 def createFields(self):
     uncomp_data = ""
     blk = DeflateBlock(self, "compressed_block[]", uncomp_data)
     yield blk
     uncomp_data = blk.uncomp_data
     while not blk["final"].value:
         blk = DeflateBlock(self, "compressed_block[]", uncomp_data)
         yield blk
         uncomp_data = blk.uncomp_data
     padding = paddingSize(self.current_size + self.absolute_address,
                           8)  # align on byte boundary
     if padding:
         yield PaddingBits(self, "padding[]", padding)
     self.uncompressed_data = uncomp_data
Exemplo n.º 7
0
 def createFields(self):
     self.uncompressed_data = ""
     self.r0 = 1
     self.r1 = 1
     self.r2 = 1
     yield Bit(self, "filesize_indicator")
     if self["filesize_indicator"].value:
         yield UInt32(self, "filesize")
     while self.current_size < self.size:
         block = LZXBlock(self, "block[]")
         yield block
         if self.size - self.current_size < 16:
             padding = paddingSize(self.address + self.current_size, 16)
             if padding:
                 yield PaddingBits(self, "padding[]", padding)
             break
Exemplo n.º 8
0
    def createFields(self):
        yield UInt16(self, "size", "Node size (in bytes)")
        yield UInt16(self, "data_size")
        yield CString(self, "name", charset="ISO-8859-1")

        size = paddingSize(self.current_size // 8, 4)
        if size:
            yield NullBytes(self, "padding[]", size)
        size = self["data_size"].value
        if size:
            if self["name"].value == "VS_VERSION_INFO":
                yield VersionInfoBinary(self, "value", size=size * 8)
            else:
                yield String(self, "value", size, charset="ISO-8859-1")
        while 12 <= (self.size - self.current_size) // 8:
            yield NE_VersionInfoNode(self, "node[]")
        size = (self.size - self.current_size) // 8
        if size:
            yield NullBytes(self, "padding[]", size)
Exemplo n.º 9
0
 def createFields(self):
     end = False
     while not end:
         marker = self.stream.readBits(
             self.absolute_address + self.current_size, 48, self.endian)
         if marker == self.START_BLOCK:
             yield Bzip2Block(self, "block[]")
         elif marker == self.END_STREAM:
             yield textHandler(
                 Bits(self, "stream_end", 48, "End-of-stream marker"),
                 hexadecimal)
             yield textHandler(
                 UInt32(self, "crc32", "CRC32 for entire stream"),
                 hexadecimal)
             padding = paddingSize(self.current_size, 8)
             if padding:
                 yield PaddingBits(self, "padding[]", padding)
             end = True
         else:
             raise ParserError("Invalid marker 0x%02X!" % marker)
Exemplo n.º 10
0
 def createFields(self):
     yield UInt32(self, "nblocks")
     yield UInt32(self, "unknown", description="Always 0")
     for i in xrange(self['nblocks'].value):
         yield BlockAddress(self, "block[]")
     padding = paddingSize(self['nblocks'].value, 256)
     if padding:
         yield NullBytes(
             self,
             "padding",
             padding * 4,
             description=
             "padding to make the number of blocks a multiple of 256")
     yield UInt32(self, "ndirs")
     for i in xrange(self['ndirs'].value):
         yield BudDirectory(self, "dir[]")
     for i in xrange(32):
         yield FreeList(self, "freelist[]")
     if self.current_size < self.size:
         yield PaddingBytes(self,
                            "slack", (self.size - self.current_size) // 8,
                            description="slack space")
Exemplo n.º 11
0
 def createFields(self):
     yield PropertiesFormat(self, "format")
     yield UInt32(self, "nb_prop")
     properties = []
     for index in xrange(self["nb_prop"].value):
         property = Property(self, "property[]")
         yield property
         properties.append(property)
     padding = paddingSize(self.current_size // 8, 4)
     if padding:
         yield NullBytes(self, "padding", padding)
     yield UInt32(self, "total_str_length")
     properties.sort(key=lambda entry: entry["name_offset"].value)
     offset0 = self.current_size // 8
     for property in properties:
         padding = self.seekByte(offset0 + property["name_offset"].value)
         if padding:
             yield padding
         yield CString(self, "name[]", "Name of %s" % property.name)
         if property["is_string"].value:
             yield CString(self, "value[]", "Value of %s" % property.name)
     padding = (self.size - self.current_size) // 8
     if padding:
         yield NullBytes(self, "end_padding", padding)
Exemplo n.º 12
0
    def createFields(self):
        yield UInt16(self, "length", "Length of Item ID Entry")
        if not self["length"].value:
            return

        yield Enum(UInt8(self, "type"), self.ITEM_TYPE)
        entrytype = self["type"].value
        if entrytype in (0x1F, 0x70):
            # GUID
            yield RawBytes(self, "dummy", 1, "should be 0x50")
            yield GUID(self, "guid")

        elif entrytype == 0x2E:
            # Shell extension
            yield RawBytes(self, "dummy", 1, "should be 0x50")
            if self["dummy"].value == '\0':
                yield UInt16(self, "length_data",
                             "Length of shell extension-specific data")
                if self["length_data"].value:
                    yield RawBytes(self, "data", self["length_data"].value,
                                   "Shell extension-specific data")
                yield GUID(self, "handler_guid")
            yield GUID(self, "guid")

        elif entrytype in (0x23, 0x25, 0x29, 0x2F):
            # Drive
            yield String(self, "drive", self["length"].value - 3, strip="\0")

        elif entrytype in (0x30, 0x31, 0x32, 0x61, 0xb1):
            yield RawBytes(self, "dummy", 1, "should be 0x00")
            yield UInt32(self, "size", "size of file; 0 for folders")
            yield DateTimeMSDOS32(self, "date_time",
                                  "File/folder date and time")
            yield MSDOSFileAttr16(self, "attribs", "File/folder attributes")
            yield CString(self, "name", "File/folder name")
            if self.root.hasUnicodeNames():
                # Align to 2-bytes
                n = paddingSize(self.current_size // 8, 2)
                if n:
                    yield PaddingBytes(self, "pad", n)

                yield UInt16(self, "length_w", "Length of wide struct member")
                yield RawBytes(self, "unknown[]", 6)
                yield DateTimeMSDOS32(self, "creation_date_time",
                                      "File/folder creation date and time")
                yield DateTimeMSDOS32(self, "access_date_time",
                                      "File/folder last access date and time")
                yield RawBytes(self, "unknown[]", 2)
                yield UInt16(
                    self, "length_next",
                    "Length of next two strings (if zero, ignore this field)")
                yield CString(self,
                              "unicode_name",
                              "File/folder name",
                              charset="UTF-16-LE")
                if self["length_next"].value:
                    yield CString(self, "localized_name", "Localized name")
                yield RawBytes(self, "unknown[]", 2)
            else:
                yield CString(self, "name_short", "File/folder short name")

        elif entrytype in (0x41, 0x42, 0x46):
            yield RawBytes(self, "unknown[]", 2)
            yield CString(self, "name")
            yield CString(self, "protocol")
            yield RawBytes(self, "unknown[]", 2)

        elif entrytype == 0x47:
            # Whole Network
            yield RawBytes(self, "unknown[]", 2)
            yield CString(self, "name")

        elif entrytype == 0xC3:
            # Network Share
            yield RawBytes(self, "unknown[]", 2)
            yield CString(self, "name")
            yield CString(self, "protocol")
            yield CString(self, "description")
            yield RawBytes(self, "unknown[]", 2)

        elif entrytype == 0x4C:
            # Web Folder
            yield RawBytes(self, "unknown[]", 5)
            yield TimestampWin64(self, "modification_time")
            yield UInt32(self, "unknown[]")
            yield UInt32(self, "unknown[]")
            yield UInt32(self, "unknown[]")
            yield LnkString(self, "name")
            yield RawBytes(self, "padding[]", 2)
            yield LnkString(self, "address")
            if self["address/length"].value:
                yield RawBytes(self, "padding[]", 2)

        else:
            yield RawBytes(self, "raw", self["length"].value - 3)
Exemplo n.º 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 xrange(8):
                 yield Bits(self, "aligned_len[]", 3)
             aligned_tree = build_tree(
                 [self['aligned_len[%d]' % i].value for i in xrange(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)
Exemplo n.º 14
0
    def createFields(self):
        yield String(self,
                     "name",
                     100,
                     "Name",
                     strip="\0",
                     charset="ISO-8859-1")
        yield String(self, "mode", 8, "Mode", strip=" \0", charset="ASCII")
        yield String(self, "uid", 8, "User ID", strip=" \0", charset="ASCII")
        yield String(self, "gid", 8, "Group ID", strip=" \0", charset="ASCII")
        yield String(self, "size", 12, "Size", strip=" \0", charset="ASCII")
        yield String(self,
                     "mtime",
                     12,
                     "Modification time",
                     strip=" \0",
                     charset="ASCII")
        yield String(self,
                     "check_sum",
                     8,
                     "Check sum",
                     strip=" \0",
                     charset="ASCII")
        yield Enum(UInt8(self, "type", "Type"), self.type_name)
        yield String(self,
                     "lname",
                     100,
                     "Link name",
                     strip=" \0",
                     charset="ISO-8859-1")
        yield String(self, "magic", 8, "Magic", strip=" \0", charset="ASCII")
        yield String(self,
                     "uname",
                     32,
                     "User name",
                     strip=" \0",
                     charset="ISO-8859-1")
        yield String(self,
                     "gname",
                     32,
                     "Group name",
                     strip=" \0",
                     charset="ISO-8859-1")
        yield String(self,
                     "devmajor",
                     8,
                     "Dev major",
                     strip=" \0",
                     charset="ASCII")
        yield String(self,
                     "devminor",
                     8,
                     "Dev minor",
                     strip=" \0",
                     charset="ASCII")
        yield String(self,
                     "prefix",
                     155,
                     "Prefix for filename",
                     strip="\0",
                     charset="ASCII")
        yield NullBytes(self, "padding", 12, "Padding (zero)")

        filesize = self.getOctal("size")
        if filesize:
            yield SubFile(self,
                          "content",
                          filesize,
                          filename=self["name"].value)

        size = paddingSize(self.current_size // 8, 512)
        if size:
            yield NullBytes(self, "padding_end", size, "Padding (512 align)")
Exemplo n.º 15
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)