Exemple #1
0
def _ParseManifestFromApk(apk_path):
    aapt_output = aapt.Dump('xmltree', apk_path, 'AndroidManifest.xml')

    parsed_manifest = {}
    node_stack = [parsed_manifest]
    indent = '  '

    for line in aapt_output[1:]:
        if len(line) == 0:
            continue

        indent_depth = 0
        while line[(len(indent) * indent_depth):].startswith(indent):
            indent_depth += 1

        node_stack = node_stack[:indent_depth]
        node = node_stack[-1]

        m = _MANIFEST_ELEMENT_RE.match(line[len(indent) * indent_depth:])
        if m:
            if not m.group(1) in node:
                node[m.group(1)] = {}
            node_stack += [node[m.group(1)]]
            continue

        m = _MANIFEST_ATTRIBUTE_RE.match(line[len(indent) * indent_depth:])
        if m:
            if not m.group(1) in node:
                node[m.group(1)] = []
            node[m.group(1)].append(m.group(2) or m.group(3))
            continue

    return parsed_manifest
Exemple #2
0
def _ParseManifestFromApk(apk_path):
    aapt_output = aapt.Dump('xmltree', apk_path, 'AndroidManifest.xml')
    parsed_manifest = {}
    node_stack = [parsed_manifest]
    indent = '  '

    if aapt_output[0].decode('utf8').startswith('N'):
        # if the first line is a namespace then the root manifest is indented, and
        # we need to add a dummy namespace node, then skip the first line (we dont
        # care about namespaces).
        node_stack.insert(0, {})
        output_to_parse = aapt_output[1:]
    else:
        output_to_parse = aapt_output

    for line in output_to_parse:
        if len(line) == 0:
            continue

        # If namespaces are stripped, aapt still outputs the full url to the
        # namespace and appends it to the attribute names.
        line = line.decode('utf8')
        line = line.replace('http://schemas.android.com/apk/res/android:',
                            'android:')

        indent_depth = 0
        while line[(len(indent) * indent_depth):].startswith(indent):
            indent_depth += 1

        # Pop the stack until the height of the stack is the same is the depth of
        # the current line within the tree.
        node_stack = node_stack[:indent_depth + 1]
        node = node_stack[-1]

        # Element nodes are a list of python dicts while attributes are just a dict.
        # This is because multiple elements, at the same depth of tree and the same
        # name, are all added to the same list keyed under the element name.
        m = _MANIFEST_ELEMENT_RE.match(line[len(indent) * indent_depth:])
        if m:
            manifest_key = m.group(1)
            if manifest_key in node:
                node[manifest_key] += [{}]
            else:
                node[manifest_key] = [{}]
            node_stack += [node[manifest_key][-1]]
            continue

        m = _MANIFEST_ATTRIBUTE_RE.match(line[len(indent) * indent_depth:])
        if m:
            manifest_key = m.group(1)
            if manifest_key in node:
                raise ApkHelperError(
                    "A single attribute should have one key and one value: {}".
                    format(line))
            else:
                node[manifest_key] = m.group(2) or m.group(3)
            continue

    return parsed_manifest
Exemple #3
0
    def GetSplitName(self):
        """Returns the name of the split of the apk."""
        if self._split_name:
            return self._split_name

        aapt_output = aapt.Dump('badging', self._apk_path)
        for line in aapt_output:
            m = _SPLIT_NAME_RE.match(line)
            if m:
                self._split_name = m.group(1)
                return self._split_name
        return None
Exemple #4
0
    def GetPackageName(self):
        """Returns the package name of the apk."""
        if self._package_name:
            return self._package_name

        aapt_output = aapt.Dump('badging', self._apk_path)
        for line in aapt_output:
            m = _PACKAGE_NAME_RE.match(line)
            if m:
                self._package_name = m.group(1)
                return self._package_name
        raise Exception('Failed to determine package name of %s' %
                        self._apk_path)
Exemple #5
0
def _ParseManifestFromApk(apk_path):
    aapt_output = aapt.Dump('xmltree', apk_path, 'AndroidManifest.xml')

    parsed_manifest = {}
    node_stack = [parsed_manifest]
    indent = '  '

    for line in aapt_output[1:]:
        if len(line) == 0:
            continue

        indent_depth = 0
        while line[(len(indent) * indent_depth):].startswith(indent):
            indent_depth += 1

        node_stack = node_stack[:indent_depth]
        node = node_stack[-1]

        m = _MANIFEST_ELEMENT_RE.match(line[len(indent) * indent_depth:])
        if m:
            manifest_key = m.group(1)
            if manifest_key in node:
                node[manifest_key] += [{}]
            else:
                node[manifest_key] = [{}]
            node_stack += [node[manifest_key][-1]]
            continue

        m = _MANIFEST_ATTRIBUTE_RE.match(line[len(indent) * indent_depth:])
        if m:
            manifest_key = m.group(1)
            if manifest_key in node:
                raise base_error.BaseError(
                    "A single attribute should have one key and one value")
            else:
                node[manifest_key] = m.group(2) or m.group(3)
            continue

    return parsed_manifest