react-native-update-cli 2.4.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/cli.json +40 -0
- package/lib/api.js +1 -1
- package/lib/locales/en.js +16 -1
- package/lib/locales/zh.js +16 -1
- package/lib/package.js +60 -6
- package/lib/provider.js +3 -0
- package/lib/utils/app-info-parser/aab.js +230 -0
- package/lib/utils/app-info-parser/apk.js +25 -27
- package/lib/utils/app-info-parser/app.js +10 -11
- package/lib/utils/app-info-parser/index.js +13 -8
- package/lib/utils/app-info-parser/ipa.js +16 -21
- package/lib/utils/app-info-parser/resource-finder.js +365 -305
- package/lib/utils/app-info-parser/utils.js +78 -63
- package/lib/utils/app-info-parser/xml-parser/binary.js +57 -51
- package/lib/utils/app-info-parser/xml-parser/manifest.js +47 -39
- package/lib/utils/app-info-parser/zip.js +21 -11
- package/lib/utils/http-helper.js +1 -1
- package/lib/utils/index.js +137 -0
- package/lib/versions.js +22 -0
- package/package.json +3 -2
- package/proto/Configuration.proto +183 -0
- package/proto/Resources.proto +569 -0
- package/src/api.ts +2 -6
- package/src/locales/en.ts +20 -0
- package/src/locales/zh.ts +18 -0
- package/src/modules/version-module.ts +1 -1
- package/src/package.ts +112 -12
- package/src/provider.ts +3 -0
- package/src/utils/app-info-parser/aab.ts +240 -0
- package/src/utils/app-info-parser/{apk.js → apk.ts} +30 -41
- package/src/utils/app-info-parser/app.ts +3 -0
- package/src/utils/app-info-parser/index.ts +9 -5
- package/src/utils/app-info-parser/{ipa.js → ipa.ts} +17 -31
- package/src/utils/app-info-parser/resource-finder.ts +508 -0
- package/src/utils/app-info-parser/utils.ts +162 -0
- package/src/utils/app-info-parser/xml-parser/{binary.js → binary.ts} +69 -61
- package/src/utils/app-info-parser/xml-parser/{manifest.js → manifest.ts} +50 -51
- package/src/utils/app-info-parser/zip.ts +86 -0
- package/src/utils/dep-versions.ts +7 -4
- package/src/utils/http-helper.ts +1 -1
- package/src/utils/index.ts +154 -0
- package/src/utils/latest-version/index.ts +2 -1
- package/src/versions.ts +27 -2
- package/src/utils/app-info-parser/app.js +0 -16
- package/src/utils/app-info-parser/resource-finder.js +0 -495
- package/src/utils/app-info-parser/utils.js +0 -172
- package/src/utils/app-info-parser/zip.js +0 -66
|
@@ -1,32 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
4
10
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
_export(exports, {
|
|
12
|
+
decodeNullUnicode: function() {
|
|
13
|
+
return decodeNullUnicode;
|
|
14
|
+
},
|
|
15
|
+
findApkIconPath: function() {
|
|
16
|
+
return findApkIconPath;
|
|
17
|
+
},
|
|
18
|
+
findIpaIconPath: function() {
|
|
19
|
+
return findIpaIconPath;
|
|
20
|
+
},
|
|
21
|
+
getBase64FromBuffer: function() {
|
|
22
|
+
return getBase64FromBuffer;
|
|
23
|
+
},
|
|
24
|
+
isArray: function() {
|
|
25
|
+
return isArray;
|
|
26
|
+
},
|
|
27
|
+
isBrowser: function() {
|
|
28
|
+
return isBrowser;
|
|
29
|
+
},
|
|
30
|
+
isObject: function() {
|
|
31
|
+
return isObject;
|
|
32
|
+
},
|
|
33
|
+
isPrimitive: function() {
|
|
34
|
+
return isPrimitive;
|
|
35
|
+
},
|
|
36
|
+
mapInfoResource: function() {
|
|
37
|
+
return mapInfoResource;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const objectType = (value)=>Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
|
|
41
|
+
const isArray = (value)=>objectType(value) === 'array';
|
|
42
|
+
const isObject = (value)=>objectType(value) === 'object';
|
|
43
|
+
const isPrimitive = (value)=>value === null || [
|
|
13
44
|
'boolean',
|
|
14
45
|
'number',
|
|
15
46
|
'string',
|
|
16
47
|
'undefined'
|
|
17
|
-
].includes(objectType(
|
|
18
|
-
|
|
19
|
-
function isBrowser() {
|
|
20
|
-
return typeof process === 'undefined' || Object.prototype.toString.call(process) !== '[object process]';
|
|
21
|
-
}
|
|
48
|
+
].includes(objectType(value));
|
|
49
|
+
const isBrowser = ()=>typeof process === 'undefined' || Object.prototype.toString.call(process) !== '[object process]';
|
|
22
50
|
/**
|
|
23
51
|
* map file place with resourceMap
|
|
24
52
|
* @param {Object} apkInfo // json info parsed from .apk file
|
|
25
53
|
* @param {Object} resourceMap // resourceMap
|
|
26
|
-
*/
|
|
27
|
-
iteratorObj(
|
|
28
|
-
return apkInfo;
|
|
29
|
-
function iteratorObj(obj) {
|
|
54
|
+
*/ const mapInfoResource = (apkInfo, resourceMap)=>{
|
|
55
|
+
const iteratorObj = (obj)=>{
|
|
30
56
|
for(const i in obj){
|
|
31
57
|
if (isArray(obj[i])) {
|
|
32
58
|
iteratorArray(obj[i]);
|
|
@@ -38,8 +64,8 @@ function isBrowser() {
|
|
|
38
64
|
}
|
|
39
65
|
}
|
|
40
66
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
67
|
+
};
|
|
68
|
+
const iteratorArray = (array)=>{
|
|
43
69
|
const l = array.length;
|
|
44
70
|
for(let i = 0; i < l; i++){
|
|
45
71
|
if (isArray(array[i])) {
|
|
@@ -52,22 +78,20 @@ function isBrowser() {
|
|
|
52
78
|
}
|
|
53
79
|
}
|
|
54
80
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
81
|
+
};
|
|
82
|
+
const isResources = (attrValue)=>{
|
|
57
83
|
if (!attrValue) return false;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
}
|
|
84
|
+
const value = typeof attrValue === 'string' ? attrValue : attrValue.toString();
|
|
85
|
+
return value.indexOf('resourceId:') === 0;
|
|
86
|
+
};
|
|
87
|
+
const transKeyToMatchResourceMap = (resourceId)=>`@${resourceId.replace('resourceId:0x', '').toUpperCase()}`;
|
|
88
|
+
iteratorObj(apkInfo);
|
|
89
|
+
return apkInfo;
|
|
90
|
+
};
|
|
67
91
|
/**
|
|
68
92
|
* find .apk file's icon path from json info
|
|
69
93
|
* @param info // json info parsed from .apk file
|
|
70
|
-
*/
|
|
94
|
+
*/ const findApkIconPath = (info)=>{
|
|
71
95
|
if (!info.application.icon || !info.application.icon.splice) {
|
|
72
96
|
return '';
|
|
73
97
|
}
|
|
@@ -86,14 +110,14 @@ function isBrowser() {
|
|
|
86
110
|
for(const i in rulesMap){
|
|
87
111
|
info.application.icon.some((icon)=>{
|
|
88
112
|
if (icon && icon.indexOf(i) !== -1) {
|
|
89
|
-
resultMap[
|
|
113
|
+
resultMap[`application-icon-${rulesMap[i]}`] = icon;
|
|
90
114
|
return true;
|
|
91
115
|
}
|
|
116
|
+
return false;
|
|
92
117
|
});
|
|
93
|
-
|
|
94
|
-
if (resultMap['application-icon-' + rulesMap[i]] && rulesMap[i] >= maxDpiIcon.dpi) {
|
|
118
|
+
if (resultMap[`application-icon-${rulesMap[i]}`] && rulesMap[i] >= maxDpiIcon.dpi) {
|
|
95
119
|
maxDpiIcon.dpi = rulesMap[i];
|
|
96
|
-
maxDpiIcon.icon = resultMap[
|
|
120
|
+
maxDpiIcon.icon = resultMap[`application-icon-${rulesMap[i]}`];
|
|
97
121
|
}
|
|
98
122
|
}
|
|
99
123
|
if (Object.keys(resultMap).length === 0 || !maxDpiIcon.icon) {
|
|
@@ -102,43 +126,34 @@ function isBrowser() {
|
|
|
102
126
|
resultMap['applicataion-icon-120'] = maxDpiIcon.icon;
|
|
103
127
|
}
|
|
104
128
|
return maxDpiIcon.icon;
|
|
105
|
-
}
|
|
129
|
+
};
|
|
106
130
|
/**
|
|
107
131
|
* find .ipa file's icon path from json info
|
|
108
132
|
* @param info // json info parsed from .ipa file
|
|
109
|
-
*/
|
|
110
|
-
|
|
133
|
+
*/ const findIpaIconPath = (info)=>{
|
|
134
|
+
var _info_CFBundleIcons_CFBundlePrimaryIcon_CFBundleIconFiles, _info_CFBundleIcons_CFBundlePrimaryIcon, _info_CFBundleIcons, _info_CFBundleIconFiles;
|
|
135
|
+
if ((_info_CFBundleIcons = info.CFBundleIcons) == null ? void 0 : (_info_CFBundleIcons_CFBundlePrimaryIcon = _info_CFBundleIcons.CFBundlePrimaryIcon) == null ? void 0 : (_info_CFBundleIcons_CFBundlePrimaryIcon_CFBundleIconFiles = _info_CFBundleIcons_CFBundlePrimaryIcon.CFBundleIconFiles) == null ? void 0 : _info_CFBundleIcons_CFBundlePrimaryIcon_CFBundleIconFiles.length) {
|
|
111
136
|
return info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles[info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles.length - 1];
|
|
112
|
-
}
|
|
137
|
+
}
|
|
138
|
+
if ((_info_CFBundleIconFiles = info.CFBundleIconFiles) == null ? void 0 : _info_CFBundleIconFiles.length) {
|
|
113
139
|
return info.CFBundleIconFiles[info.CFBundleIconFiles.length - 1];
|
|
114
|
-
} else {
|
|
115
|
-
return '.app/Icon.png';
|
|
116
140
|
}
|
|
117
|
-
|
|
141
|
+
return '.app/Icon.png';
|
|
142
|
+
};
|
|
118
143
|
/**
|
|
119
144
|
* transform buffer to base64
|
|
120
145
|
* @param {Buffer} buffer
|
|
121
|
-
*/
|
|
122
|
-
|
|
123
|
-
}
|
|
146
|
+
*/ const getBase64FromBuffer = (buffer)=>{
|
|
147
|
+
const base64 = typeof buffer === 'string' ? buffer : buffer.toString('base64');
|
|
148
|
+
return `data:image/png;base64,${base64}`;
|
|
149
|
+
};
|
|
124
150
|
/**
|
|
125
151
|
* 去除unicode空字符
|
|
126
152
|
* @param {String} str
|
|
127
|
-
*/
|
|
128
|
-
if (typeof
|
|
129
|
-
//
|
|
130
|
-
|
|
153
|
+
*/ const decodeNullUnicode = (value)=>{
|
|
154
|
+
if (typeof value === 'string') {
|
|
155
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: <explanation>
|
|
156
|
+
return value.replace(/\u0000/g, '');
|
|
131
157
|
}
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
module.exports = {
|
|
135
|
-
isArray,
|
|
136
|
-
isObject,
|
|
137
|
-
isPrimitive,
|
|
138
|
-
isBrowser,
|
|
139
|
-
mapInfoResource,
|
|
140
|
-
findApkIconPath,
|
|
141
|
-
findIpaIconPath,
|
|
142
|
-
getBase64FromBuffer,
|
|
143
|
-
decodeNullUnicode
|
|
158
|
+
return value;
|
|
144
159
|
};
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
// From https://github.com/openstf/adbkit-apkreader
|
|
2
2
|
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "BinaryXmlParser", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return BinaryXmlParser;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
3
12
|
const NodeType = {
|
|
4
13
|
ELEMENT_NODE: 1,
|
|
5
14
|
ATTRIBUTE_NODE: 2,
|
|
@@ -134,7 +143,8 @@ class BinaryXmlParser {
|
|
|
134
143
|
rawUnit: null
|
|
135
144
|
};
|
|
136
145
|
const value = this.readU32();
|
|
137
|
-
|
|
146
|
+
var _dimension_value;
|
|
147
|
+
const unit = ((_dimension_value = dimension.value) != null ? _dimension_value : 0) & 0xff;
|
|
138
148
|
dimension.value = value >> 8;
|
|
139
149
|
dimension.rawUnit = unit;
|
|
140
150
|
switch(unit){
|
|
@@ -184,13 +194,13 @@ class BinaryXmlParser {
|
|
|
184
194
|
}
|
|
185
195
|
readHex24() {
|
|
186
196
|
this.debug && console.group('readHex24');
|
|
187
|
-
|
|
197
|
+
const val = (this.readU32() & 0xffffff).toString(16);
|
|
188
198
|
this.debug && console.groupEnd();
|
|
189
199
|
return val;
|
|
190
200
|
}
|
|
191
201
|
readHex32() {
|
|
192
202
|
this.debug && console.group('readHex32');
|
|
193
|
-
|
|
203
|
+
const val = this.readU32().toString(16);
|
|
194
204
|
this.debug && console.groupEnd();
|
|
195
205
|
return val;
|
|
196
206
|
}
|
|
@@ -205,7 +215,6 @@ class BinaryXmlParser {
|
|
|
205
215
|
let size = this.readU16();
|
|
206
216
|
/* const zero = */ this.readU8();
|
|
207
217
|
const dataType = this.readU8();
|
|
208
|
-
// Yes, there has been a real world APK where the size is malformed.
|
|
209
218
|
if (size === 0) {
|
|
210
219
|
size = 8;
|
|
211
220
|
}
|
|
@@ -220,15 +229,19 @@ class BinaryXmlParser {
|
|
|
220
229
|
typedValue.type = 'int_hex';
|
|
221
230
|
break;
|
|
222
231
|
case TypedValue.TYPE_STRING:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
{
|
|
233
|
+
const ref = this.readS32();
|
|
234
|
+
typedValue.value = ref > 0 ? this.strings[ref] : '';
|
|
235
|
+
typedValue.type = 'string';
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
227
238
|
case TypedValue.TYPE_REFERENCE:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
239
|
+
{
|
|
240
|
+
const id = this.readU32();
|
|
241
|
+
typedValue.value = `resourceId:0x${id.toString(16)}`;
|
|
242
|
+
typedValue.type = 'reference';
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
232
245
|
case TypedValue.TYPE_INT_BOOLEAN:
|
|
233
246
|
typedValue.value = this.readS32() !== 0;
|
|
234
247
|
typedValue.type = 'boolean';
|
|
@@ -270,7 +283,6 @@ class BinaryXmlParser {
|
|
|
270
283
|
typedValue.type = 'unknown';
|
|
271
284
|
}
|
|
272
285
|
}
|
|
273
|
-
// Ensure we consume the whole value
|
|
274
286
|
const end = start + size;
|
|
275
287
|
if (this.cursor !== end) {
|
|
276
288
|
const type = dataType.toString(16);
|
|
@@ -293,30 +305,34 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
293
305
|
this.debug && console.group('readString', encoding);
|
|
294
306
|
switch(encoding){
|
|
295
307
|
case 'utf-8':
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
308
|
+
{
|
|
309
|
+
const stringLength = this.readLength8();
|
|
310
|
+
this.debug && console.debug('stringLength:', stringLength);
|
|
311
|
+
const byteLength = this.readLength8();
|
|
312
|
+
this.debug && console.debug('byteLength:', byteLength);
|
|
313
|
+
const value = this.buffer.toString(encoding, this.cursor, this.cursor += byteLength);
|
|
314
|
+
this.debug && console.debug('value:', value);
|
|
315
|
+
this.debug && console.groupEnd();
|
|
316
|
+
return value;
|
|
317
|
+
}
|
|
304
318
|
case 'ucs2':
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
319
|
+
{
|
|
320
|
+
const stringLength = this.readLength16();
|
|
321
|
+
this.debug && console.debug('stringLength:', stringLength);
|
|
322
|
+
const byteLength = stringLength * 2;
|
|
323
|
+
this.debug && console.debug('byteLength:', byteLength);
|
|
324
|
+
const value = this.buffer.toString(encoding, this.cursor, this.cursor += byteLength);
|
|
325
|
+
this.debug && console.debug('value:', value);
|
|
326
|
+
this.debug && console.groupEnd();
|
|
327
|
+
return value;
|
|
328
|
+
}
|
|
313
329
|
default:
|
|
314
330
|
throw new Error(`Unsupported encoding '${encoding}'`);
|
|
315
331
|
}
|
|
316
332
|
}
|
|
317
333
|
readChunkHeader() {
|
|
318
334
|
this.debug && console.group('readChunkHeader');
|
|
319
|
-
|
|
335
|
+
const header = {
|
|
320
336
|
startOffset: this.cursor,
|
|
321
337
|
chunkType: this.readU16(),
|
|
322
338
|
headerSize: this.readU16(),
|
|
@@ -361,7 +377,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
361
377
|
this.cursor = stringsStart + offsets[i];
|
|
362
378
|
this.strings.push(this.readString(encoding));
|
|
363
379
|
}
|
|
364
|
-
// Skip styles
|
|
365
380
|
this.cursor = header.startOffset + header.chunkSize;
|
|
366
381
|
this.debug && console.groupEnd();
|
|
367
382
|
return null;
|
|
@@ -381,11 +396,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
381
396
|
/* const commentRef = */ this.readU32();
|
|
382
397
|
/* const prefixRef = */ this.readS32();
|
|
383
398
|
/* const uriRef = */ this.readS32();
|
|
384
|
-
// We don't currently care about the values, but they could
|
|
385
|
-
// be accessed like so:
|
|
386
|
-
//
|
|
387
|
-
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
|
|
388
|
-
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
|
|
389
399
|
this.debug && console.groupEnd();
|
|
390
400
|
return null;
|
|
391
401
|
}
|
|
@@ -395,11 +405,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
395
405
|
/* const commentRef = */ this.readU32();
|
|
396
406
|
/* const prefixRef = */ this.readS32();
|
|
397
407
|
/* const uriRef = */ this.readS32();
|
|
398
|
-
// We don't currently care about the values, but they could
|
|
399
|
-
// be accessed like so:
|
|
400
|
-
//
|
|
401
|
-
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
|
|
402
|
-
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
|
|
403
408
|
this.debug && console.groupEnd();
|
|
404
409
|
return null;
|
|
405
410
|
}
|
|
@@ -457,10 +462,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
457
462
|
}
|
|
458
463
|
attr.nodeName = attr.name = this.strings[nameRef];
|
|
459
464
|
if (valueRef > 0) {
|
|
460
|
-
// some apk have versionName with special characters
|
|
461
465
|
if (attr.name === 'versionName') {
|
|
462
|
-
// only keep printable characters
|
|
463
|
-
// https://www.ascii-code.com/characters/printable-characters
|
|
464
466
|
this.strings[valueRef] = this.strings[valueRef].replace(/[^\x21-\x7E]/g, '');
|
|
465
467
|
}
|
|
466
468
|
attr.value = this.strings[valueRef];
|
|
@@ -524,19 +526,19 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
524
526
|
this.readResourceMap(header);
|
|
525
527
|
break;
|
|
526
528
|
case ChunkType.XML_START_NAMESPACE:
|
|
527
|
-
this.readXmlNamespaceStart(
|
|
529
|
+
this.readXmlNamespaceStart();
|
|
528
530
|
break;
|
|
529
531
|
case ChunkType.XML_END_NAMESPACE:
|
|
530
|
-
this.readXmlNamespaceEnd(
|
|
532
|
+
this.readXmlNamespaceEnd();
|
|
531
533
|
break;
|
|
532
534
|
case ChunkType.XML_START_ELEMENT:
|
|
533
|
-
this.readXmlElementStart(
|
|
535
|
+
this.readXmlElementStart();
|
|
534
536
|
break;
|
|
535
537
|
case ChunkType.XML_END_ELEMENT:
|
|
536
|
-
this.readXmlElementEnd(
|
|
538
|
+
this.readXmlElementEnd();
|
|
537
539
|
break;
|
|
538
540
|
case ChunkType.XML_CDATA:
|
|
539
|
-
this.readXmlCData(
|
|
541
|
+
this.readXmlCData();
|
|
540
542
|
break;
|
|
541
543
|
case ChunkType.NULL:
|
|
542
544
|
this.readNull(header);
|
|
@@ -544,7 +546,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
544
546
|
default:
|
|
545
547
|
throw new Error(`Unsupported chunk type '${header.chunkType}'`);
|
|
546
548
|
}
|
|
547
|
-
// Ensure we consume the whole chunk
|
|
548
549
|
const end = start + header.chunkSize;
|
|
549
550
|
if (this.cursor !== end) {
|
|
550
551
|
const diff = end - this.cursor;
|
|
@@ -560,6 +561,12 @@ supposed to end at offset ${end}. Ignoring the rest of the chunk.`);
|
|
|
560
561
|
return this.document;
|
|
561
562
|
}
|
|
562
563
|
constructor(buffer, options = {}){
|
|
564
|
+
this.cursor = 0;
|
|
565
|
+
this.strings = [];
|
|
566
|
+
this.resources = [];
|
|
567
|
+
this.document = null;
|
|
568
|
+
this.parent = null;
|
|
569
|
+
this.stack = [];
|
|
563
570
|
this.buffer = buffer;
|
|
564
571
|
this.cursor = 0;
|
|
565
572
|
this.strings = [];
|
|
@@ -570,4 +577,3 @@ supposed to end at offset ${end}. Ignoring the rest of the chunk.`);
|
|
|
570
577
|
this.debug = options.debug || false;
|
|
571
578
|
}
|
|
572
579
|
}
|
|
573
|
-
module.exports = BinaryXmlParser;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// From https://github.com/openstf/adbkit-apkreader
|
|
2
2
|
"use strict";
|
|
3
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "ManifestParser", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return ManifestParser;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const _binary = require("./binary");
|
|
4
13
|
const INTENT_MAIN = 'android.intent.action.MAIN';
|
|
5
14
|
const CATEGORY_LAUNCHER = 'android.intent.category.LAUNCHER';
|
|
6
15
|
class ManifestParser {
|
|
@@ -14,35 +23,35 @@ class ManifestParser {
|
|
|
14
23
|
parseIntents(element, target) {
|
|
15
24
|
target.intentFilters = [];
|
|
16
25
|
target.metaData = [];
|
|
17
|
-
|
|
18
|
-
switch(
|
|
26
|
+
for (const child of element.childNodes){
|
|
27
|
+
switch(child.nodeName){
|
|
19
28
|
case 'intent-filter':
|
|
20
29
|
{
|
|
21
|
-
const intentFilter = this.collapseAttributes(
|
|
30
|
+
const intentFilter = this.collapseAttributes(child);
|
|
22
31
|
intentFilter.actions = [];
|
|
23
32
|
intentFilter.categories = [];
|
|
24
33
|
intentFilter.data = [];
|
|
25
|
-
|
|
26
|
-
switch(
|
|
34
|
+
for (const item of child.childNodes){
|
|
35
|
+
switch(item.nodeName){
|
|
27
36
|
case 'action':
|
|
28
|
-
intentFilter.actions.push(this.collapseAttributes(
|
|
37
|
+
intentFilter.actions.push(this.collapseAttributes(item));
|
|
29
38
|
break;
|
|
30
39
|
case 'category':
|
|
31
|
-
intentFilter.categories.push(this.collapseAttributes(
|
|
40
|
+
intentFilter.categories.push(this.collapseAttributes(item));
|
|
32
41
|
break;
|
|
33
42
|
case 'data':
|
|
34
|
-
intentFilter.data.push(this.collapseAttributes(
|
|
43
|
+
intentFilter.data.push(this.collapseAttributes(item));
|
|
35
44
|
break;
|
|
36
45
|
}
|
|
37
|
-
}
|
|
46
|
+
}
|
|
38
47
|
target.intentFilters.push(intentFilter);
|
|
39
48
|
break;
|
|
40
49
|
}
|
|
41
50
|
case 'meta-data':
|
|
42
|
-
target.metaData.push(this.collapseAttributes(
|
|
51
|
+
target.metaData.push(this.collapseAttributes(child));
|
|
43
52
|
break;
|
|
44
53
|
}
|
|
45
|
-
}
|
|
54
|
+
}
|
|
46
55
|
}
|
|
47
56
|
parseApplication(element) {
|
|
48
57
|
const app = this.collapseAttributes(element);
|
|
@@ -54,12 +63,12 @@ class ManifestParser {
|
|
|
54
63
|
app.providers = [];
|
|
55
64
|
app.usesLibraries = [];
|
|
56
65
|
app.metaData = [];
|
|
57
|
-
element.childNodes
|
|
58
|
-
switch(
|
|
66
|
+
for (const child of element.childNodes){
|
|
67
|
+
switch(child.nodeName){
|
|
59
68
|
case 'activity':
|
|
60
69
|
{
|
|
61
|
-
const activity = this.collapseAttributes(
|
|
62
|
-
this.parseIntents(
|
|
70
|
+
const activity = this.collapseAttributes(child);
|
|
71
|
+
this.parseIntents(child, activity);
|
|
63
72
|
app.activities.push(activity);
|
|
64
73
|
if (this.isLauncherActivity(activity)) {
|
|
65
74
|
app.launcherActivities.push(activity);
|
|
@@ -68,8 +77,8 @@ class ManifestParser {
|
|
|
68
77
|
}
|
|
69
78
|
case 'activity-alias':
|
|
70
79
|
{
|
|
71
|
-
const activityAlias = this.collapseAttributes(
|
|
72
|
-
this.parseIntents(
|
|
80
|
+
const activityAlias = this.collapseAttributes(child);
|
|
81
|
+
this.parseIntents(child, activityAlias);
|
|
73
82
|
app.activityAliases.push(activityAlias);
|
|
74
83
|
if (this.isLauncherActivity(activityAlias)) {
|
|
75
84
|
app.launcherActivities.push(activityAlias);
|
|
@@ -78,48 +87,48 @@ class ManifestParser {
|
|
|
78
87
|
}
|
|
79
88
|
case 'service':
|
|
80
89
|
{
|
|
81
|
-
const service = this.collapseAttributes(
|
|
82
|
-
this.parseIntents(
|
|
90
|
+
const service = this.collapseAttributes(child);
|
|
91
|
+
this.parseIntents(child, service);
|
|
83
92
|
app.services.push(service);
|
|
84
93
|
break;
|
|
85
94
|
}
|
|
86
95
|
case 'receiver':
|
|
87
96
|
{
|
|
88
|
-
const receiver = this.collapseAttributes(
|
|
89
|
-
this.parseIntents(
|
|
97
|
+
const receiver = this.collapseAttributes(child);
|
|
98
|
+
this.parseIntents(child, receiver);
|
|
90
99
|
app.receivers.push(receiver);
|
|
91
100
|
break;
|
|
92
101
|
}
|
|
93
102
|
case 'provider':
|
|
94
103
|
{
|
|
95
|
-
const provider = this.collapseAttributes(
|
|
104
|
+
const provider = this.collapseAttributes(child);
|
|
96
105
|
provider.grantUriPermissions = [];
|
|
97
106
|
provider.metaData = [];
|
|
98
107
|
provider.pathPermissions = [];
|
|
99
|
-
|
|
100
|
-
switch(
|
|
108
|
+
for (const item of child.childNodes){
|
|
109
|
+
switch(item.nodeName){
|
|
101
110
|
case 'grant-uri-permission':
|
|
102
|
-
provider.grantUriPermissions.push(this.collapseAttributes(
|
|
111
|
+
provider.grantUriPermissions.push(this.collapseAttributes(item));
|
|
103
112
|
break;
|
|
104
113
|
case 'meta-data':
|
|
105
|
-
provider.metaData.push(this.collapseAttributes(
|
|
114
|
+
provider.metaData.push(this.collapseAttributes(item));
|
|
106
115
|
break;
|
|
107
116
|
case 'path-permission':
|
|
108
|
-
provider.pathPermissions.push(this.collapseAttributes(
|
|
117
|
+
provider.pathPermissions.push(this.collapseAttributes(item));
|
|
109
118
|
break;
|
|
110
119
|
}
|
|
111
|
-
}
|
|
120
|
+
}
|
|
112
121
|
app.providers.push(provider);
|
|
113
122
|
break;
|
|
114
123
|
}
|
|
115
124
|
case 'uses-library':
|
|
116
|
-
app.usesLibraries.push(this.collapseAttributes(
|
|
125
|
+
app.usesLibraries.push(this.collapseAttributes(child));
|
|
117
126
|
break;
|
|
118
127
|
case 'meta-data':
|
|
119
|
-
app.metaData.push(this.collapseAttributes(
|
|
128
|
+
app.metaData.push(this.collapseAttributes(child));
|
|
120
129
|
break;
|
|
121
130
|
}
|
|
122
|
-
}
|
|
131
|
+
}
|
|
123
132
|
return app;
|
|
124
133
|
}
|
|
125
134
|
isLauncherActivity(activity) {
|
|
@@ -147,7 +156,7 @@ class ManifestParser {
|
|
|
147
156
|
manifest.compatibleScreens = [];
|
|
148
157
|
manifest.supportsGlTextures = [];
|
|
149
158
|
manifest.application = Object.create(null);
|
|
150
|
-
document.childNodes
|
|
159
|
+
for (const element of document.childNodes){
|
|
151
160
|
switch(element.nodeName){
|
|
152
161
|
case 'uses-permission':
|
|
153
162
|
manifest.usesPermissions.push(this.collapseAttributes(element));
|
|
@@ -180,9 +189,9 @@ class ManifestParser {
|
|
|
180
189
|
manifest.supportsScreens = this.collapseAttributes(element);
|
|
181
190
|
break;
|
|
182
191
|
case 'compatible-screens':
|
|
183
|
-
element.childNodes
|
|
184
|
-
|
|
185
|
-
}
|
|
192
|
+
for (const screen of element.childNodes){
|
|
193
|
+
manifest.compatibleScreens.push(this.collapseAttributes(screen));
|
|
194
|
+
}
|
|
186
195
|
break;
|
|
187
196
|
case 'supports-gl-texture':
|
|
188
197
|
manifest.supportsGlTextures.push(this.collapseAttributes(element));
|
|
@@ -191,12 +200,11 @@ class ManifestParser {
|
|
|
191
200
|
manifest.application = this.parseApplication(element);
|
|
192
201
|
break;
|
|
193
202
|
}
|
|
194
|
-
}
|
|
203
|
+
}
|
|
195
204
|
return manifest;
|
|
196
205
|
}
|
|
197
206
|
constructor(buffer, options = {}){
|
|
198
207
|
this.buffer = buffer;
|
|
199
|
-
this.xmlParser = new BinaryXmlParser(this.buffer, options);
|
|
208
|
+
this.xmlParser = new _binary.BinaryXmlParser(this.buffer, options);
|
|
200
209
|
}
|
|
201
210
|
}
|
|
202
|
-
module.exports = ManifestParser;
|