node-apk
Version:
A library to parse Android application manifest and signature
104 lines (102 loc) • 4.53 kB
JavaScript
"use strict";
/*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>.*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseResourceValue = exports.StringPool = exports.Chunk = exports.ChunkType = void 0;
var ChunkType;
(function (ChunkType) {
ChunkType[ChunkType["NULL"] = 0] = "NULL";
ChunkType[ChunkType["STRING_POOL"] = 1] = "STRING_POOL";
ChunkType[ChunkType["TABLE"] = 2] = "TABLE";
ChunkType[ChunkType["XML"] = 3] = "XML";
ChunkType[ChunkType["XML_FIRST_CHUNK"] = 256] = "XML_FIRST_CHUNK";
ChunkType[ChunkType["XML_START_NAMESPACE"] = 256] = "XML_START_NAMESPACE";
ChunkType[ChunkType["XML_END_NAMESPACE"] = 257] = "XML_END_NAMESPACE";
ChunkType[ChunkType["XML_START_ELEMENT"] = 258] = "XML_START_ELEMENT";
ChunkType[ChunkType["XML_END_ELEMENT"] = 259] = "XML_END_ELEMENT";
ChunkType[ChunkType["XML_CDATA"] = 260] = "XML_CDATA";
ChunkType[ChunkType["XML_LAST_CHUNK"] = 383] = "XML_LAST_CHUNK";
ChunkType[ChunkType["XML_RESOURCE_MAP"] = 384] = "XML_RESOURCE_MAP";
ChunkType[ChunkType["TABLE_PACKAGE"] = 512] = "TABLE_PACKAGE";
ChunkType[ChunkType["TABLE_TYPE"] = 513] = "TABLE_TYPE";
ChunkType[ChunkType["TABLE_TYPE_SPEC"] = 514] = "TABLE_TYPE_SPEC";
ChunkType[ChunkType["TABLE_LIBRARY"] = 515] = "TABLE_LIBRARY";
})(ChunkType = exports.ChunkType || (exports.ChunkType = {}));
var Chunk = /** @class */ (function () {
function Chunk(source, chunkType) {
this.type = source.readUShort();
if (!chunkType || this.type === chunkType) {
this.headerSize = source.readUShort();
this.chunkSize = source.readUInt();
this.headerSource = source.source(this.headerSize - 8);
this.chunkSource = source.source(this.chunkSize - this.headerSize);
}
else {
throw Error("Found incorrect chunk type: ".concat(this.type, ", expected: ").concat(chunkType));
}
}
return Chunk;
}());
exports.Chunk = Chunk;
var StringPool = /** @class */ (function () {
function StringPool(chunk) {
this.stringCount = chunk.headerSource.readUInt();
this.styleCount = chunk.headerSource.readUInt();
this.flags = chunk.headerSource.readUInt();
this.stringsStart = chunk.headerSource.readUInt();
this.stylesStart = chunk.headerSource.readUInt();
this.values = [];
var indexes = [];
for (var i = 0; i < this.stringCount; ++i) {
indexes.push(chunk.chunkSource.readUInt());
}
// TODO: make sure indexes are sorted
for (var _i = 0, indexes_1 = indexes; _i < indexes_1.length; _i++) {
var index = indexes_1[_i];
chunk.chunkSource.moveAt(this.stringsStart - chunk.headerSize + index);
if (this.flags & 256) {
this.values.push(StringPool.readUtf8String(chunk.chunkSource));
}
else {
this.values.push(StringPool.readUtf16String(chunk.chunkSource));
}
}
}
StringPool.readUtf8String = function (source) {
source.getCursorAndMove(1); // skip char length
return source.readUtf8String(source.readUByte());
};
StringPool.readUtf16String = function (source) {
return source.readUtf16String(source.readUShort() * 2);
};
return StringPool;
}());
exports.StringPool = StringPool;
var ResourceType;
(function (ResourceType) {
ResourceType[ResourceType["NULL"] = 0] = "NULL";
ResourceType[ResourceType["REFERENCE"] = 1] = "REFERENCE";
ResourceType[ResourceType["STRING"] = 3] = "STRING";
ResourceType[ResourceType["INT_DEC"] = 16] = "INT_DEC";
ResourceType[ResourceType["INT_BOOLEAN"] = 18] = "INT_BOOLEAN";
})(ResourceType || (ResourceType = {}));
function parseResourceValue(source, stringPool) {
source.getCursorAndMove(3); // size + res0
var type = source.readUByte();
switch (type) {
case ResourceType.REFERENCE:
return source.readInt();
case ResourceType.STRING: {
var index = source.readInt();
return index >= 0 ? stringPool.values[index] : null;
}
case ResourceType.INT_DEC:
return source.readInt();
case ResourceType.INT_BOOLEAN:
return source.readInt() === 0 ? false : true;
default:
return null;
}
}
exports.parseResourceValue = parseResourceValue;