summaryrefslogtreecommitdiff
path: root/plugins/python/androperms/parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/python/androperms/parser.py')
-rw-r--r--plugins/python/androperms/parser.py328
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 ""