UNPKG

node-apk

Version:

A library to parse Android application manifest and signature

79 lines (66 loc) 2.56 kB
/* * Copyright (c) 2019 XdevL. All rights reserved. * * This work is licensed under the terms of the MIT license. * For a copy, see <https://opensource.org/licenses/MIT>. */ import { Chunk, ChunkType, parseResourceValue, StringPool } from "./common"; import Source from "./source"; class XmlAttribute { public readonly name: string; public readonly value: any; constructor(source: Source, stringPool: StringPool) { source.getCursorAndMove(4); // nameSpace this.name = stringPool.values[source.readInt()]; source.getCursorAndMove(4); // rawValue this.value = parseResourceValue(source, stringPool); } } export default class XmlElement { private static parseChildren(parent: XmlElement, root: Chunk, stringPool: StringPool) { const maxOffset = root.chunkSize - root.headerSize; while (root.chunkSource.getCursorAndMove(0) < maxOffset) { const chunk = new Chunk(root.chunkSource); switch(chunk.type) { case ChunkType.XML_START_ELEMENT: { const child = new XmlElement(chunk.chunkSource, stringPool); parent.children[child.tag] = parent.children[child.tag] || []; parent.children[child.tag].push(child); XmlElement.parseChildren(child, root, stringPool); break; } case ChunkType.XML_START_NAMESPACE: XmlElement.parseChildren(parent, root, stringPool); break; case ChunkType.XML_END_ELEMENT: case ChunkType.XML_END_NAMESPACE: return; } } } public readonly tag: string; public readonly attributes: {[key: string]: any} = {}; public readonly children: {[key: string]: XmlElement[]} = {}; constructor(source: Source, stringPool?: StringPool) { if (stringPool) { source.getCursorAndMove(4); // namespace this.tag = stringPool.values[source.readInt()]; const attributeStart = source.readUShort(); const attributeSize = source.readUShort(); const attributeCount = source.readUShort(); source.moveAt(attributeStart); for (let i = 0; i < attributeCount; ++i ) { const attr = new XmlAttribute(source.source(attributeSize), stringPool); this.attributes[attr.name] = attr.value; } } else { const chunk = new Chunk(source, ChunkType.XML) stringPool = new StringPool(new Chunk(chunk.chunkSource, ChunkType.STRING_POOL)); this.tag = "xml"; XmlElement.parseChildren(this, chunk, stringPool); } } public toString(): string { return JSON.stringify(this, null, 4); } }