Example #1
0
    def test_header_type_is_invalid(self):
        with self.assertRaises(Exception) as cm:
            invector = ResTable_package_header(
                ResChunk_header(ResourceType.RES_NULL_TYPE))

        expected = 'header must describe resource of type '\
                'ResourceType.RES_TABLE_PACKAGE_TYPE'
        _, actual = cm.exception.args

        self.assertEqual(expected, actual)
Example #2
0
    def test_from_bytes(self):
        invector = b'\0\2\x20\1\xe4\3\1\0\x7f\0\0\0t\0e\0s\0t\0\0\0' + \
        bytes(246) + b'\x20\1\0\0\x0a\0\0\0\xb4\1\0\0\x19\3\0\0' + \
        b'\0\0\0\0' + b'\x13\x37'
        expected = ResTable_package_header(header=ResChunk_header(
            chunkType=ResourceType.RES_TABLE_PACKAGE_TYPE, headerSize=0x120,
            size=0x103e4), id=0x7f, name=b't\0e\0s\0t\0\0\0', typeStrings=0x120,
            lastPublicType=10, keyStrings=0x1b4, lastPublicKey=0x319), \
        b'\x13\x37'
        actual = ResTable_package_header.from_bytes(invector)

        self.assertEqual(expected, actual)
Example #3
0
    def from_bytes(b):
        header, b = ResChunk_header.from_bytes(b)
        id, b = uint32.from_bytes(b, little=True)
        name, b = b[:256], b[256:]
        typeStrings, b = uint32.from_bytes(b, little=True)
        lastPublicType, b = uint32.from_bytes(b, little=True)
        keyStrings, b = uint32.from_bytes(b, little=True)
        lastPublicKey, b = uint32.from_bytes(b, little=True)

        return ResTable_package_header(header, id, name, typeStrings,
                                       lastPublicType, keyStrings,
                                       lastPublicKey), b[4:]
Example #4
0
    def test_len(self):
        invector = ResTable_package_header(header=ResChunk_header(
            chunkType=ResourceType.RES_TABLE_PACKAGE_TYPE,
            headerSize=0x120,
            size=0x103e4),
                                           id=0x7f,
                                           name=b't\0e\0s\0t\0\0\0',
                                           typeStrings=0x120,
                                           lastPublicType=10,
                                           keyStrings=0x1b4,
                                           lastPublicKey=0x319)
        expected = 0x120
        actual = len(invector)

        self.assertEqual(expected, actual)
Example #5
0
    def test_repr(self):
        invector = ResTable_package_header(header=ResChunk_header(
            chunkType=ResourceType.RES_TABLE_PACKAGE_TYPE,
            headerSize=0x120,
            size=0x103e4),
                                           id=0x7f,
                                           name=b't\0e\0s\0t\0\0\0',
                                           typeStrings=0x120,
                                           lastPublicType=10,
                                           keyStrings=0x1b4,
                                           lastPublicKey=0x319)
        expected = 'ResTable_package_header(ResChunk_header(' \
                'ResourceType.RES_TABLE_PACKAGE_TYPE, 288, 66532), 127, ' \
                '\'test\', 288, 10, 436, 793)'
        actual = repr(invector)

        self.assertEqual(expected, actual)
Example #6
0
    def test_str(self):
        invector = ResTable_package_header(header=ResChunk_header(
            chunkType=ResourceType.RES_TABLE_PACKAGE_TYPE,
            headerSize=0x120,
            size=0x103e4),
                                           id=0x7f,
                                           name=b't\0e\0s\0t\0\0\0',
                                           typeStrings=0x120,
                                           lastPublicType=10,
                                           keyStrings=0x1b4,
                                           lastPublicKey=0x319)
        expected = '{header={type=ResourceType.RES_TABLE_PACKAGE_TYPE, ' \
                'headerSize=288, size=66532}, id=127, name=\'test\', ' \
                'typeStrings=288, lastPublicType=10, keyStrings=436, ' \
                'lastPublicKey=793}'
        actual = str(invector)

        self.assertEqual(expected, actual)
Example #7
0
    def from_bytes(b, little=True):
        content = b
        header, b = ResTable_package_header.from_bytes(b)
        content_size = header.header.size.integer
        content, b = content[:content_size], content[content_size:]
        typeStrings, at = ResStringPool.from_bytes(
            content[header.typeStrings.integer:])
        keyStrings, ak = ResStringPool.from_bytes(
            content[header.keyStrings.integer:])
        if len(ak) < len(at):
            rest = ak
        else:
            rest = at

        types = []
        spec = None
        ret_b = b
        b = rest

        # Deserialize typeSpec and type till end of package. Final structure
        # would be list of lists, where inner list always starts with typeSpec
        # and contains all related type structures
        while len(b) > 0:
            hdr, _ = ResChunk_header.from_bytes(b)
            if hdr.type == ResourceType.RES_TABLE_TYPE_SPEC_TYPE:
                if spec is not None:
                    types.append(spec)
                spec = []
                typeSpec, b = ResTable_typeSpec.from_bytes(b)
                spec.append(typeSpec)
            elif hdr.type == ResourceType.RES_TABLE_TYPE_TYPE:
                typ, b = ResTable_type.from_bytes(b)
                spec.append(typ)
            else:
                raise ChunkHeaderWrongTypeException([
                    ResourceType.RES_TABLE_TYPE_SPEC_TYPE,
                    ResourceType.RES_TABLE_TYPE_TYPE
                ], hdr.type)
        types.append(spec)

        return ResTable_package(header, typeStrings, keyStrings, types), ret_b
Example #8
0
class ResTable_packageTests(unittest.TestCase):

    # FIXME: a bit ugly, maybe change ?
    Flags = ResStringPool_header.Flags

    # ResTable_package_header(name='test')
    package_header = b'\0\2\x20\1\x08\3\0\0\x7f\0\0\0t\0e\0s\0t\0\0\0' + \
            bytes(246) + b'\x20\1\0\0\1\0\0\0\xb4\1\0\0\4\0\0\0' + \
            b'\0\0\0\0'

    # ResStringPool
    type_strings = \
            b'\1\0\x1c\0\x94\0\0\0\x0a\0\0\0\0\0\0\0\0\1\0\0\x44\0\0\0' + \
            b'\0\0\0\0\0\0\0\0\7\0\0\0\x12\0\0\0\x1b\0\0\0\x21\0\0\0' + \
            b'\x29\0\0\0\x31\0\0\0\x3a\0\0\0\x42\0\0\0\x49\0\0\0\4\4attr\0' + \
            b'\x08\x08drawable\0\6\6layout\0\3\3raw\0\5\5color\0\5\5dimen\0' + \
            b'\6\6string\0\5\5style\0\4\4menu\0\2\2id\0' + \
            b'\0\0'

    # ResStringPool
    key_strings = \
            b'\1\0\x1c\0\x4c\0\0\0' + \
            b'\4\0\0\0\0\0\0\0\0\1\0\0\x2c\0\0\0\0\0\0\0' + \
            b'\0\0\0\0\x08\0\0\0\x11\0\0\0\x19\0\0\0' + \
            b'\5\5alarm\0\6\6alarm1\0\5\5arrow\0\4\4back\0'

    typeSpec = b'\2\2\x10\0\x20\0\0\0\7\0\0\0\4\0\0\0' + (b'\4\0\0\0' * 4)  #20

    type1 = b'\1\2\x44\0\x74\0\0\0\7\0\0\0\4\0\0\0\x54\0\0\0' + \
            b'\x30\0\0\0' + bytes(0x2c) + \
            b'\0\0\0\0\x10\0\0\0\x20\0\0\0\x30\0\0\0' + \
            b'\x08\0\0\0\0\0\0\0\x08\0\0\0\x08\0\0\0' + \
            b'\x08\0\0\0\x11\0\0\0\x08\0\0\0\x19\0\0\0'

    type2 = b'\1\2\x44\0\x74\0\0\0\7\0\0\0\4\0\0\0\x54\0\0\0' + \
            b'\x30\0\0\0\0\0\0\0de' + bytes(0x26) + \
            b'\0\0\0\0\x10\0\0\0\x20\0\0\0\x30\0\0\0' + \
            b'\x08\0\0\0\0\0\0\0\x08\0\0\0\x08\0\0\0' + \
            b'\x08\0\0\0\x11\0\0\0\x08\0\0\0\x19\0\0\0'

    tv1_bytes = package_header + type_strings + key_strings + typeSpec + type1 + \
            type2

    tv1_obj = \
            ResTable_package(
                ResTable_package_header(
                    ResChunk_header(
                        ResourceType.RES_TABLE_PACKAGE_TYPE, 288, 776
                    ),
                    127, b't\x00e\x00s\x00t\x00\x00\x00', 288, 1, 436, 4
                ),
                ResStringPool(
                    ResStringPool_header(
                        ResChunk_header(
                            ResourceType.RES_STRING_POOL_TYPE, 28, 148
                        ),
                        10, 0, Flags.UTF8_FLAG, 68, 0
                    ),
                    [
                        uint32(0),
                        uint32(7),
                        uint32(18),
                        uint32(27),
                        uint32(33),
                        uint32(41),
                        uint32(49),
                        uint32(58),
                        uint32(66),
                        uint32(73)
                    ],
                    [],
                    [
                        b'\x04\x04attr\x00',
                        b'\x08\x08drawable\x00',
                        b'\x06\x06layout\x00',
                        b'\x03\x03raw\x00',
                        b'\x05\x05color\x00',
                        b'\x05\x05dimen\x00',
                        b'\x06\x06string\x00',
                        b'\x05\x05style\x00',
                        b'\x04\x04menu\x00',
                        b'\x02\x02id\x00\x00\x00'
                    ],
                    []
                ),
                ResStringPool(
                    ResStringPool_header(
                        ResChunk_header(
                            ResourceType.RES_STRING_POOL_TYPE, 28, 76
                        ),
                        4, 0, Flags.UTF8_FLAG, 44, 0
                    ),
                    [
                        uint32(0),
                        uint32(8),
                        uint32(17),
                        uint32(25)
                    ],
                    [],
                    [
                        b'\x05\x05alarm\x00',
                        b'\x06\x06alarm1\x00',
                        b'\x05\x05arrow\x00',
                        b'\x04\x04back\x00'
                    ],
                    []
                ),
                [
                    [
                        ResTable_typeSpec(
                            ResTable_typeSpec_header(
                                ResChunk_header(
                                    ResourceType.RES_TABLE_TYPE_SPEC_TYPE,
                                    16, 32
                                ),
                                7, 0, 0, 4
                            ),
                            (b'\x04\x00\x00\x00' * 4)
                        ),
                        ResTable_type(
                            ResTable_type_header(
                                ResChunk_header(
                                    ResourceType.RES_TABLE_TYPE_TYPE, 68, 116
                                ),
                                7, 0, 0, 4, 84,
                                b'0' + bytes(0x2f)
                            ),
                            b'\x00\x00\x00\x00\x10\x00\x00\x00'\
                                    b' \x00\x00\x000\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x00\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x08\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x11\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x19\x00\x00\x00'
                        ),
                        ResTable_type(
                            ResTable_type_header(
                                ResChunk_header(
                                    ResourceType.RES_TABLE_TYPE_TYPE, 68, 116
                                ),
                                7, 0, 0, 4, 84,
                                b'0\x00\x00\x00\x00\x00\x00\x00de'+bytes(0x26)
                            ),
                            b'\x00\x00\x00\x00\x10\x00\x00\x00'\
                                    b' \x00\x00\x000\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x00\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x08\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x11\x00\x00\x00'\
                                    b'\x08\x00\x00\x00\x19\x00\x00\x00'
                        )
                    ]
                ]
            )

    def test_str(self):
        invector = ResTable_packageTests.tv1_obj
        expected = "{header={header={type="\
                "ResourceType.RES_TABLE_PACKAGE_TYPE, headerSize=288, "\
                "size=776}, id=127, name=b't\\x00e\\x00s\\x00t\\x00\\x00\\x00"+\
                ("\\x00" * 246)+"', typeStrings=288, lastPublicType=1, "\
                "keyStrings=436, lastPublicKey=4}, typeStrings={"\
                "header={header={"\
                "type=ResourceType.RES_STRING_POOL_TYPE, headerSize=28, "\
                "size=148}, stringCount=10, styleCount=0, "\
                "flags=Flags.UTF8_FLAG, stringsStart=68, stylesStart=0}, "\
                "strrefs=[uint32(0), uint32(7), uint32(18), uint32(27), "\
                "uint32(33), uint32(41), uint32(49), uint32(58), uint32(66), "\
                "uint32(73)], stylerefs=[], strings=[b'\\x04\\x04attr\\x00', "\
                "b'\\x08\\x08drawable\\x00', b'\\x06\\x06layout\\x00', "\
                "b'\\x03\\x03raw\\x00', b'\\x05\\x05color\\x00', "\
                "b'\\x05\\x05dimen\\x00', b'\\x06\\x06string\\x00', "\
                "b'\\x05\\x05style\\x00', b'\\x04\\x04menu\\x00', "\
                "b'\\x02\\x02id\\x00\\x00\\x00'], styles=[]}, "\
                "keyStrings={header={header={"\
                "type=ResourceType.RES_STRING_POOL_TYPE, headerSize=28, "\
                "size=76}, stringCount=4, styleCount=0, "\
                "flags=Flags.UTF8_FLAG, stringsStart=44, stylesStart=0}, "\
                "strrefs=[uint32(0), uint32(8), uint32(17), uint32(25)], "\
                "stylerefs=[], strings=[b'\\x05\\x05alarm\\x00', "\
                "b'\\x06\\x06alarm1\\x00', b'\\x05\\x05arrow\\x00', "\
                "b'\\x04\\x04back\\x00'], styles=[]}, "\
                "types=[[ResTable_typeSpec(ResTable_typeSpec_header("\
                "ResChunk_header(ResourceType.RES_TABLE_TYPE_SPEC_TYPE, 16, "\
                "32), 7, 0, 0, 4), b'\\x04\\x00\\x00\\x00\\x04\\x00\\x00\\x00"\
                "\\x04\\x00\\x00\\x00\\x04\\x00\\x00\\x00'), ResTable_type("\
                "ResTable_type_header(ResChunk_header("\
                "ResourceType.RES_TABLE_TYPE_TYPE, 68, 116), 7, 0, 0, 4, 84, "\
                "b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'"\
                "), b'\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00 \\x00\\x00\\x00"\
                "0\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08"\
                "\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x11"\
                "\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x19\\x00\\x00\\x00'), "\
                "ResTable_type(ResTable_type_header(ResChunk_header("\
                "ResourceType.RES_TABLE_TYPE_TYPE, 68, 116), 7, 0, 0, 4, 84, "\
                "b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00de\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'), b'\\x00"\
                "\\x00\\x00\\x00\\x10\\x00\\x00\\x00 \\x00\\x00\\x000\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x11\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x19\\x00\\x00\\x00')]]}"
        actual = str(invector)

        self.assertEqual(expected, actual)

    def test_repr(self):
        invector = ResTable_packageTests.tv1_obj
        expected = "ResTable_package(ResTable_package_header(ResChunk_header("\
                "ResourceType.RES_TABLE_PACKAGE_TYPE, 288, 776), 127, "\
                "b't\\x00e\\x00s\\x00t\\x00\\x00\\x00" + ("\\x00" * 246) + \
                "', 288, 1, 436, 4), ResStringPool(ResStringPool_header("\
                "ResChunk_header(ResourceType.RES_STRING_POOL_TYPE, 28, 148"\
                "), 10, 0, Flags.UTF8_FLAG, 68, 0), [uint32(0), uint32(7), "\
                "uint32(18), uint32(27), uint32(33), uint32(41), uint32(49), "\
                "uint32(58), uint32(66), uint32(73)], [], ["\
                "b'\\x04\\x04attr\\x00', b'\\x08\\x08drawable\\x00', "\
                "b'\\x06\\x06layout\\x00', b'\\x03\\x03raw\\x00', "\
                "b'\\x05\\x05color\\x00', b'\\x05\\x05dimen\\x00', "\
                "b'\\x06\\x06string\\x00', b'\\x05\\x05style\\x00', "\
                "b'\\x04\\x04menu\\x00', b'\\x02\\x02id\\x00\\x00\\x00'], "\
                "[]), ResStringPool(ResStringPool_header(ResChunk_header("\
                "ResourceType.RES_STRING_POOL_TYPE, 28, 76), 4, 0, "\
                "Flags.UTF8_FLAG, 44, 0), [uint32(0), uint32(8), uint32(17), "\
                "uint32(25)], [], [b'\\x05\\x05alarm\\x00', "\
                "b'\\x06\\x06alarm1\\x00', b'\\x05\\x05arrow\\x00', "\
                "b'\\x04\\x04back\\x00'], []), [[ResTable_typeSpec("\
                "ResTable_typeSpec_header(ResChunk_header("\
                "ResourceType.RES_TABLE_TYPE_SPEC_TYPE, 16, 32), 7, 0, 0, 4), "\
                "b'\\x04\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x04\\x00\\x00"\
                "\\x00\\x04\\x00\\x00\\x00'), ResTable_type("\
                "ResTable_type_header(ResChunk_header("\
                "ResourceType.RES_TABLE_TYPE_TYPE, 68, 116), 7, 0, 0, 4, 84, "\
                "b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'"\
                "), b'\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00 \\x00\\x00\\x00"\
                "0\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08"\
                "\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x11"\
                "\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x19\\x00\\x00\\x00'), "\
                "ResTable_type(ResTable_type_header(ResChunk_header("\
                "ResourceType.RES_TABLE_TYPE_TYPE, 68, 116), 7, 0, 0, 4, 84, "\
                "b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00de\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"\
                "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'), b'\\x00"\
                "\\x00\\x00\\x00\\x10\\x00\\x00\\x00 \\x00\\x00\\x000\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x11\\x00"\
                "\\x00\\x00\\x08\\x00\\x00\\x00\\x19\\x00\\x00\\x00')]])"
        actual = repr(invector)

        self.assertEqual(expected, actual)

    def test_bytes(self):
        invector = ResTable_packageTests.tv1_obj
        expected = ResTable_packageTests.tv1_bytes
        actual = bytes(invector)

        self.assertEqual(expected, actual)

    def test_from_bytes(self):
        invector = ResTable_packageTests.tv1_bytes + b'\x13\x37'
        expected = ResTable_packageTests.tv1_obj, b'\x13\x37'
        actual = ResTable_package.from_bytes(invector)

        self.assertEqual(expected, actual)
Example #9
0
    def __init__(self,
                 header=None,
                 id=0,
                 name=b'\0\0',
                 typeStrings=0,
                 lastPublicType=0,
                 keyStrings=0,
                 lastPublicKey=0):
        if header is None:
            header = ResChunk_header(ResourceType.RES_TABLE_PACKAGE_TYPE,
                                     headerSize=ResTable_package_header.len,
                                     size=ResTable_package_header.len)
        if not isinstance(header, ResChunk_header):
            raise WrongTypeException('header', ResChunk_header)
        if header.type is not ResourceType.RES_TABLE_PACKAGE_TYPE:
            raise ChunkHeaderWrongTypeException(
                ResourceType.RES_TABLE_PACKAGE_TYPE)
        ## \link ResChunk_header \endlink instance
        # \details Identifies structure and defines its size
        self.header = header

        if isinstance(id, uint32):
            ## If this is a base package, its ID
            # \details Package IDs start at 1 (corresponding to the value of the
            # package bits in a resource identifier). 0 means this is not a base
            # package.
            self.id = id
        else:
            self.id = uint32(id, little=True)

        if isinstance(name, bytes):
            name_length = len(name)
            if name_length > ResTable_package_header.MAX_NAME_LEN * 2:
                raise Exception('name is longer than maximum ({l}>{m})'.format(
                    l=name_length, m=ResTable_package_header.MAX_NAME_LEN))
            if name[-2:] != b'\0\0':
                raise (Exception('name does not end with NULL'))
            ## Actual name of this package
            # \details NULL-terminated, UTF-16 string.
            self.name = name + bytes((ResTable_package_header.MAX_NAME_LEN * \
                    2) - name_length)
        else:
            raise Exception('name must be of type bytes')

        if isinstance(typeStrings, uint32):
            self.typeStrings = typeStrings
        else:
            self.typeStrings = uint32(typeStrings, little=True)

        if isinstance(lastPublicType, uint32):
            self.lastPublicType = lastPublicType
        else:
            self.lastPublicType = uint32(lastPublicType, little=True)

        if isinstance(keyStrings, uint32):
            self.keyStrings = keyStrings
        else:
            self.keyStrings = uint32(keyStrings, little=True)

        if isinstance(lastPublicKey, uint32):
            self.lastPublicKey = lastPublicKey
        else:
            self.lastPublicKey = uint32(lastPublicKey, little=True)