diff options
Diffstat (limited to 'plugins/python/androperms/parser.py')
-rw-r--r-- | plugins/python/androperms/parser.py | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/plugins/python/androperms/parser.py b/plugins/python/androperms/parser.py new file mode 100644 index 0000000..1939bbe --- /dev/null +++ b/plugins/python/androperms/parser.py @@ -0,0 +1,328 @@ +#!/usr/bin/python -u +# -*- coding: utf-8 -*- + + +from defs import * +from stack import NamespaceStack +from string import StringBlock + +from struct import unpack + + +class AXMLParser(): + + + def __init__(self, reader): + + self._reader = reader + + magic = reader.readInt() + if magic != CHUNK_AXML_FILE: + raise Exception('Bad Magic Number (0x%08lx)!' % magic) + + # chunkSize + reader.skipInt() + + self._strings = StringBlock(reader) + self._namespaces = NamespaceStack() + self._operational = True + + self.resetEventInfo() + + + def resetEventInfo(self): + + self._event = -1 + self._line_number = -1 + self._name = -1 + self._namespace_uri = -1 + self._attributes = None + self._id_attrib = -1 + self._class_attrib = -1 + self._style_attrib = -1 + + self._decreaseDepth = False + + + + def next(self): + + self.doNext() + return self._event + + + def doNext(self): + + + + + + event = self._event + + + while True: + + if self._decreaseDepth: + self._decreaseDepth = False + self._namespaces.decDepth() + + # Fake END_DOCUMENT event. + if event == END_TAG and self._namespaces.getDepth() == 1 and self._namespaces.count() == 0: + self._event = END_DOCUMENT + break + + if event == START_DOCUMENT: + # Fake event, see CHUNK_XML_START_TAG handler. + chunk = CHUNK_XML_START_TAG + + else: + chunk = self._reader.readInt() + + if chunk == CHUNK_RESOURCEIDS: + + size = self._reader.readInt() + if size < 8 or size % 4 != 0: + raise Exception('Invalid resource ids size (%d).' % size) + + self._resource_ids = self._reader.readIntArray(size / 4 - 2) + + continue + + if chunk < CHUNK_XML_FIRST or chunk > CHUNK_XML_LAST: + raise Exception('Invalid chunk type 0x%08lx.' % chunk) + + # Fake START_DOCUMENT event. + if chunk == CHUNK_XML_START_TAG and event == -1: + self._event = START_DOCUMENT + break + + # Common header. + self._reader.skipInt() # chunkSize + self._line_number = self._reader.readInt() + self._reader.skipInt() # 0xffffffff + + if chunk == CHUNK_XML_START_NAMESPACE or chunk == CHUNK_XML_END_NAMESPACE: + + if chunk == CHUNK_XML_START_NAMESPACE: + + prefix = self._reader.readInt() + uri = self._reader.readInt() + self._namespaces.push(prefix, uri) + + else: + + self._reader.skipInt() # prefix + self._reader.skipInt() # uri + self._namespaces.pop() + + continue + + elif chunk == CHUNK_XML_START_TAG: + + self._namespace_uri = self._reader.readInt() + self._name = self._reader.readInt() + self._reader.skipInt() # flags ? + + attribs_count = self._reader.readInt() + self._id_attrib = (attribs_count >> 16) - 1 + attribs_count &= 0xffff + + self._class_attrib = self._reader.readInt() + self._style_attrib = (self._class_attrib >> 16) - 1 + self._class_attrib = (self._class_attrib & 0xffff) - 1 + + self._attributes = self._reader.readIntArray(attribs_count * ATTRIBUTE_LENGHT) + + for i in range(ATTRIBUTE_IX_VALUE_TYPE, len(self._attributes), ATTRIBUTE_LENGHT): + self._attributes[i] >>= 24 + + self._namespaces.incDepth() + self._event = START_TAG + + break + + elif chunk == CHUNK_XML_END_TAG: + + self._namespaceUri = self._reader.readInt() + self._name = self._reader.readInt() + + self._event = END_TAG + self._decreaseDepth = True + + break + + elif chunk == CHUNK_XML_TEXT: + + self._name = self._reader.readInt() + self._reader.skipInt() # ??? + self._reader.skipInt() # ??? + + self._event=TEXT + + break + + else: + raise Exception('Unknown chunck (0x%08lx)' % chunk) + + + ### ESPACES ### + + def getNamespacePrefix(self, index): + + name = self._namespaces.getPrefix(index) + + if name == -1: + return '' + + else: + return self._strings.getRaw(name) + + + def getNamespaceUri(self, index): + + name = self._namespaces.getUri(index) + + if name == -1: + return '' + + else: + return self._strings.getRaw(name) + + + ### NAMES ### + + def getTagPrefix(self): + """Provide the prefix linked to START_TAG or END_TAG.""" + + name = self._namespaces.findPrefix(self._namespace_uri) + + if name == -1: + return '' + + else: + return self._strings.getRaw(name) + ':' + + + def getTagName(self): + """Provide the name linked to START_TAG or END_TAG.""" + + if self._name == -1 or (self._event != START_TAG and self._event != END_TAG): + raise Exception('Invalid tag name.') + + return self._strings.getRaw(self._name) + + + def getText(self): + """Provide the content linked to TEXT.""" + + if self._name == -1 or self._event != START_TEXT: + raise Exception('Invalid text content.') + + return self._strings.getRaw(self._name) + + + ### ATRIBUTES ### + + def countAttributes(self): + """Count the properties of the current tag.""" + + if self._event != START_TAG: + raise Exception('Invalid event.') + + return len(self._attributes) / ATTRIBUTE_LENGHT + + + def getAttribPrefix(self, index): + """Get the prefix of a given attribute.""" + + index *= ATTRIBUTE_LENGHT + + if index >= len(self._attributes): + raise Exception('Bad attribute index.') + + uri = self._attributes[index + ATTRIBUTE_IX_NAMESPACE_URI] + name = self._namespaces.findPrefix(uri) + + if name == -1: + return '' + + else: + return self._strings.getRaw(name) + ':' + + + def getAttribName(self, index): + """Get the name of a given attribute.""" + + index *= ATTRIBUTE_LENGHT + + if index >= len(self._attributes): + raise Exception('Bad attribute index.') + + name = self._attributes[index + ATTRIBUTE_IX_NAME] + + if name == -1: + return '???' + + else: + return self._strings.getRaw(name) + + + def getAttribValue(self, index): + """Get the value of a given attribute.""" + + index *= ATTRIBUTE_LENGHT + + if index >= len(self._attributes): + raise Exception('Bad attribute index.') + + vtype = self._attributes[index + ATTRIBUTE_IX_VALUE_TYPE] + vdata = self._attributes[index + ATTRIBUTE_IX_VALUE_DATA] + + if vtype == TYPE_NULL: + return '???' + + elif vtype == TYPE_REFERENCE: + return '@%s%08X' % (self.getPackage(vdata), vdata) + + elif vtype == TYPE_ATTRIBUTE: + return '?%s%08X' % (self.getPackage(vdata), vdata) + + if vtype == TYPE_STRING: + vdata = self._attributes[index + ATTRIBUTE_IX_VALUE_STRING] + return self._strings.getRaw(vdata) + + elif vtype == TYPE_FLOAT: + return '%f' % unpack('=f', pack('=L', vdata))[0] + + elif vtype == TYPE_DIMENSION: + return '%f%s' % (self.complexToFloat(vdata), DIMENSION_UNITS[vdata & COMPLEX_UNIT_MASK]) + + elif vtype == TYPE_FRACTION: + return '%f%s' % (self.complexToFloat(vdata), FRACTION_UNITS[vdata & COMPLEX_UNIT_MASK]) + + elif vtype == TYPE_INT_HEX: + return '0x%08x' % vdata + + elif vtype == TYPE_INT_BOOLEAN: + if vdata == 0: + return 'false' + else: + return 'true' + + elif vtype >= TYPE_FIRST_COLOR_INT and vtype <= TYPE_LAST_COLOR_INT: + return '#%08x' % vdata + + elif vtype >= TYPE_FIRST_INT and vtype <= TYPE_LAST_INT: + return str(vdata) + + return "<0x%x, 0x%02x>" % (vdata, vtype) + + + def complexToFloat(self, xcomplex): + return (float)(xcomplex & 0xffffff00) * RADIX_MULTS[(xcomplex >> 4) & 3]; + + def getPackage(self, id): + if id >> 24 == 1: + return "android:" + else: + return "" |