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
|
@@ -70,8 +70,21 @@ const TypedValue = {
|
|
|
70
70
|
TYPE_STRING: 0x00000003,
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
type BinaryXmlParserOptions = {
|
|
74
|
+
debug?: boolean;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export class BinaryXmlParser {
|
|
78
|
+
buffer: Buffer;
|
|
79
|
+
cursor = 0;
|
|
80
|
+
strings: string[] = [];
|
|
81
|
+
resources: number[] = [];
|
|
82
|
+
document: any = null;
|
|
83
|
+
parent: any = null;
|
|
84
|
+
stack: any[] = [];
|
|
85
|
+
debug: boolean;
|
|
86
|
+
|
|
87
|
+
constructor(buffer: Buffer, options: BinaryXmlParserOptions = {}) {
|
|
75
88
|
this.buffer = buffer;
|
|
76
89
|
this.cursor = 0;
|
|
77
90
|
this.strings = [];
|
|
@@ -149,14 +162,18 @@ class BinaryXmlParser {
|
|
|
149
162
|
readDimension() {
|
|
150
163
|
this.debug && console.group('readDimension');
|
|
151
164
|
|
|
152
|
-
const dimension
|
|
165
|
+
const dimension: {
|
|
166
|
+
value: number | null;
|
|
167
|
+
unit: string | null;
|
|
168
|
+
rawUnit: number | null;
|
|
169
|
+
} = {
|
|
153
170
|
value: null,
|
|
154
171
|
unit: null,
|
|
155
172
|
rawUnit: null,
|
|
156
173
|
};
|
|
157
174
|
|
|
158
175
|
const value = this.readU32();
|
|
159
|
-
const unit = dimension.value & 0xff;
|
|
176
|
+
const unit = (dimension.value ?? 0) & 0xff;
|
|
160
177
|
|
|
161
178
|
dimension.value = value >> 8;
|
|
162
179
|
dimension.rawUnit = unit;
|
|
@@ -190,7 +207,11 @@ class BinaryXmlParser {
|
|
|
190
207
|
readFraction() {
|
|
191
208
|
this.debug && console.group('readFraction');
|
|
192
209
|
|
|
193
|
-
const fraction
|
|
210
|
+
const fraction: {
|
|
211
|
+
value: number | null;
|
|
212
|
+
type: string | null;
|
|
213
|
+
rawType: number | null;
|
|
214
|
+
} = {
|
|
194
215
|
value: null,
|
|
195
216
|
type: null,
|
|
196
217
|
rawType: null,
|
|
@@ -218,14 +239,14 @@ class BinaryXmlParser {
|
|
|
218
239
|
|
|
219
240
|
readHex24() {
|
|
220
241
|
this.debug && console.group('readHex24');
|
|
221
|
-
|
|
242
|
+
const val = (this.readU32() & 0xffffff).toString(16);
|
|
222
243
|
this.debug && console.groupEnd();
|
|
223
244
|
return val;
|
|
224
245
|
}
|
|
225
246
|
|
|
226
247
|
readHex32() {
|
|
227
248
|
this.debug && console.group('readHex32');
|
|
228
|
-
|
|
249
|
+
const val = this.readU32().toString(16);
|
|
229
250
|
this.debug && console.groupEnd();
|
|
230
251
|
return val;
|
|
231
252
|
}
|
|
@@ -233,7 +254,11 @@ class BinaryXmlParser {
|
|
|
233
254
|
readTypedValue() {
|
|
234
255
|
this.debug && console.group('readTypedValue');
|
|
235
256
|
|
|
236
|
-
const typedValue
|
|
257
|
+
const typedValue: {
|
|
258
|
+
value: any;
|
|
259
|
+
type: string | null;
|
|
260
|
+
rawType: number | null;
|
|
261
|
+
} = {
|
|
237
262
|
value: null,
|
|
238
263
|
type: null,
|
|
239
264
|
rawType: null,
|
|
@@ -245,7 +270,6 @@ class BinaryXmlParser {
|
|
|
245
270
|
/* const zero = */ this.readU8();
|
|
246
271
|
const dataType = this.readU8();
|
|
247
272
|
|
|
248
|
-
// Yes, there has been a real world APK where the size is malformed.
|
|
249
273
|
if (size === 0) {
|
|
250
274
|
size = 8;
|
|
251
275
|
}
|
|
@@ -261,16 +285,18 @@ class BinaryXmlParser {
|
|
|
261
285
|
typedValue.value = this.readS32();
|
|
262
286
|
typedValue.type = 'int_hex';
|
|
263
287
|
break;
|
|
264
|
-
case TypedValue.TYPE_STRING:
|
|
265
|
-
|
|
288
|
+
case TypedValue.TYPE_STRING: {
|
|
289
|
+
const ref = this.readS32();
|
|
266
290
|
typedValue.value = ref > 0 ? this.strings[ref] : '';
|
|
267
291
|
typedValue.type = 'string';
|
|
268
292
|
break;
|
|
269
|
-
|
|
270
|
-
|
|
293
|
+
}
|
|
294
|
+
case TypedValue.TYPE_REFERENCE: {
|
|
295
|
+
const id = this.readU32();
|
|
271
296
|
typedValue.value = `resourceId:0x${id.toString(16)}`;
|
|
272
297
|
typedValue.type = 'reference';
|
|
273
298
|
break;
|
|
299
|
+
}
|
|
274
300
|
case TypedValue.TYPE_INT_BOOLEAN:
|
|
275
301
|
typedValue.value = this.readS32() !== 0;
|
|
276
302
|
typedValue.type = 'boolean';
|
|
@@ -314,7 +340,6 @@ class BinaryXmlParser {
|
|
|
314
340
|
}
|
|
315
341
|
}
|
|
316
342
|
|
|
317
|
-
// Ensure we consume the whole value
|
|
318
343
|
const end = start + size;
|
|
319
344
|
if (this.cursor !== end) {
|
|
320
345
|
const type = dataType.toString(16);
|
|
@@ -331,21 +356,21 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
331
356
|
}
|
|
332
357
|
|
|
333
358
|
// https://twitter.com/kawasima/status/427730289201139712
|
|
334
|
-
convertIntToFloat(int) {
|
|
359
|
+
convertIntToFloat(int: number) {
|
|
335
360
|
const buf = new ArrayBuffer(4);
|
|
336
361
|
new Int32Array(buf)[0] = int;
|
|
337
362
|
return new Float32Array(buf)[0];
|
|
338
363
|
}
|
|
339
364
|
|
|
340
|
-
readString(encoding) {
|
|
365
|
+
readString(encoding: string) {
|
|
341
366
|
this.debug && console.group('readString', encoding);
|
|
342
367
|
switch (encoding) {
|
|
343
|
-
case 'utf-8':
|
|
344
|
-
|
|
368
|
+
case 'utf-8': {
|
|
369
|
+
const stringLength = this.readLength8();
|
|
345
370
|
this.debug && console.debug('stringLength:', stringLength);
|
|
346
|
-
|
|
371
|
+
const byteLength = this.readLength8();
|
|
347
372
|
this.debug && console.debug('byteLength:', byteLength);
|
|
348
|
-
|
|
373
|
+
const value = this.buffer.toString(
|
|
349
374
|
encoding,
|
|
350
375
|
this.cursor,
|
|
351
376
|
(this.cursor += byteLength),
|
|
@@ -353,12 +378,13 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
353
378
|
this.debug && console.debug('value:', value);
|
|
354
379
|
this.debug && console.groupEnd();
|
|
355
380
|
return value;
|
|
356
|
-
|
|
357
|
-
|
|
381
|
+
}
|
|
382
|
+
case 'ucs2': {
|
|
383
|
+
const stringLength = this.readLength16();
|
|
358
384
|
this.debug && console.debug('stringLength:', stringLength);
|
|
359
|
-
byteLength = stringLength * 2;
|
|
385
|
+
const byteLength = stringLength * 2;
|
|
360
386
|
this.debug && console.debug('byteLength:', byteLength);
|
|
361
|
-
value = this.buffer.toString(
|
|
387
|
+
const value = this.buffer.toString(
|
|
362
388
|
encoding,
|
|
363
389
|
this.cursor,
|
|
364
390
|
(this.cursor += byteLength),
|
|
@@ -366,6 +392,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
366
392
|
this.debug && console.debug('value:', value);
|
|
367
393
|
this.debug && console.groupEnd();
|
|
368
394
|
return value;
|
|
395
|
+
}
|
|
369
396
|
default:
|
|
370
397
|
throw new Error(`Unsupported encoding '${encoding}'`);
|
|
371
398
|
}
|
|
@@ -373,7 +400,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
373
400
|
|
|
374
401
|
readChunkHeader() {
|
|
375
402
|
this.debug && console.group('readChunkHeader');
|
|
376
|
-
|
|
403
|
+
const header = {
|
|
377
404
|
startOffset: this.cursor,
|
|
378
405
|
chunkType: this.readU16(),
|
|
379
406
|
headerSize: this.readU16(),
|
|
@@ -387,7 +414,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
387
414
|
return header;
|
|
388
415
|
}
|
|
389
416
|
|
|
390
|
-
readStringPool(header) {
|
|
417
|
+
readStringPool(header: any) {
|
|
391
418
|
this.debug && console.group('readStringPool');
|
|
392
419
|
|
|
393
420
|
header.stringCount = this.readU32();
|
|
@@ -405,7 +432,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
405
432
|
throw new Error('Invalid string pool header');
|
|
406
433
|
}
|
|
407
434
|
|
|
408
|
-
const offsets = [];
|
|
435
|
+
const offsets: number[] = [];
|
|
409
436
|
for (let i = 0, l = header.stringCount; i < l; ++i) {
|
|
410
437
|
this.debug && console.debug('offset:', i);
|
|
411
438
|
offsets.push(this.readU32());
|
|
@@ -426,7 +453,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
426
453
|
this.strings.push(this.readString(encoding));
|
|
427
454
|
}
|
|
428
455
|
|
|
429
|
-
// Skip styles
|
|
430
456
|
this.cursor = header.startOffset + header.chunkSize;
|
|
431
457
|
|
|
432
458
|
this.debug && console.groupEnd();
|
|
@@ -434,7 +460,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
434
460
|
return null;
|
|
435
461
|
}
|
|
436
462
|
|
|
437
|
-
readResourceMap(header) {
|
|
463
|
+
readResourceMap(header: any) {
|
|
438
464
|
this.debug && console.group('readResourceMap');
|
|
439
465
|
const count = Math.floor((header.chunkSize - header.headerSize) / 4);
|
|
440
466
|
for (let i = 0; i < count; ++i) {
|
|
@@ -444,7 +470,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
444
470
|
return null;
|
|
445
471
|
}
|
|
446
472
|
|
|
447
|
-
readXmlNamespaceStart(
|
|
473
|
+
readXmlNamespaceStart() {
|
|
448
474
|
this.debug && console.group('readXmlNamespaceStart');
|
|
449
475
|
|
|
450
476
|
/* const line = */ this.readU32();
|
|
@@ -452,18 +478,12 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
452
478
|
/* const prefixRef = */ this.readS32();
|
|
453
479
|
/* const uriRef = */ this.readS32();
|
|
454
480
|
|
|
455
|
-
// We don't currently care about the values, but they could
|
|
456
|
-
// be accessed like so:
|
|
457
|
-
//
|
|
458
|
-
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
|
|
459
|
-
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
|
|
460
|
-
|
|
461
481
|
this.debug && console.groupEnd();
|
|
462
482
|
|
|
463
483
|
return null;
|
|
464
484
|
}
|
|
465
485
|
|
|
466
|
-
readXmlNamespaceEnd(
|
|
486
|
+
readXmlNamespaceEnd() {
|
|
467
487
|
this.debug && console.group('readXmlNamespaceEnd');
|
|
468
488
|
|
|
469
489
|
/* const line = */ this.readU32();
|
|
@@ -471,21 +491,15 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
471
491
|
/* const prefixRef = */ this.readS32();
|
|
472
492
|
/* const uriRef = */ this.readS32();
|
|
473
493
|
|
|
474
|
-
// We don't currently care about the values, but they could
|
|
475
|
-
// be accessed like so:
|
|
476
|
-
//
|
|
477
|
-
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
|
|
478
|
-
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
|
|
479
|
-
|
|
480
494
|
this.debug && console.groupEnd();
|
|
481
495
|
|
|
482
496
|
return null;
|
|
483
497
|
}
|
|
484
498
|
|
|
485
|
-
readXmlElementStart(
|
|
499
|
+
readXmlElementStart() {
|
|
486
500
|
this.debug && console.group('readXmlElementStart');
|
|
487
501
|
|
|
488
|
-
const node = {
|
|
502
|
+
const node: any = {
|
|
489
503
|
namespaceURI: null,
|
|
490
504
|
nodeType: NodeType.ELEMENT_NODE,
|
|
491
505
|
nodeName: null,
|
|
@@ -532,7 +546,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
532
546
|
readXmlAttribute() {
|
|
533
547
|
this.debug && console.group('readXmlAttribute');
|
|
534
548
|
|
|
535
|
-
const attr = {
|
|
549
|
+
const attr: any = {
|
|
536
550
|
namespaceURI: null,
|
|
537
551
|
nodeType: NodeType.ATTRIBUTE_NODE,
|
|
538
552
|
nodeName: null,
|
|
@@ -552,10 +566,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
552
566
|
attr.nodeName = attr.name = this.strings[nameRef];
|
|
553
567
|
|
|
554
568
|
if (valueRef > 0) {
|
|
555
|
-
// some apk have versionName with special characters
|
|
556
569
|
if (attr.name === 'versionName') {
|
|
557
|
-
// only keep printable characters
|
|
558
|
-
// https://www.ascii-code.com/characters/printable-characters
|
|
559
570
|
this.strings[valueRef] = this.strings[valueRef].replace(
|
|
560
571
|
/[^\x21-\x7E]/g,
|
|
561
572
|
'',
|
|
@@ -571,7 +582,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
571
582
|
return attr;
|
|
572
583
|
}
|
|
573
584
|
|
|
574
|
-
readXmlElementEnd(
|
|
585
|
+
readXmlElementEnd() {
|
|
575
586
|
this.debug && console.group('readXmlCData');
|
|
576
587
|
|
|
577
588
|
/* const line = */ this.readU32();
|
|
@@ -587,10 +598,10 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
587
598
|
return null;
|
|
588
599
|
}
|
|
589
600
|
|
|
590
|
-
readXmlCData(
|
|
601
|
+
readXmlCData() {
|
|
591
602
|
this.debug && console.group('readXmlCData');
|
|
592
603
|
|
|
593
|
-
const cdata = {
|
|
604
|
+
const cdata: any = {
|
|
594
605
|
namespaceURI: null,
|
|
595
606
|
nodeType: NodeType.CDATA_SECTION_NODE,
|
|
596
607
|
nodeName: '#cdata',
|
|
@@ -615,7 +626,7 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
615
626
|
return cdata;
|
|
616
627
|
}
|
|
617
628
|
|
|
618
|
-
readNull(header) {
|
|
629
|
+
readNull(header: any) {
|
|
619
630
|
this.debug && console.group('readNull');
|
|
620
631
|
this.cursor += header.chunkSize - header.headerSize;
|
|
621
632
|
this.debug && console.groupEnd();
|
|
@@ -642,19 +653,19 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
642
653
|
this.readResourceMap(header);
|
|
643
654
|
break;
|
|
644
655
|
case ChunkType.XML_START_NAMESPACE:
|
|
645
|
-
this.readXmlNamespaceStart(
|
|
656
|
+
this.readXmlNamespaceStart();
|
|
646
657
|
break;
|
|
647
658
|
case ChunkType.XML_END_NAMESPACE:
|
|
648
|
-
this.readXmlNamespaceEnd(
|
|
659
|
+
this.readXmlNamespaceEnd();
|
|
649
660
|
break;
|
|
650
661
|
case ChunkType.XML_START_ELEMENT:
|
|
651
|
-
this.readXmlElementStart(
|
|
662
|
+
this.readXmlElementStart();
|
|
652
663
|
break;
|
|
653
664
|
case ChunkType.XML_END_ELEMENT:
|
|
654
|
-
this.readXmlElementEnd(
|
|
665
|
+
this.readXmlElementEnd();
|
|
655
666
|
break;
|
|
656
667
|
case ChunkType.XML_CDATA:
|
|
657
|
-
this.readXmlCData(
|
|
668
|
+
this.readXmlCData();
|
|
658
669
|
break;
|
|
659
670
|
case ChunkType.NULL:
|
|
660
671
|
this.readNull(header);
|
|
@@ -663,7 +674,6 @@ and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
|
|
|
663
674
|
throw new Error(`Unsupported chunk type '${header.chunkType}'`);
|
|
664
675
|
}
|
|
665
676
|
|
|
666
|
-
// Ensure we consume the whole chunk
|
|
667
677
|
const end = start + header.chunkSize;
|
|
668
678
|
if (this.cursor !== end) {
|
|
669
679
|
const diff = end - this.cursor;
|
|
@@ -682,5 +692,3 @@ supposed to end at offset ${end}. Ignoring the rest of the chunk.`);
|
|
|
682
692
|
return this.document;
|
|
683
693
|
}
|
|
684
694
|
}
|
|
685
|
-
|
|
686
|
-
module.exports = BinaryXmlParser;
|
|
@@ -1,61 +1,64 @@
|
|
|
1
1
|
// From https://github.com/openstf/adbkit-apkreader
|
|
2
|
-
|
|
2
|
+
import { BinaryXmlParser } from './binary';
|
|
3
3
|
|
|
4
4
|
const INTENT_MAIN = 'android.intent.action.MAIN';
|
|
5
5
|
const CATEGORY_LAUNCHER = 'android.intent.category.LAUNCHER';
|
|
6
6
|
|
|
7
|
-
class ManifestParser {
|
|
8
|
-
|
|
7
|
+
export class ManifestParser {
|
|
8
|
+
private buffer: Buffer;
|
|
9
|
+
private xmlParser: BinaryXmlParser;
|
|
10
|
+
|
|
11
|
+
constructor(buffer: Buffer, options: Record<string, any> = {}) {
|
|
9
12
|
this.buffer = buffer;
|
|
10
13
|
this.xmlParser = new BinaryXmlParser(this.buffer, options);
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
collapseAttributes(element) {
|
|
14
|
-
const collapsed = Object.create(null);
|
|
16
|
+
private collapseAttributes(element: any) {
|
|
17
|
+
const collapsed: Record<string, any> = Object.create(null);
|
|
15
18
|
for (const attr of Array.from(element.attributes)) {
|
|
16
19
|
collapsed[attr.name] = attr.typedValue.value;
|
|
17
20
|
}
|
|
18
21
|
return collapsed;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
parseIntents(element, target) {
|
|
24
|
+
private parseIntents(element: any, target: any) {
|
|
22
25
|
target.intentFilters = [];
|
|
23
26
|
target.metaData = [];
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
switch (
|
|
28
|
+
for (const child of element.childNodes) {
|
|
29
|
+
switch (child.nodeName) {
|
|
27
30
|
case 'intent-filter': {
|
|
28
|
-
const intentFilter = this.collapseAttributes(
|
|
31
|
+
const intentFilter = this.collapseAttributes(child);
|
|
29
32
|
|
|
30
33
|
intentFilter.actions = [];
|
|
31
34
|
intentFilter.categories = [];
|
|
32
35
|
intentFilter.data = [];
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
switch (
|
|
37
|
+
for (const item of child.childNodes) {
|
|
38
|
+
switch (item.nodeName) {
|
|
36
39
|
case 'action':
|
|
37
|
-
intentFilter.actions.push(this.collapseAttributes(
|
|
40
|
+
intentFilter.actions.push(this.collapseAttributes(item));
|
|
38
41
|
break;
|
|
39
42
|
case 'category':
|
|
40
|
-
intentFilter.categories.push(this.collapseAttributes(
|
|
43
|
+
intentFilter.categories.push(this.collapseAttributes(item));
|
|
41
44
|
break;
|
|
42
45
|
case 'data':
|
|
43
|
-
intentFilter.data.push(this.collapseAttributes(
|
|
46
|
+
intentFilter.data.push(this.collapseAttributes(item));
|
|
44
47
|
break;
|
|
45
48
|
}
|
|
46
|
-
}
|
|
49
|
+
}
|
|
47
50
|
|
|
48
51
|
target.intentFilters.push(intentFilter);
|
|
49
52
|
break;
|
|
50
53
|
}
|
|
51
54
|
case 'meta-data':
|
|
52
|
-
target.metaData.push(this.collapseAttributes(
|
|
55
|
+
target.metaData.push(this.collapseAttributes(child));
|
|
53
56
|
break;
|
|
54
57
|
}
|
|
55
|
-
}
|
|
58
|
+
}
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
parseApplication(element) {
|
|
61
|
+
private parseApplication(element: any) {
|
|
59
62
|
const app = this.collapseAttributes(element);
|
|
60
63
|
|
|
61
64
|
app.activities = [];
|
|
@@ -67,11 +70,11 @@ class ManifestParser {
|
|
|
67
70
|
app.usesLibraries = [];
|
|
68
71
|
app.metaData = [];
|
|
69
72
|
|
|
70
|
-
element.childNodes
|
|
71
|
-
switch (
|
|
73
|
+
for (const child of element.childNodes) {
|
|
74
|
+
switch (child.nodeName) {
|
|
72
75
|
case 'activity': {
|
|
73
|
-
const activity = this.collapseAttributes(
|
|
74
|
-
this.parseIntents(
|
|
76
|
+
const activity = this.collapseAttributes(child);
|
|
77
|
+
this.parseIntents(child, activity);
|
|
75
78
|
app.activities.push(activity);
|
|
76
79
|
if (this.isLauncherActivity(activity)) {
|
|
77
80
|
app.launcherActivities.push(activity);
|
|
@@ -79,8 +82,8 @@ class ManifestParser {
|
|
|
79
82
|
break;
|
|
80
83
|
}
|
|
81
84
|
case 'activity-alias': {
|
|
82
|
-
const activityAlias = this.collapseAttributes(
|
|
83
|
-
this.parseIntents(
|
|
85
|
+
const activityAlias = this.collapseAttributes(child);
|
|
86
|
+
this.parseIntents(child, activityAlias);
|
|
84
87
|
app.activityAliases.push(activityAlias);
|
|
85
88
|
if (this.isLauncherActivity(activityAlias)) {
|
|
86
89
|
app.launcherActivities.push(activityAlias);
|
|
@@ -88,65 +91,65 @@ class ManifestParser {
|
|
|
88
91
|
break;
|
|
89
92
|
}
|
|
90
93
|
case 'service': {
|
|
91
|
-
const service = this.collapseAttributes(
|
|
92
|
-
this.parseIntents(
|
|
94
|
+
const service = this.collapseAttributes(child);
|
|
95
|
+
this.parseIntents(child, service);
|
|
93
96
|
app.services.push(service);
|
|
94
97
|
break;
|
|
95
98
|
}
|
|
96
99
|
case 'receiver': {
|
|
97
|
-
const receiver = this.collapseAttributes(
|
|
98
|
-
this.parseIntents(
|
|
100
|
+
const receiver = this.collapseAttributes(child);
|
|
101
|
+
this.parseIntents(child, receiver);
|
|
99
102
|
app.receivers.push(receiver);
|
|
100
103
|
break;
|
|
101
104
|
}
|
|
102
105
|
case 'provider': {
|
|
103
|
-
const provider = this.collapseAttributes(
|
|
106
|
+
const provider = this.collapseAttributes(child);
|
|
104
107
|
|
|
105
108
|
provider.grantUriPermissions = [];
|
|
106
109
|
provider.metaData = [];
|
|
107
110
|
provider.pathPermissions = [];
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
switch (
|
|
112
|
+
for (const item of child.childNodes) {
|
|
113
|
+
switch (item.nodeName) {
|
|
111
114
|
case 'grant-uri-permission':
|
|
112
115
|
provider.grantUriPermissions.push(
|
|
113
|
-
this.collapseAttributes(
|
|
116
|
+
this.collapseAttributes(item),
|
|
114
117
|
);
|
|
115
118
|
break;
|
|
116
119
|
case 'meta-data':
|
|
117
|
-
provider.metaData.push(this.collapseAttributes(
|
|
120
|
+
provider.metaData.push(this.collapseAttributes(item));
|
|
118
121
|
break;
|
|
119
122
|
case 'path-permission':
|
|
120
|
-
provider.pathPermissions.push(this.collapseAttributes(
|
|
123
|
+
provider.pathPermissions.push(this.collapseAttributes(item));
|
|
121
124
|
break;
|
|
122
125
|
}
|
|
123
|
-
}
|
|
126
|
+
}
|
|
124
127
|
|
|
125
128
|
app.providers.push(provider);
|
|
126
129
|
break;
|
|
127
130
|
}
|
|
128
131
|
case 'uses-library':
|
|
129
|
-
app.usesLibraries.push(this.collapseAttributes(
|
|
132
|
+
app.usesLibraries.push(this.collapseAttributes(child));
|
|
130
133
|
break;
|
|
131
134
|
case 'meta-data':
|
|
132
|
-
app.metaData.push(this.collapseAttributes(
|
|
135
|
+
app.metaData.push(this.collapseAttributes(child));
|
|
133
136
|
break;
|
|
134
137
|
}
|
|
135
|
-
}
|
|
138
|
+
}
|
|
136
139
|
|
|
137
140
|
return app;
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
isLauncherActivity(activity) {
|
|
141
|
-
return activity.intentFilters.some((filter) => {
|
|
143
|
+
private isLauncherActivity(activity: any) {
|
|
144
|
+
return activity.intentFilters.some((filter: any) => {
|
|
142
145
|
const hasMain = filter.actions.some(
|
|
143
|
-
(action) => action.name === INTENT_MAIN,
|
|
146
|
+
(action: any) => action.name === INTENT_MAIN,
|
|
144
147
|
);
|
|
145
148
|
if (!hasMain) {
|
|
146
149
|
return false;
|
|
147
150
|
}
|
|
148
151
|
return filter.categories.some(
|
|
149
|
-
(category) => category.name === CATEGORY_LAUNCHER,
|
|
152
|
+
(category: any) => category.name === CATEGORY_LAUNCHER,
|
|
150
153
|
);
|
|
151
154
|
});
|
|
152
155
|
}
|
|
@@ -169,7 +172,7 @@ class ManifestParser {
|
|
|
169
172
|
manifest.supportsGlTextures = [];
|
|
170
173
|
manifest.application = Object.create(null);
|
|
171
174
|
|
|
172
|
-
document.childNodes
|
|
175
|
+
for (const element of document.childNodes) {
|
|
173
176
|
switch (element.nodeName) {
|
|
174
177
|
case 'uses-permission':
|
|
175
178
|
manifest.usesPermissions.push(this.collapseAttributes(element));
|
|
@@ -202,11 +205,9 @@ class ManifestParser {
|
|
|
202
205
|
manifest.supportsScreens = this.collapseAttributes(element);
|
|
203
206
|
break;
|
|
204
207
|
case 'compatible-screens':
|
|
205
|
-
element.childNodes
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
);
|
|
209
|
-
});
|
|
208
|
+
for (const screen of element.childNodes) {
|
|
209
|
+
manifest.compatibleScreens.push(this.collapseAttributes(screen));
|
|
210
|
+
}
|
|
210
211
|
break;
|
|
211
212
|
case 'supports-gl-texture':
|
|
212
213
|
manifest.supportsGlTextures.push(this.collapseAttributes(element));
|
|
@@ -215,10 +216,8 @@ class ManifestParser {
|
|
|
215
216
|
manifest.application = this.parseApplication(element);
|
|
216
217
|
break;
|
|
217
218
|
}
|
|
218
|
-
}
|
|
219
|
+
}
|
|
219
220
|
|
|
220
221
|
return manifest;
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
|
-
|
|
224
|
-
module.exports = ManifestParser;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const Unzip = require('isomorphic-unzip');
|
|
2
|
+
|
|
3
|
+
import { decodeNullUnicode, isBrowser } from './utils';
|
|
4
|
+
|
|
5
|
+
let bundleZipUtils: any;
|
|
6
|
+
|
|
7
|
+
export class Zip {
|
|
8
|
+
file: string | File | Blob;
|
|
9
|
+
unzip: any;
|
|
10
|
+
|
|
11
|
+
constructor(file: string | File | Blob) {
|
|
12
|
+
if (isBrowser()) {
|
|
13
|
+
if (!(file instanceof window.Blob || typeof file.size !== 'undefined')) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'Param error: [file] must be an instance of Blob or File in browser.',
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
this.file = file;
|
|
19
|
+
} else {
|
|
20
|
+
if (typeof file !== 'string') {
|
|
21
|
+
throw new Error('Param error: [file] must be file path in Node.');
|
|
22
|
+
}
|
|
23
|
+
this.file = require('path').resolve(file);
|
|
24
|
+
}
|
|
25
|
+
this.unzip = new Unzip(this.file);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* get entries by regexps, the return format is: { <filename>: <Buffer|Blob> }
|
|
30
|
+
* @param {Array} regexps // regexps for matching files
|
|
31
|
+
* @param {String} type // return type, can be buffer or blob, default buffer
|
|
32
|
+
*/
|
|
33
|
+
getEntries(
|
|
34
|
+
regexps: Array<RegExp | string>,
|
|
35
|
+
type: 'buffer' | 'blob' = 'buffer',
|
|
36
|
+
) {
|
|
37
|
+
const decoded = regexps.map((regex) => decodeNullUnicode(regex));
|
|
38
|
+
return new Promise<Record<string, Buffer | Blob>>((resolve, reject) => {
|
|
39
|
+
this.unzip.getBuffer(
|
|
40
|
+
decoded,
|
|
41
|
+
{ type },
|
|
42
|
+
(err: Error | null, buffers: Record<string, Buffer | Blob>) => {
|
|
43
|
+
err ? reject(err) : resolve(buffers);
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* get entry by regex, return an instance of Buffer or Blob
|
|
51
|
+
* @param {Regex} regex // regex for matching file
|
|
52
|
+
* @param {String} type // return type, can be buffer or blob, default buffer
|
|
53
|
+
*/
|
|
54
|
+
getEntry(regex: RegExp | string, type: 'buffer' | 'blob' = 'buffer') {
|
|
55
|
+
const decoded = decodeNullUnicode(regex);
|
|
56
|
+
return new Promise<Buffer | Blob | undefined>((resolve, reject) => {
|
|
57
|
+
this.unzip.getBuffer(
|
|
58
|
+
[decoded],
|
|
59
|
+
{ type },
|
|
60
|
+
(err: Error | null, buffers: Record<string, Buffer | Blob>) => {
|
|
61
|
+
err ? reject(err) : resolve(buffers[decoded as any]);
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async getEntryFromHarmonyApp(regex: RegExp) {
|
|
68
|
+
try {
|
|
69
|
+
const { enumZipEntries, readEntry } =
|
|
70
|
+
bundleZipUtils ?? (bundleZipUtils = require('../../bundle'));
|
|
71
|
+
let originSource: Buffer | Blob | undefined;
|
|
72
|
+
await enumZipEntries(this.file, (entry: any, zipFile: any) => {
|
|
73
|
+
if (regex.test(entry.fileName)) {
|
|
74
|
+
return readEntry(entry, zipFile).then(
|
|
75
|
+
(value: Buffer | Blob | undefined) => {
|
|
76
|
+
originSource = value;
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return originSource;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('Error in getEntryFromHarmonyApp:', error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -29,9 +29,12 @@ if (currentPackage) {
|
|
|
29
29
|
|
|
30
30
|
export const depVersions = Object.keys(_depVersions)
|
|
31
31
|
.sort() // Sort the keys alphabetically
|
|
32
|
-
.reduce(
|
|
33
|
-
obj
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
.reduce(
|
|
33
|
+
(obj, key) => {
|
|
34
|
+
obj[key] = _depVersions[key]; // Rebuild the object with sorted keys
|
|
35
|
+
return obj;
|
|
36
|
+
},
|
|
37
|
+
{} as Record<string, string>,
|
|
38
|
+
);
|
|
36
39
|
|
|
37
40
|
// console.log({ depVersions });
|