Exemplo n.º 1
0
class BasicIFDEntry(FieldSet):
    TYPE_BYTE = 0
    TYPE_UNDEFINED = 7
    TYPE_RATIONAL = 5
    TYPE_SIGNED_RATIONAL = 10
    TYPE_INFO = {
        1: (UInt8, "BYTE (8 bits)"),
        2: (ASCIIString, "ASCII (8 bits)"),
        3: (UInt16, "SHORT (16 bits)"),
        4: (UInt32, "LONG (32 bits)"),
        5: (RationalUInt32, "RATIONAL (2x LONG, 64 bits)"),
        6: (Int8, "SBYTE (8 bits)"),
        7: (Bytes, "UNDEFINED (8 bits)"),
        8: (Int16, "SSHORT (16 bits)"),
        9: (Int32, "SLONG (32 bits)"),
        10: (RationalInt32, "SRATIONAL (2x SLONG, 64 bits)"),
        11: (Float32, "FLOAT (32 bits)"),
        12: (Float64, "DOUBLE (64 bits)"),
    }
    ENTRY_FORMAT = createDict(TYPE_INFO, 0)
    TYPE_NAME = createDict(TYPE_INFO, 1)
    TAG_INFO = {}

    def createFields(self):
        yield IFDTag(self, "tag", "Tag")
        yield Enum(UInt16(self, "type", "Type"), self.TYPE_NAME)
        self.value_cls = self.ENTRY_FORMAT.get(self['type'].value, Bytes)
        if issubclass(self.value_cls, Bytes):
            self.value_size = 8
        else:
            self.value_size = self.value_cls.static_size
        yield UInt32(self, "count", "Count")

        count = self['count'].value
        totalsize = self.value_size * count
        if count == 0:
            yield NullBytes(self, "padding", 4)
        elif totalsize <= 32:
            name = "value"
            if issubclass(self.value_cls, Bytes):
                yield self.value_cls(self, name, count)
            elif count == 1:
                yield self.value_cls(self, name)
            else:
                yield ValueArray(self, name, self.value_cls, count)
            if totalsize < 32:
                yield NullBits(self, "padding", 32 - totalsize)
        else:
            yield UInt32(self, "offset", "Value offset")

    def createValue(self):
        if "value" in self:
            return self['value'].value
        return None

    def createDescription(self):
        return "Entry: " + self["tag"].getTag()[1]
Exemplo n.º 2
0
class IndexOffset(FieldSet):
    TYPE_DESC = createDict(RESOURCE_TYPE, 1)

    def __init__(self, parent, name, res_type=None):
        FieldSet.__init__(self, parent, name)
        self.res_type = res_type

    def createFields(self):
        if self.res_type is None:
            # immediate subdirectory of the root
            yield Enum(UInt32(self, "type"), self.TYPE_DESC)
        else:
            # sub-subdirectory, "type" field is just an ID
            yield textHandler(UInt32(self, "type"), lambda field: "ID %d" % field.value)
        yield Bits(self, "offset", 31)
        yield Bit(self, "is_subdir")

    def getResType(self):
        return self["type"].value

    def createDescription(self):
        if self["is_subdir"].value:
            return "Sub-directory: %s at %s" % (self["type"].display, self["offset"].value)
        else:
            return "Index: %s at %s" % (self["type"].display, self["offset"].value)
Exemplo n.º 3
0
class Chunk(FieldSet):
    CHUNK_INFO = {
        0x0001: ("string_table", "String Table", StringChunk, None),
        0x0003: ("xml_file", "XML File", Top, None),
        0x0100: ("namespace_start[]", "Start Namespace", NamespaceTag,
                 NamespaceStartValue),
        0x0101:
        ("namespace_end[]", "End Namespace", NamespaceTag, NamespaceEndValue),
        0x0102: ("tag_start[]", "Start Tag", TagStart, TagStartValue),
        0x0103: ("tag_end[]", "End Tag", TagEnd, TagEndValue),
        0x0104: ("text[]", "Text", TextChunk, None),
        0x0180: ("resource_ids", "Resource IDs", ResourceIDs, None),
    }
    CHUNK_DESC = createDict(CHUNK_INFO, 1)

    def __init__(self, parent, name, description=None):
        FieldSet.__init__(self, parent, name, description)
        self._size = self['chunk_size'].value * 8
        type = self['type'].value
        self.parse_func = None
        if type in self.CHUNK_INFO:
            self._name, self._description, self.parse_func, value_func = self.CHUNK_INFO[
                type]
            if value_func:
                self.createValue = lambda: value_func(self)

    def createFields(self):
        yield Enum(UInt16(self, "type"), self.CHUNK_DESC)
        yield UInt16(self, "header_size")
        yield UInt32(self, "chunk_size")
        if self.parse_func:
            for field in self.parse_func(self):
                yield field
Exemplo n.º 4
0
class XMLAttribute(FieldSet):
    TYPE_INFO = {
        0: ('Null', IntTextHandler(lambda field: '')),
        1: ('Reference', IntTextHandler(lambda field: '@%08x' % field.value)),
        2: ('Attribute', IntTextHandler(lambda field: '?%08x' % field.value)),
        3: ('String', IntTextHandler(stringIndex)),
        4: ('Float', Float32),
        5: ('Dimension', XMLDimensionFloat),
        6: ('Fraction', XMLFractionFloat),
        16: ('Int_Dec', Int32),
        17: ('Int_Hex', IntTextHandler(hexadecimal)),
        18: ('Int_Boolean', IntTextHandler(booleanText)),
        28: ('Int_Color_Argb8',
             IntTextHandler(lambda field: '#%08x' % field.value)),
        29: ('Int_Color_Rgb8',
             IntTextHandler(lambda field: '#%08x' % field.value)),
        30: ('Int_Color_Argb4',
             IntTextHandler(lambda field: '#%08x' % field.value)),
        31: ('Int_Color_Rgb4',
             IntTextHandler(lambda field: '#%08x' % field.value)),
    }
    TYPE_NAME = createDict(TYPE_INFO, 0)
    TYPE_FUNC = createDict(TYPE_INFO, 1)
    static_size = 5 * 32

    def createFields(self):
        yield textHandler(Int32(self, "ns"), stringIndex)
        yield textHandler(Int32(self, "name"), stringIndex)
        yield textHandler(Int32(self, "value_string"), stringIndex)
        yield UInt16(self, "unk[]")
        yield UInt8(self, "unk[]")
        yield Enum(UInt8(self, "value_type"), self.TYPE_NAME)
        func = self.TYPE_FUNC.get(self['value_type'].value, None)
        if not func:
            func = UInt32
        yield func(self, "value_data")

    def createValue(self):
        return (self['name'].display, self['value_data'].value)

    def createDisplay(self):
        return '%s="%s"' % (self['name'].display, self['value_data'].display)
Exemplo n.º 5
0
class Layer2(Layer):
    PROTO_INFO = {
        0x0800: ("ipv4", IPv4, "IPv4"),
        0x0806: ("arp", ARP, "ARP"),
        0x86dd: ("ipv6", IPv6, "IPv6"),
    }
    PROTO_DESC = createDict(PROTO_INFO, 2)

    def parseNext(self, parent):
        try:
            name, parser, desc = self.PROTO_INFO[self["protocol"].value]
            return parser(parent, name)
        except KeyError:
            return None
Exemplo n.º 6
0
class IP(Layer):
    PROTOCOL_INFO = {
        1: ("icmp", ICMP, "ICMP"),
        6: ("tcp", TCP, "TCP"),
        17: ("udp", UDP, "UDP"),
        58: ("icmpv6", ICMPv6, "ICMPv6"),
        60: ("ipv6_opts", None, "IPv6 destination option"),
    }
    PROTOCOL_NAME = createDict(PROTOCOL_INFO, 2)

    def parseNext(self, parent):
        proto = self["protocol"].value
        if proto not in self.PROTOCOL_INFO:
            return None
        name, parser, desc = self.PROTOCOL_INFO[proto]
        if not parser:
            return None
        return parser(parent, name)
Exemplo n.º 7
0
class MetadataBlock(FieldSet):
    "Metadata block field: http://flac.sourceforge.net/format.html#metadata_block"

    BLOCK_TYPES = {
        0: ("stream_info", u"Stream info", StreamInfo),
        1: ("padding[]", u"Padding", None),
        2: ("application[]", u"Application", None),
        3: ("seek_table", u"Seek table", SeekTable),
        4: ("comment", u"Vorbis comment", VorbisComment),
        5: ("cue_sheet[]", u"Cue sheet", None),
        6: ("picture[]", u"Picture", None),
    }
    BLOCK_TYPE_DESC = createDict(BLOCK_TYPES, 1)

    def __init__(self, *args, **kw):
        FieldSet.__init__(self, *args, **kw)
        self._size = 32 + self["metadata_length"].value * 8
        try:
            key = self["block_type"].value
            self._name, self._description, self.handler = self.BLOCK_TYPES[key]
        except KeyError:
            self.handler = None

    def createFields(self):
        yield Bit(self, "last_metadata_block", "True if this is the last metadata block")
        yield Enum(Bits(self, "block_type", 7, "Metadata block header type"), self.BLOCK_TYPE_DESC)
        yield UInt24(self, "metadata_length", "Length of following metadata in bytes (doesn't include this header)")

        block_type = self["block_type"].value
        size = self["metadata_length"].value
        if not size:
            return
        try:
            handler = self.BLOCK_TYPES[block_type][2]
        except KeyError:
            handler = None
        if handler:
            yield handler(self, "content", size=size * 8)
        elif self["block_type"].value == 1:
            yield NullBytes(self, "padding", size)
        else:
            yield RawBytes(self, "rawdata", size)
Exemplo n.º 8
0
class TcpdumpFile(Parser):
    PARSER_TAGS = {
        "id": "tcpdump",
        "category": "misc",
        "min_size": 24 * 8,
        "description": "Tcpdump file (network)",
        "magic": (("\xd4\xc3\xb2\xa1", 0), ),
    }
    endian = LITTLE_ENDIAN

    LINK_TYPE = {
        1: ("ethernet", Ethernet),
        113: ("unicast", Unicast),
    }
    LINK_TYPE_DESC = createDict(LINK_TYPE, 0)

    def validate(self):
        if self["id"].value != "\xd4\xc3\xb2\xa1":
            return "Wrong file signature"
        if self["link_type"].value not in self.LINK_TYPE:
            return "Unknown link type"
        return True

    def createFields(self):
        yield Bytes(self, "id", 4, "Tcpdump identifier")
        yield UInt16(self, "maj_ver", "Major version")
        yield UInt16(self, "min_ver", "Minor version")
        yield Int32(self, "this_zone", "GMT to local time zone correction")
        yield Int32(self, "sigfigs", "accuracy of timestamps")
        yield UInt32(self, "snap_len", "max length saved portion of each pkt")
        yield Enum(UInt32(self, "link_type", "data link type"),
                   self.LINK_TYPE_DESC)
        link = self["link_type"].value
        if link not in self.LINK_TYPE:
            raise ParserError("Unknown link type: %s" % link)
        name, parser = self.LINK_TYPE[link]
        while self.current_size < self.size:
            yield Packet(self, "packet[]", parser, name)
Exemplo n.º 9
0
from hachoir_py2.parser import Parser
from hachoir_py2.field import (FieldSet, UInt8, UInt24, UInt32, NullBits,
                               NullBytes, Bit, Bits, String, RawBytes, Enum)
from hachoir_py2.core.endian import BIG_ENDIAN
from hachoir_py2.parser.audio.mpeg_audio import Frame
from hachoir_py2.parser.video.amf import AMFObject
from hachoir_py2.core.tools import createDict

SAMPLING_RATE = {
    0: (5512, "5.5 kHz"),
    1: (11025, "11 kHz"),
    2: (22050, "22.1 kHz"),
    3: (44100, "44.1 kHz"),
}
SAMPLING_RATE_VALUE = createDict(SAMPLING_RATE, 0)
SAMPLING_RATE_TEXT = createDict(SAMPLING_RATE, 1)

AUDIO_CODEC_MP3 = 2
AUDIO_CODEC_NAME = {
    0: u"Uncompressed",
    1: u"ADPCM",
    2: u"MP3",
    5: u"Nellymoser 8kHz mono",
    6: u"Nellymoser",
}

VIDEO_CODEC_NAME = {
    2: u"Sorensen H.263",
    3: u"Screen video",
    4: u"On2 VP6",
Exemplo n.º 10
0
class AuFile(Parser):
    PARSER_TAGS = {
        "id": "sun_next_snd",
        "category": "audio",
        "file_ext": ("au", "snd"),
        "mime": (u"audio/basic", ),
        "min_size": 24 * 8,
        "magic": ((".snd", 0), ),
        "description": "Sun/NeXT audio"
    }
    endian = BIG_ENDIAN

    CODEC_INFO = {
        1: (8, u"8-bit ISDN u-law"),
        2: (8, u"8-bit linear PCM"),
        3: (16, u"16-bit linear PCM"),
        4: (24, u"24-bit linear PCM"),
        5: (32, u"32-bit linear PCM"),
        6: (32, u"32-bit IEEE floating point"),
        7: (64, u"64-bit IEEE floating point"),
        8: (None, u"Fragmented sample data"),
        9: (None, u"DSP program"),
        10: (8, u"8-bit fixed point"),
        11: (16, u"16-bit fixed point"),
        12: (24, u"24-bit fixed point"),
        13: (32, u"32-bit fixed point"),
        18: (16, u"16-bit linear with emphasis"),
        19: (16, u"16-bit linear compressed"),
        20: (16, u"16-bit linear with emphasis and compression"),
        21: (None, u"Music kit DSP commands"),
        23: (None, u"4-bit ISDN u-law compressed (CCITT G.721 ADPCM)"),
        24: (None, u"ITU-T G.722 ADPCM"),
        25: (None, u"ITU-T G.723 3-bit ADPCM"),
        26: (None, u"ITU-T G.723 5-bit ADPCM"),
        27: (8, u"8-bit ISDN A-law"),
    }

    # Create bit rate and codec name dictionnaries
    BITS_PER_SAMPLE = createDict(CODEC_INFO, 0)
    CODEC_NAME = createDict(CODEC_INFO, 1)

    VALID_NB_CHANNEL = set((1, 2))  # FIXME: 4, 5, 7, 8 channels are supported?

    def validate(self):
        if self.stream.readBytes(0, 4) != ".snd":
            return "Wrong file signature"
        if self["channels"].value not in self.VALID_NB_CHANNEL:
            return "Invalid number of channel"
        return True

    def getBitsPerSample(self):
        """
        Get bit rate (number of bit per sample per channel),
        may returns None if you unable to compute it.
        """
        return self.BITS_PER_SAMPLE.get(self["codec"].value)

    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 createContentSize(self):
        return (self["data_ofs"].value + self["data_size"].value) * 8
Exemplo n.º 11
0
    0x0538: ("POLYPOLYGON", u"Draw multiple polygons", None),
    0x0548: ("EXTFLOODFILL", u"Extend flood fill", None),
    0x061C: ("ROUNDRECT", u"Draw a rounded rectangle", None),
    0x061D: ("PATBLT", u"Pattern blitting", None),
    0x0626: ("ESCAPE", u"Escape", None),
    0x06FF: ("CREATEREGION", u"Create region", None),
    0x0817: ("ARC", u"Draw an arc", None),
    0x081A: ("PIE", u"Draw a pie", None),
    0x0830: ("CHORD", u"Draw a chord", None),
    0x0940: ("DIBBITBLT", u"DIB bit blitting", None),
    0x0a32: ("EXTTEXTOUT", u"Draw text (extra)", None),
    0x0b41: ("DIBSTRETCHBLT", u"DIB stretch blitting", None),
    0x0d33: ("SETDIBTODEV", u"Set DIB to device", None),
    0x0f43: ("STRETCHDIB", u"Stretch DIB", None),
}
META_NAME = createDict(META, 0)
META_DESC = createDict(META, 1)

# ----------------------------------------------------------------------------
# EMF constants

# EMF mapping modes
EMF_MAPPING_MODE = {
    1: "TEXT",
    2: "LOMETRIC",
    3: "HIMETRIC",
    4: "LOENGLISH",
    5: "HIENGLISH",
    6: "TWIPS",
    7: "ISOTROPIC",
    8: "ANISOTROPIC",
Exemplo n.º 12
0
class Command(FieldSet):
    COMMAND = {}
    for channel in xrange(16):
        COMMAND[0x80 + channel] = ("Note off (channel %u)" % channel,
                                   parseNote)
        COMMAND[0x90 + channel] = ("Note on (channel %u)" % channel, parseNote)
        COMMAND[0xA0 + channel] = ("Key after-touch (channel %u)" % channel,
                                   parseNote)
        COMMAND[0xB0 + channel] = ("Control change (channel %u)" % channel,
                                   parseControl)
        COMMAND[0xC0 + channel] = ("Program (patch) change (channel %u)" %
                                   channel, parsePatch)
        COMMAND[0xD0 + channel] = ("Channel after-touch (channel %u)" %
                                   channel, parseChannel)
        COMMAND[0xE0 + channel] = ("Pitch wheel change (channel %u)" % channel,
                                   parsePitch)
    COMMAND_DESC = createDict(COMMAND, 0)
    COMMAND_PARSER = createDict(COMMAND, 1)

    META_COMMAND_TEXT = 1
    META_COMMAND_NAME = 3
    META_COMMAND = {
        0x00: ("Sets the track's sequence number", None),
        0x01: ("Text event", parseText),
        0x02: ("Copyright info", parseText),
        0x03: ("Sequence or Track name", parseText),
        0x04: ("Track instrument name", parseText),
        0x05: ("Lyric", parseText),
        0x06: ("Marker", parseText),
        0x07: ("Cue point", parseText),
        0x20: ("MIDI Channel Prefix", parseChannel),
        0x2F: ("End of the track", None),
        0x51: ("Set tempo", parseTempo),
        0x54: ("SMPTE offset", parseSMPTEOffset),
        0x58: ("Time Signature", parseTimeSignature),
        0x59: ("Key signature", None),
        0x7F: ("Sequencer specific information", None),
    }
    META_COMMAND_DESC = createDict(META_COMMAND, 0)
    META_COMMAND_PARSER = createDict(META_COMMAND, 1)

    def __init__(self, *args, **kwargs):
        if 'prev_command' in kwargs:
            self.prev_command = kwargs['prev_command']
            del kwargs['prev_command']
        else:
            self.prev_command = None
        self.command = None
        FieldSet.__init__(self, *args, **kwargs)

    def createFields(self):
        yield Integer(self, "time", "Delta time in ticks")
        next = self.stream.readBits(self.absolute_address + self.current_size,
                                    8, self.root.endian)
        if next & 0x80 == 0:
            # "Running Status" command
            if self.prev_command is None:
                raise ParserError(
                    "Running Status command not preceded by another command.")
            self.command = self.prev_command.command
        else:
            yield Enum(textHandler(UInt8(self, "command"), hexadecimal),
                       self.COMMAND_DESC)
            self.command = self["command"].value
        if self.command == 0xFF:
            yield Enum(textHandler(UInt8(self, "meta_command"), hexadecimal),
                       self.META_COMMAND_DESC)
            yield UInt8(self, "data_len")
            size = self["data_len"].value
            if size:
                command = self["meta_command"].value
                if command in self.META_COMMAND_PARSER:
                    parser = self.META_COMMAND_PARSER[command]
                else:
                    parser = None
                if parser:
                    for field in parser(self, size):
                        yield field
                else:
                    yield RawBytes(self, "data", size)
        else:
            if self.command not in self.COMMAND_PARSER:
                raise ParserError("Unknown command: %s" %
                                  self["command"].display)
            parser = self.COMMAND_PARSER[self.command]
            for field in parser(self):
                yield field

    def createDescription(self):
        if "meta_command" in self:
            return self["meta_command"].display
        else:
            return self.COMMAND_DESC[self.command]
Exemplo n.º 13
0
class Object(FieldSet):
    TYPE_INFO = {
        0: ("end[]", None, "End (reserved for BER, None)",
            None),  # TODO: Write parser
        1: ("boolean[]", readBoolean, "Boolean", None),
        2: ("integer[]", readInteger, "Integer", None),
        3: ("bit_str[]", readBitString, "Bit string", None),
        4: ("octet_str[]", readOctetString, "Octet string", None),
        5: ("null[]", None, "NULL (empty, None)", None),
        6: ("obj_id[]", readObjectID, "Object identifier", formatObjectID),
        7:
        ("obj_desc[]", None, "Object descriptor", None),  # TODO: Write parser
        8: ("external[]", None, "External, instance of",
            None),  # TODO: Write parser # External?
        9:
        ("real[]", readASCIIString, "Real number", None),  # TODO: Write parser
        10: ("enum[]", readInteger, "Enumerated", None),
        11: ("embedded[]", None, "Embedded PDV", None),  # TODO: Write parser
        12: ("utf8_str[]", readUTF8String, "Printable string", None),
        13: ("rel_obj_id[]", None, "Relative object identifier",
             None),  # TODO: Write parser
        14: ("time[]", None, "Time", None),  # TODO: Write parser
        # 15: invalid??? sequence of???
        16: ("seq[]", readSequence, "Sequence", None),
        17: ("set[]", readSet, "Set", None),
        18: ("num_str[]", readASCIIString, "Numeric string", None),
        19: ("print_str[]", readASCIIString, "Printable string", formatValue),
        20:
        ("teletex_str[]", readASCIIString, "Teletex (T61, None) string", None),
        21: ("videotex_str[]", readASCIIString, "Videotex string", None),
        22: ("ia5_str[]", readASCIIString, "IA5 string", formatValue),
        23: ("utc_time[]", readASCIIString, "UTC time", formatUTCTime),
        24: ("general_time[]", readASCIIString, "Generalized time", None),
        25: ("graphic_str[]", readASCIIString, "Graphic string", None),
        26: ("visible_str[]", readASCIIString, "Visible (ISO64, None) string",
             None),
        27: ("general_str[]", readASCIIString, "General string", None),
        28: ("universal_str[]", readASCIIString, "Universal string", None),
        29:
        ("unrestricted_str[]", readASCIIString, "Unrestricted string", None),
        30: ("bmp_str[]", readBMPString, "BMP string", None),
        # 31: multiple octet tag number, TODO: not supported

        # Extended tag values:
        #   31: Date
        #   32: Time of day
        #   33: Date-time
        #   34: Duration
    }
    TYPE_DESC = createDict(TYPE_INFO, 2)

    CLASS_DESC = {0: "universal", 1: "application", 2: "context", 3: "private"}
    FORM_DESC = {False: "primitive", True: "constructed"}

    def __init__(self, *args, **kw):
        FieldSet.__init__(self, *args, **kw)
        key = self["type"].value & 31
        if self['class'].value == 0:
            # universal object
            if key in self.TYPE_INFO:
                self._name, self._handler, self._description, create_desc = self.TYPE_INFO[
                    key]
                if create_desc:
                    self.createDescription = lambda: "%s: %s" % (
                        self.TYPE_INFO[key][2], create_desc(self))
                    self._description = None
            elif key == 31:
                raise ParserError(
                    "ASN.1 Object: tag bigger than 30 are not supported")
            else:
                self._handler = None
        elif self['form'].value:
            # constructed: treat as sequence
            self._name = 'seq[]'
            self._handler = readSequence
            self._description = 'constructed object type %i' % key
        else:
            # primitive, context/private
            self._name = 'raw[]'
            self._handler = readASCIIString
            self._description = '%s object type %i' % (self['class'].display,
                                                       key)
        field = self["size"]
        self._size = field.address + field.size + field.value * 8

    def createFields(self):
        yield Enum(Bits(self, "class", 2), self.CLASS_DESC)
        yield Enum(Bit(self, "form"), self.FORM_DESC)
        if self['class'].value == 0:
            yield Enum(Bits(self, "type", 5), self.TYPE_DESC)
        else:
            yield Bits(self, "type", 5)
        yield ASNInteger(self, "size", "Size in bytes")
        size = self["size"].value
        if size:
            if self._handler:
                for field in self._handler(self, size):
                    yield field
            else:
                yield RawBytes(self, "raw", size)
Exemplo n.º 14
0
class Photoshop8BIM(FieldSet):
    TAG_INFO = {
        0x03ed: ("res_info", ResolutionInfo, "Resolution information"),
        0x03f3: ("print_flag", PrintFlags, "Print flags: labels, crop marks, colour bars, etc."),
        0x03f5: ("col_half_info", None, "Colour half-toning information"),
        0x03f8: ("color_trans_func", None, "Colour transfer function"),
        0x0404: ("iptc", IPTC, "IPTC/NAA"),
        0x0406: ("jpeg_qual", None, "JPEG quality"),
        0x0408: ("grid_guide", GridGuides, "Grid guides informations"),
        0x0409: ("thumb_res", Thumbnail, "Thumbnail resource (PS 4.0)"),
        0x0410: ("watermark", UInt8, "Watermark"),
        0x040a: ("copyright_flag", UInt8, "Copyright flag"),
        0x040b: ("url", None, "URL"),
        0x040c: ("thumb_res2", Thumbnail, "Thumbnail resource (PS 5.0)"),
        0x040d: ("glob_angle", UInt32, "Global lighting angle for effects"),
        0x0411: ("icc_tagged", None, "ICC untagged (1 means intentionally untagged)"),
        0x0414: ("base_layer_id", UInt32, "Base value for new layers ID's"),
        0x0416: ("indexed_colors", UInt16, "Number of colors in table that are actually defined"),
        0x0417: ("transparency_index", UInt16, "Index of transparent color"),
        0x0419: ("glob_altitude", UInt32, "Global altitude"),
        0x041a: ("slices", None, "Slices"),
        0x041e: ("url_list", None, "Unicode URLs"),
        0x0421: ("version", Version, "Version information"),
        0x0425: ("caption_digest", None, "16-byte MD5 caption digest"),
        0x0426: ("printscale", PrintScale, "Printer scaling"),
        0x2710: ("print_flag2", PrintFlags2, "Print flags (2)"),
    }
    TAG_NAME = createDict(TAG_INFO, 0)
    CONTENT_HANDLER = createDict(TAG_INFO, 1)
    TAG_DESC = createDict(TAG_INFO, 2)

    def __init__(self, *args, **kw):
        FieldSet.__init__(self, *args, **kw)
        try:
            self._name, self.handler, self._description = self.TAG_INFO[self["tag"].value]
        except KeyError:
            self.handler = None
        size = self["size"]
        self._size = size.address + size.size + alignValue(size.value, 2) * 8

    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) != "\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)