Exemple #1
0
    def __init__(self, parent, name, tree, description=""):
        Field.__init__(self, parent, name, 0, description)

        endian = self.parent.endian
        stream = self.parent.stream
        addr = self.absolute_address

        value = 0
        met_ff = False
        while (self.size, value) not in tree:
            if addr % 8 == 0:
                last_byte = stream.readBytes(addr - 8, 1)
                if last_byte == b'\xFF':
                    next_byte = stream.readBytes(addr, 1)
                    if next_byte != b'\x00':
                        raise FieldError("Unexpected byte sequence %r!" %
                                         (last_byte + next_byte))
                    addr += 8  # hack hack hack
                    met_ff = True
                    self._description = "[skipped 8 bits after 0xFF] "
            bit = stream.readBits(addr, 1, endian)
            value <<= 1
            value += bit
            self._size += 1
            addr += 1
        self.createValue = lambda: value
        self.realvalue = tree[(self.size, value)]
        if met_ff:
            self._size += 8
Exemple #2
0
def createRawField(parent, size, name="raw[]", description=None):
    if size <= 0:
        raise FieldError("Unable to create raw field of %s bits" % size)
    if (size % 8) == 0:
        return RawBytes(parent, name, size // 8, description)
    else:
        return RawBits(parent, name, size, description)
Exemple #3
0
def createNullField(parent, nbits, name="padding[]", description=None):
    if nbits <= 0:
        raise FieldError("Unable to create null padding of %s bits" % nbits)
    if (nbits % 8) == 0:
        return NullBytes(parent, name, nbits // 8, description)
    else:
        return NullBits(parent, name, nbits, description)
Exemple #4
0
 def __init__(self, parent, name, length, description="Raw data"):
     assert issubclass(parent.__class__, Field)
     if not (0 < length <= MAX_LENGTH):
         raise FieldError("Invalid RawBytes length (%s)!" % length)
     Field.__init__(self, parent, name, length * 8, description)
     self._display = None
Exemple #5
0
 def __init__(self, parent, name, signed, size, description=None):
     if not (8 <= size <= 16384):
         raise FieldError(
             "Invalid integer size (%s): have to be in 8..16384" % size)
     Bits.__init__(self, parent, name, size, description)
     self.signed = signed
Exemple #6
0
 def createFields(self):
     if self.frame["../type"].value in [0xC0, 0xC1]:
         # yay, huffman coding!
         if not hasattr(self, "huffman_tables"):
             self.huffman_tables = {}
             for huffman in self.parent.array("huffman"):
                 for table in huffman["content"].array("huffman_table"):
                     for _dummy_ in table:
                         # exhaust table, so the huffman tree is built
                         pass
                     self.huffman_tables[table["table_class"].value,
                                         table["index"].value] = table.tree
         components = []  # sos_comp, samples
         max_vert = 0
         max_horiz = 0
         for component in self.scan.array("component"):
             for sof_comp in self.frame.array("component"):
                 if sof_comp["component_id"].value == component[
                         "component_id"].value:
                     vert = sof_comp["vert_sample"].value
                     horiz = sof_comp["horiz_sample"].value
                     components.append((component, vert * horiz))
                     max_vert = max(max_vert, vert)
                     max_horiz = max(max_horiz, horiz)
         mcu_height = alignValue(self.frame["height"].value,
                                 8 * max_vert) // (8 * max_vert)
         mcu_width = alignValue(self.frame["width"].value,
                                8 * max_horiz) // (8 * max_horiz)
         if self.restart_interval and self.restart_offset > 0:
             mcu_number = self.restart_interval * self.restart_offset
         else:
             mcu_number = 0
         initial_mcu = mcu_number
         while True:
             if (self.restart_interval and mcu_number != initial_mcu and mcu_number % self.restart_interval == 0) or\
                mcu_number == mcu_height * mcu_width:
                 padding = paddingSize(self.current_size, 8)
                 if padding:
                     yield PaddingBits(self, "padding[]", padding)  # all 1s
                 last_byte = self.stream.readBytes(
                     self.absolute_address + self.current_size - 8, 1)
                 if last_byte == b'\xFF':
                     next_byte = self.stream.readBytes(
                         self.absolute_address + self.current_size, 1)
                     if next_byte != b'\x00':
                         raise FieldError("Unexpected byte sequence %r!" %
                                          (last_byte + next_byte))
                     yield NullBytes(self, "stuffed_byte[]", 1)
                 break
             for sos_comp, num_units in components:
                 for interleave_count in range(num_units):
                     yield JpegHuffmanImageUnit(
                         self, "block[%i]component[%i][]" %
                         (mcu_number, sos_comp["component_id"].value),
                         self.huffman_tables[
                             0, sos_comp["dc_coding_table"].value],
                         self.huffman_tables[
                             1, sos_comp["ac_coding_table"].value])
             mcu_number += 1
     else:
         self.warning(
             "Sorry, only supporting Baseline & Extended Sequential JPEG images so far!"
         )
         return
Exemple #7
0
    def __init__(self,
                 parent,
                 name,
                 format,
                 description=None,
                 strip=None,
                 charset=None,
                 nbytes=None,
                 truncate=None):
        Bytes.__init__(self, parent, name, 1, description)

        # Is format valid?
        assert format in self.VALID_FORMATS

        # Store options
        self._format = format
        self._strip = strip
        self._truncate = truncate

        # Check charset and compute character size in bytes
        # (or None when it's not possible to guess character size)
        if not charset or charset in self.CHARSET_8BIT:
            self._character_size = 1  # one byte per character
        elif charset in self.UTF_CHARSET:
            self._character_size = None
        else:
            raise FieldError("Invalid charset for %s: \"%s\"" %
                             (self.path, charset))
        self._charset = charset

        # It is a fixed string?
        if nbytes is not None:
            assert self._format == "fixed"
            # Arbitrary limits, just to catch some bugs...
            if not (1 <= nbytes <= 0xffff):
                raise FieldError("Invalid string size for %s: %s" %
                                 (self.path, nbytes))
            self._content_size = nbytes  # content length in bytes
            self._size = nbytes * 8
            self._content_offset = 0
        else:
            # Format with a suffix: Find the end of the string
            if self._format in self.SUFFIX_FORMAT:
                self._content_offset = 0

                # Choose the suffix
                suffix = self.suffix_str

                # Find the suffix
                length = self._parent.stream.searchBytesLength(
                    suffix, False, self.absolute_address)
                if length is None:
                    raise FieldError(
                        "Unable to find end of string %s (format %s)!" %
                        (self.path, self._format))
                if 1 < len(suffix):
                    # Fix length for little endian bug with UTF-xx charset:
                    #   u"abc" -> "a\0b\0c\0\0\0" (UTF-16-LE)
                    #   search returns length=5, whereas real lenght is 6
                    length = alignValue(length, len(suffix))

                # Compute sizes
                self._content_size = length  # in bytes
                self._size = (length + len(suffix)) * 8

            # Format with a prefix: Read prefixed length in bytes
            else:
                assert self._format in self.PASCAL_FORMATS

                # Get the prefix size
                prefix_size = self.PASCAL_FORMATS[self._format]
                self._content_offset = prefix_size

                # Read the prefix and compute sizes
                value = self._parent.stream.readBits(self.absolute_address,
                                                     prefix_size * 8,
                                                     self._parent.endian)
                self._content_size = value  # in bytes
                self._size = (prefix_size + value) * 8

        # For UTF-16 and UTF-32, choose the right charset using BOM
        if self._charset in self.UTF_CHARSET:
            # Charset requires a BOM?
            bomsize, endian = self.UTF_CHARSET[self._charset]
            if endian == "BOM":
                # Read the BOM value
                nbytes = bomsize // 8
                bom = self._parent.stream.readBytes(self.absolute_address,
                                                    nbytes)

                # Choose right charset using the BOM
                bom_endian = self.UTF_BOM[bomsize]
                if bom not in bom_endian:
                    raise FieldError("String %s has invalid BOM (%s)!" %
                                     (self.path, repr(bom)))
                self._charset = bom_endian[bom]
                self._content_size -= nbytes
                self._content_offset += nbytes

        # Compute length in character if possible
        if self._character_size:
            self._length = self._content_size // self._character_size
        else:
            self._length = None