@futpib/parser 1.0.0 → 1.0.1
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/build/apk.d.ts +29 -3
- package/build/apkParser.d.ts +15 -2
- package/build/apkParser.js +70 -41
- package/build/apkParser.test.js +2 -2
- package/build/apkUnparser.d.ts +4 -0
- package/build/apkUnparser.js +90 -0
- package/build/apkUnparser.test.d.ts +1 -0
- package/build/apkUnparser.test.js +26 -0
- package/build/arbitraryFileSystemEntry.js +1 -1
- package/build/arbitraryZip.d.ts +1 -1
- package/build/arbitraryZip.js +13 -19
- package/build/arbitraryZipPermissions.d.ts +1 -8
- package/build/arbitraryZipPermissions.js +1 -16
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arbitraryZipStream.js +3 -3
- package/build/arrayParser.d.ts +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayParser.test.js +2 -2
- package/build/arrayUnparser.d.ts +2 -0
- package/build/arrayUnparser.js +8 -0
- package/build/bsonParser.test.js +2 -2
- package/build/customInvariant.d.ts +4 -0
- package/build/customInvariant.js +11 -0
- package/build/debugLogParser.d.ts +1 -1
- package/build/debugLogParser.js +1 -1
- package/build/elementParser.d.ts +2 -2
- package/build/elementParser.js +1 -1
- package/build/endOfInputParser.d.ts +2 -2
- package/build/exactElementParser.d.ts +1 -1
- package/build/exactSequenceParser.js +1 -1
- package/build/index.d.ts +5 -2
- package/build/index.js +3 -0
- package/build/inputReader.d.ts +3 -3
- package/build/inputReader.js +6 -6
- package/build/inputReader.test.js +7 -7
- package/build/javaKeyStore.d.ts +1 -0
- package/build/javaKeyStore.js +1 -0
- package/build/javaKeyStoreParser.d.ts +2 -0
- package/build/javaKeyStoreParser.js +67 -0
- package/build/javaKeyStoreParser.test.d.ts +1 -0
- package/build/javaKeyStoreParser.test.js +16 -0
- package/build/javaKeystoreParser.d.ts +2 -0
- package/build/javaKeystoreParser.js +7 -0
- package/build/jsonParser.js +3 -2
- package/build/jsonParser.test.js +2 -2
- package/build/listParser.d.ts +1 -1
- package/build/listParser.js +5 -5
- package/build/negativeLookahead.d.ts +1 -1
- package/build/negativeLookahead.js +16 -18
- package/build/negativeLookaheadParser.d.ts +2 -0
- package/build/negativeLookaheadParser.js +18 -0
- package/build/optionalParser.d.ts +1 -1
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +3 -3
- package/build/parser.js +3 -3
- package/build/parser.test.js +16 -16
- package/build/parserAccessorParser.d.ts +1 -1
- package/build/parserConsumedSequenceParser.d.ts +2 -0
- package/build/parserConsumedSequenceParser.js +17 -0
- package/build/parserContext.d.ts +6 -6
- package/build/parserContext.js +15 -14
- package/build/parserContext.test.js +7 -7
- package/build/parserCreatorCompose.d.ts +3 -3
- package/build/parserCreatorCompose.js +2 -2
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.d.ts +20 -0
- package/build/parserInputCompanion.js +30 -0
- package/build/parserInvariant.d.ts +1 -1
- package/build/parserInvariant.js +1 -1
- package/build/quantifierParser.d.ts +2 -0
- package/build/quantifierParser.js +17 -0
- package/build/sequenceBuffer.d.ts +3 -3
- package/build/sequenceBuffer.js +6 -6
- package/build/sequenceBuffer.test.js +2 -2
- package/build/sequenceUnparser.d.ts +2 -0
- package/build/sequenceUnparser.js +6 -0
- package/build/sliceBoundedParser.d.ts +1 -1
- package/build/sliceBoundedParser.js +1 -1
- package/build/sliceBoundedParser.test.js +2 -2
- package/build/terminatedArrayParser.d.ts +1 -1
- package/build/terminatedArrayParser.js +3 -3
- package/build/uint8Array.d.ts +1 -0
- package/build/uint8Array.js +7 -0
- package/build/unparser.d.ts +8 -0
- package/build/unparser.js +104 -0
- package/build/unparser.test.d.ts +1 -0
- package/build/unparser.test.js +150 -0
- package/build/unparserContext.d.ts +31 -0
- package/build/unparserContext.js +74 -0
- package/build/unparserError.d.ts +9 -0
- package/build/unparserError.js +9 -0
- package/build/unparserImplementationInvariant.d.ts +2 -0
- package/build/unparserImplementationInvariant.js +5 -0
- package/build/unparserInputCompanion.d.ts +15 -0
- package/build/unparserInputCompanion.js +13 -0
- package/build/unparserOutputCompanion.d.ts +15 -0
- package/build/unparserOutputCompanion.js +13 -0
- package/build/zip.d.ts +9 -17
- package/build/zipParser.d.ts +13 -10
- package/build/zipParser.js +48 -60
- package/build/zipParser.test.js +2 -7
- package/build/zipUnparser.d.ts +5 -0
- package/build/zipUnparser.js +171 -0
- package/build/zipUnparser.test.d.ts +1 -0
- package/build/zipUnparser.test.js +80 -0
- package/package.json +4 -2
- package/src/apk.ts +35 -3
- package/src/apkParser.test.ts +2 -2
- package/src/apkParser.test.ts.md +114 -111
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +150 -85
- package/src/apkUnparser.test.ts +37 -0
- package/src/apkUnparser.ts +120 -0
- package/src/arbitraryFileSystemEntry.ts +2 -4
- package/src/arbitraryZip.ts +20 -27
- package/src/arbitraryZipPermissions.ts +0 -25
- package/src/arbitraryZipStream.ts +4 -4
- package/src/arrayParser.test.ts +3 -3
- package/src/arrayParser.ts +3 -2
- package/src/arrayUnparser.ts +13 -0
- package/src/bsonParser.test.ts +2 -2
- package/src/bsonParser.ts +3 -3
- package/src/{parserInvariant.ts → customInvariant.ts} +1 -1
- package/src/debugLogParser.ts +1 -1
- package/src/elementParser.ts +3 -3
- package/src/endOfInputParser.ts +4 -4
- package/src/exactElementParser.ts +1 -1
- package/src/exactSequenceParser.ts +2 -2
- package/src/index.ts +15 -2
- package/src/inputReader.test.ts +7 -7
- package/src/inputReader.ts +5 -5
- package/src/javaKeyStore.ts +0 -0
- package/src/javaKeyStoreParser.test.ts +23 -0
- package/src/javaKeyStoreParser.test.ts.md +103 -0
- package/src/javaKeyStoreParser.test.ts.snap +0 -0
- package/src/javaKeyStoreParser.ts +136 -0
- package/src/jsonParser.test.ts +2 -2
- package/src/jsonParser.ts +13 -12
- package/src/listParser.ts +6 -6
- package/src/negativeLookaheadParser.ts +24 -0
- package/src/optionalParser.ts +3 -3
- package/src/parser.test.ts +19 -17
- package/src/parser.ts +7 -7
- package/src/parserAccessorParser.ts +1 -1
- package/src/parserConsumedSequenceParser.ts +20 -0
- package/src/parserContext.test.ts +7 -7
- package/src/parserContext.ts +18 -14
- package/src/parserCreatorCompose.ts +6 -6
- package/src/parserImplementationInvariant.ts +2 -2
- package/src/{inputCompanion.ts → parserInputCompanion.ts} +10 -6
- package/src/quantifierParser.ts +25 -0
- package/src/sequenceBuffer.test.ts +2 -2
- package/src/sequenceBuffer.ts +5 -5
- package/src/sequenceUnparser.ts +9 -0
- package/src/sliceBoundedParser.test.ts +2 -2
- package/src/sliceBoundedParser.ts +2 -2
- package/src/terminatedArrayParser.ts +3 -3
- package/src/uint8Array.ts +10 -0
- package/src/unparser.test.ts +221 -0
- package/src/unparser.ts +209 -0
- package/src/unparserContext.ts +127 -0
- package/src/unparserError.ts +12 -0
- package/src/unparserImplementationInvariant.ts +6 -0
- package/src/unparserOutputCompanion.ts +24 -0
- package/src/zip.ts +10 -22
- package/src/zipParser.test.ts +2 -8
- package/src/zipParser.ts +147 -129
- package/src/zipUnparser.test.ts +119 -0
- package/src/zipUnparser.ts +239 -0
- package/src/negativeLookahead.ts +0 -26
package/build/apk.d.ts
CHANGED
|
@@ -1,12 +1,38 @@
|
|
|
1
|
-
import { Zip } from './zip.js';
|
|
1
|
+
import { type Zip } from './zip.js';
|
|
2
2
|
export type ApkSigningBlockPair = {
|
|
3
3
|
id: number;
|
|
4
4
|
value: Uint8Array;
|
|
5
5
|
};
|
|
6
|
-
export type
|
|
6
|
+
export type ApkSignatureV2Digest = {
|
|
7
|
+
signatureAlgorithmId: number;
|
|
8
|
+
digest: Uint8Array;
|
|
9
|
+
};
|
|
10
|
+
export type ApkSignatureV2AdditionalAttribute = {
|
|
11
|
+
id: number;
|
|
12
|
+
value: Uint8Array;
|
|
13
|
+
};
|
|
14
|
+
export type ApkSignatureV2SignedData = {
|
|
15
|
+
digests: ApkSignatureV2Digest[];
|
|
16
|
+
certificates: Uint8Array[];
|
|
17
|
+
additionalAttributes: ApkSignatureV2AdditionalAttribute[];
|
|
7
18
|
zeroPaddingLength?: number;
|
|
8
|
-
|
|
19
|
+
};
|
|
20
|
+
export type ApkSignatureV2Signature = {
|
|
21
|
+
signatureAlgorithmId: number;
|
|
22
|
+
signature: Uint8Array;
|
|
23
|
+
};
|
|
24
|
+
export type ApkSignatureV2Signer = {
|
|
25
|
+
signedData: ApkSignatureV2SignedData;
|
|
26
|
+
signatures: ApkSignatureV2Signature[];
|
|
27
|
+
publicKey: Uint8Array;
|
|
28
|
+
};
|
|
29
|
+
export type ApkSignatureV2 = {
|
|
30
|
+
signers: ApkSignatureV2Signer[];
|
|
31
|
+
};
|
|
32
|
+
export type ApkSigningBlock = {
|
|
9
33
|
pairs: ApkSigningBlockPair[];
|
|
34
|
+
signatureV2?: ApkSignatureV2;
|
|
35
|
+
zeroPaddingLength?: number;
|
|
10
36
|
};
|
|
11
37
|
export type Apk = Zip & {
|
|
12
38
|
signingBlock?: ApkSigningBlock;
|
package/build/apkParser.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
import { Parser } from
|
|
2
|
-
import {
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
|
+
import { ZipCentralDirectoryHeader, ZipEndOfCentralDirectoryRecord, ZipLocalFile } from './zipParser.js';
|
|
3
|
+
import { type Apk, type ApkSigningBlock } from './apk.js';
|
|
4
|
+
export declare const apkSigningBlockParser: Parser<ApkSigningBlock, Uint8Array>;
|
|
3
5
|
export declare const apkParser: Parser<Apk, Uint8Array>;
|
|
6
|
+
export type ApkSignableSections = {
|
|
7
|
+
zipLocalFiles: ZipLocalFile[];
|
|
8
|
+
apkSigningBlock?: ApkSigningBlock;
|
|
9
|
+
zipCentralDirectory: ZipCentralDirectoryHeader[];
|
|
10
|
+
zipEndOfCentralDirectory: ZipEndOfCentralDirectoryRecord;
|
|
11
|
+
zipLocalFilesUint8Array: Uint8Array;
|
|
12
|
+
apkSigningBlockUint8Array?: Uint8Array;
|
|
13
|
+
zipCentralDirectoryUint8Array: Uint8Array;
|
|
14
|
+
zipEndOfCentralDirectoryUint8Array: Uint8Array;
|
|
15
|
+
};
|
|
16
|
+
export declare const apkSignableSectionsParser: Parser<ApkSignableSections, Uint8Array>;
|
package/build/apkParser.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import { createExactElementParser } from
|
|
1
|
+
import invariant from 'invariant';
|
|
2
|
+
import { createArrayParser } from './arrayParser.js';
|
|
3
|
+
import { createOptionalParser } from './optionalParser.js';
|
|
4
|
+
import { setParserName } from './parser.js';
|
|
5
|
+
import { promiseCompose } from './promiseCompose.js';
|
|
6
|
+
import { createTupleParser } from './tupleParser.js';
|
|
7
|
+
import { zip64EndOfCentralDirectoryLocatorParser, zip64EndOfCentralDirectoryRecordParser, zipArchiveDecryptionHeaderParser, zipArchiveExtraDataRecordParser, zipCentralDirectoryHeaderParser, zipEndOfCentralDirectoryRecordParser, zipFromZipSegments, zipLocalFileParser, } from './zipParser.js';
|
|
8
|
+
import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
|
|
9
|
+
import { parserCreatorCompose } from './parserCreatorCompose.js';
|
|
10
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
11
|
+
import { createSliceBoundedParser } from './sliceBoundedParser.js';
|
|
12
|
+
import { createDisjunctionParser } from './disjunctionParser.js';
|
|
13
|
+
import { createExactElementParser } from './exactElementParser.js';
|
|
14
|
+
import { createParserConsumedSequenceParser } from './parserConsumedSequenceParser.js';
|
|
14
15
|
// https://source.android.com/docs/security/features/apksigning/v2#apk-signing-block
|
|
15
16
|
const uint32LEParser = promiseCompose(createFixedLengthSequenceParser(4), array => Buffer.from(array).readUInt32LE());
|
|
16
17
|
setParserName(uint32LEParser, 'uint32LEParser');
|
|
@@ -27,7 +28,7 @@ const createApkSigningBlockZeroPaddingPairInnerParser = (length) => promiseCompo
|
|
|
27
28
|
const createApkSigningBlockSignatureV2PairInnerParser = (length) => {
|
|
28
29
|
const apkSigningBlockSignatureV2PairInnerParser = promiseCompose(createTupleParser([
|
|
29
30
|
createExactSequenceParser(Buffer.from('1a870971', 'hex')),
|
|
30
|
-
|
|
31
|
+
apkSignatureV2SignersParser,
|
|
31
32
|
]), ([_magic, signers = []]) => ({ type: 'signatureV2', signers }));
|
|
32
33
|
return setParserName(apkSigningBlockSignatureV2PairInnerParser, 'apkSigningBlockSignatureV2PairInnerParser');
|
|
33
34
|
};
|
|
@@ -43,7 +44,7 @@ const createApkSigningBlockPairInnerParser = (length) => createDisjunctionParser
|
|
|
43
44
|
const apkSigningBlockPairParser = createUint64LengthPrefixedParser(length => createApkSigningBlockPairInnerParser(Number(length)));
|
|
44
45
|
setParserName(apkSigningBlockPairParser, 'apkSigningBlockPairParser');
|
|
45
46
|
const apkSigningBlockPairsParser = createArrayParser(apkSigningBlockPairParser);
|
|
46
|
-
const apkSigningBlockParser = createUint64LengthPrefixedParser(sizeOfBlock => promiseCompose(createTupleParser([
|
|
47
|
+
export const apkSigningBlockParser = createUint64LengthPrefixedParser(sizeOfBlock => promiseCompose(createTupleParser([
|
|
47
48
|
apkSigningBlockPairsParser,
|
|
48
49
|
uint64LEParser,
|
|
49
50
|
createExactSequenceParser(Buffer.from('APK Sig Block 42', 'utf8')),
|
|
@@ -60,56 +61,61 @@ const apkSigningBlockParser = createUint64LengthPrefixedParser(sizeOfBlock => pr
|
|
|
60
61
|
}));
|
|
61
62
|
return {
|
|
62
63
|
zeroPaddingLength: zeroPaddingPair?.length,
|
|
63
|
-
signatureV2: signatureV2Pair
|
|
64
|
+
signatureV2: signatureV2Pair ? {
|
|
65
|
+
signers: signatureV2Pair?.signers,
|
|
66
|
+
} : undefined,
|
|
64
67
|
pairs: genericPairs,
|
|
65
68
|
};
|
|
66
69
|
}));
|
|
67
|
-
const
|
|
70
|
+
const apkSignatureV2DigestParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
|
|
68
71
|
uint32LEParser,
|
|
69
72
|
createUint32LengthPrefixedParser(digestLength => createFixedLengthSequenceParser(digestLength)),
|
|
70
73
|
]), ([signatureAlgorithmId, digest]) => ({ signatureAlgorithmId, digest })));
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
74
|
+
const apkSignatureV2DigestsParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2DigestParser);
|
|
75
|
+
const apkSignatureV2CertificateParser = createUint32LengthPrefixedParser(certificateLength => createFixedLengthSequenceParser(certificateLength));
|
|
76
|
+
const apkSignatureV2CertificatesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2CertificateParser);
|
|
77
|
+
const apkSignatureV2AdditionalAttributeParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
|
|
75
78
|
uint32LEParser,
|
|
76
79
|
createFixedLengthSequenceParser(pairLength - 4),
|
|
77
80
|
]), ([id, value]) => ({ id, value })));
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
setParserName(apkSignatureV2AdditionalAttributeParser, 'apkSignatureV2AdditionalAttributeParser');
|
|
82
|
+
const apkSignatureV2AdditionalAttributesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2AdditionalAttributeParser);
|
|
83
|
+
setParserName(apkSignatureV2AdditionalAttributesParser, 'apkSignatureV2AdditionalAttributesParser');
|
|
84
|
+
const apkSignatureV2SignedDataParser = createUint32LengthPrefixedSliceBoundedParser(promiseCompose(createTupleParser([
|
|
85
|
+
apkSignatureV2DigestsParser,
|
|
86
|
+
apkSignatureV2CertificatesParser,
|
|
87
|
+
apkSignatureV2AdditionalAttributesParser,
|
|
83
88
|
createArrayParser(createExactElementParser(0)),
|
|
84
|
-
]), ([digests
|
|
89
|
+
]), ([digests, certificates, additionalAttributes, zeroPadding,]) => ({
|
|
85
90
|
digests,
|
|
86
91
|
certificates,
|
|
87
92
|
additionalAttributes,
|
|
93
|
+
zeroPaddingLength: zeroPadding.length,
|
|
88
94
|
})));
|
|
89
|
-
setParserName(
|
|
90
|
-
const
|
|
95
|
+
setParserName(apkSignatureV2SignedDataParser, 'apkSignatureV2SignedDataParser');
|
|
96
|
+
const apkSignatureV2SignatureParser = createUint32LengthPrefixedParser(signatureLength => promiseCompose(createTupleParser([
|
|
91
97
|
uint32LEParser,
|
|
92
98
|
createUint32LengthPrefixedParser(signatureLength => createFixedLengthSequenceParser(signatureLength)),
|
|
93
99
|
]), ([signatureAlgorithmId, signature,]) => ({
|
|
94
100
|
signatureAlgorithmId,
|
|
95
101
|
signature,
|
|
96
102
|
})));
|
|
97
|
-
const
|
|
98
|
-
setParserName(
|
|
99
|
-
const
|
|
100
|
-
setParserName(
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
]), ([signedData, signatures = [], publicKey]) => ({
|
|
103
|
+
const apkSignatureV2SignaturesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2SignatureParser);
|
|
104
|
+
setParserName(apkSignatureV2SignaturesParser, 'apkSignatureV2SignaturesParser');
|
|
105
|
+
const apkSignatureV2PublicKeyParser = createUint32LengthPrefixedParser(publicKeyLength => createFixedLengthSequenceParser(publicKeyLength));
|
|
106
|
+
setParserName(apkSignatureV2PublicKeyParser, 'apkSignatureV2PublicKeyParser');
|
|
107
|
+
const apkSignatureV2SignerParser = createUint32LengthPrefixedSliceBoundedParser(promiseCompose(createTupleParser([
|
|
108
|
+
apkSignatureV2SignedDataParser,
|
|
109
|
+
apkSignatureV2SignaturesParser,
|
|
110
|
+
apkSignatureV2PublicKeyParser,
|
|
111
|
+
]), ([signedData, signatures = [], publicKey,]) => ({
|
|
106
112
|
signedData,
|
|
107
113
|
signatures,
|
|
108
114
|
publicKey,
|
|
109
115
|
})));
|
|
110
|
-
setParserName(
|
|
111
|
-
const
|
|
112
|
-
setParserName(
|
|
116
|
+
setParserName(apkSignatureV2SignerParser, 'apkSignatureV2SignerParser');
|
|
117
|
+
const apkSignatureV2SignersParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2SignerParser);
|
|
118
|
+
setParserName(apkSignatureV2SignersParser, 'apkSignatureV2SignersParser');
|
|
113
119
|
const apkParser_ = createTupleParser([
|
|
114
120
|
createArrayParser(zipLocalFileParser),
|
|
115
121
|
createOptionalParser(zipArchiveDecryptionHeaderParser),
|
|
@@ -133,3 +139,26 @@ export const apkParser = promiseCompose(apkParser_, async ([zipLocalFiles, zipAr
|
|
|
133
139
|
};
|
|
134
140
|
});
|
|
135
141
|
setParserName(apkParser, 'apkParser');
|
|
142
|
+
export const apkSignableSectionsParser = promiseCompose(createTupleParser([
|
|
143
|
+
createParserConsumedSequenceParser(createTupleParser([
|
|
144
|
+
createArrayParser(zipLocalFileParser),
|
|
145
|
+
createOptionalParser(zipArchiveDecryptionHeaderParser),
|
|
146
|
+
createOptionalParser(zipArchiveExtraDataRecordParser),
|
|
147
|
+
])),
|
|
148
|
+
createOptionalParser(createParserConsumedSequenceParser(apkSigningBlockParser)),
|
|
149
|
+
createParserConsumedSequenceParser(createTupleParser([
|
|
150
|
+
createArrayParser(zipCentralDirectoryHeaderParser),
|
|
151
|
+
createOptionalParser(zip64EndOfCentralDirectoryRecordParser),
|
|
152
|
+
createOptionalParser(zip64EndOfCentralDirectoryLocatorParser),
|
|
153
|
+
])),
|
|
154
|
+
createParserConsumedSequenceParser(zipEndOfCentralDirectoryRecordParser),
|
|
155
|
+
]), async ([[[zipLocalFiles,], zipLocalFilesUint8Array,], [apkSigningBlock = undefined, apkSigningBlockUint8Array = undefined,] = [], [[zipCentralDirectory,], zipCentralDirectoryUint8Array,], [zipEndOfCentralDirectory, zipEndOfCentralDirectoryUint8Array,],]) => ({
|
|
156
|
+
zipLocalFiles,
|
|
157
|
+
apkSigningBlock,
|
|
158
|
+
zipCentralDirectory,
|
|
159
|
+
zipEndOfCentralDirectory,
|
|
160
|
+
zipLocalFilesUint8Array,
|
|
161
|
+
apkSigningBlockUint8Array,
|
|
162
|
+
zipCentralDirectoryUint8Array,
|
|
163
|
+
zipEndOfCentralDirectoryUint8Array,
|
|
164
|
+
}));
|
package/build/apkParser.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import {
|
|
2
|
+
import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
3
3
|
import { runParser } from './parser.js';
|
|
4
4
|
import { apkParser } from './apkParser.js';
|
|
5
5
|
for (const apkCid of [
|
|
@@ -9,7 +9,7 @@ for (const apkCid of [
|
|
|
9
9
|
test('apk ' + apkCid, async (t) => {
|
|
10
10
|
const apkResponse = await fetch('https://ipfs.io/ipfs/' + apkCid);
|
|
11
11
|
const apkStream = apkResponse.body;
|
|
12
|
-
const actual = await runParser(apkParser, apkStream,
|
|
12
|
+
const actual = await runParser(apkParser, apkStream, uint8ArrayParserInputCompanion, {
|
|
13
13
|
errorJoinMode: 'all',
|
|
14
14
|
});
|
|
15
15
|
for (const entry of actual.entries) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ApkSignatureV2SignedData, ApkSigningBlock } from "./apk.js";
|
|
2
|
+
import { Unparser } from "./unparser.js";
|
|
3
|
+
export declare const apkSignatureV2SignedDataUnparser: Unparser<ApkSignatureV2SignedData, Uint8Array>;
|
|
4
|
+
export declare const apkSigningBlockUnparser: Unparser<ApkSigningBlock, Uint8Array>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createArrayUnparser } from "./arrayUnparser.js";
|
|
2
|
+
import { createSequenceUnparser } from "./sequenceUnparser.js";
|
|
3
|
+
const uint8ArrayUnparser = createSequenceUnparser();
|
|
4
|
+
const uint32LEUnparser = async function* (input) {
|
|
5
|
+
const buffer = Buffer.alloc(4);
|
|
6
|
+
buffer.writeUInt32LE(input);
|
|
7
|
+
yield buffer;
|
|
8
|
+
};
|
|
9
|
+
const uint64LEUnparser = async function* (input) {
|
|
10
|
+
const buffer = Buffer.alloc(8);
|
|
11
|
+
buffer.writeBigUInt64LE(BigInt(input));
|
|
12
|
+
yield buffer;
|
|
13
|
+
};
|
|
14
|
+
const createUint32LengthPrefixedUnparser = (innerUnparser) => async function* (input, unparserContext) {
|
|
15
|
+
const length = yield* unparserContext.writeLater(4);
|
|
16
|
+
yield* innerUnparser(input, unparserContext);
|
|
17
|
+
yield* unparserContext.writeEarlier(length, uint32LEUnparser, unparserContext.position - length.positionEnd);
|
|
18
|
+
};
|
|
19
|
+
const createUint64LengthPrefixedUnparser = (innerUnparser) => async function* (input, unparserContext) {
|
|
20
|
+
const length = yield* unparserContext.writeLater(8);
|
|
21
|
+
yield* innerUnparser(input, unparserContext);
|
|
22
|
+
yield* unparserContext.writeEarlier(length, uint64LEUnparser, unparserContext.position - length.positionEnd);
|
|
23
|
+
};
|
|
24
|
+
const apkSignatureV2DigestUnparser = createUint32LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
25
|
+
yield* uint32LEUnparser(input.signatureAlgorithmId, unparserContext);
|
|
26
|
+
yield* uint32LEUnparser(input.digest.length, unparserContext);
|
|
27
|
+
yield input.digest;
|
|
28
|
+
});
|
|
29
|
+
const apkSignatureV2DigestsUnparser = createUint32LengthPrefixedUnparser(createArrayUnparser(apkSignatureV2DigestUnparser));
|
|
30
|
+
const apkSignatureV2CertificateUnparser = createUint32LengthPrefixedUnparser(uint8ArrayUnparser);
|
|
31
|
+
const apkSignatureV2CertificatesUnparser = createUint32LengthPrefixedUnparser(createArrayUnparser(apkSignatureV2CertificateUnparser));
|
|
32
|
+
const apkSignatureV2AdditionalAttributeUnparser = createUint32LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
33
|
+
yield* uint32LEUnparser(input.id, unparserContext);
|
|
34
|
+
yield input.value;
|
|
35
|
+
});
|
|
36
|
+
const apkSignatureV2AdditionalAttributesUnparser = createUint32LengthPrefixedUnparser(createArrayUnparser(apkSignatureV2AdditionalAttributeUnparser));
|
|
37
|
+
export const apkSignatureV2SignedDataUnparser = createUint32LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
38
|
+
yield* apkSignatureV2DigestsUnparser(input.digests, unparserContext);
|
|
39
|
+
yield* apkSignatureV2CertificatesUnparser(input.certificates, unparserContext);
|
|
40
|
+
yield* apkSignatureV2AdditionalAttributesUnparser(input.additionalAttributes, unparserContext);
|
|
41
|
+
if (input.zeroPaddingLength) {
|
|
42
|
+
yield Buffer.alloc(input.zeroPaddingLength);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const apkSignatureV2SignatureUnparser = createUint32LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
46
|
+
yield* uint32LEUnparser(input.signatureAlgorithmId, unparserContext);
|
|
47
|
+
yield* uint32LEUnparser(input.signature.length, unparserContext);
|
|
48
|
+
yield input.signature;
|
|
49
|
+
});
|
|
50
|
+
const apkSignatureV2SignaturesUnparser = createUint32LengthPrefixedUnparser(createArrayUnparser(apkSignatureV2SignatureUnparser));
|
|
51
|
+
const apkSignatureV2PublicKeyUnparser = createUint32LengthPrefixedUnparser(uint8ArrayUnparser);
|
|
52
|
+
const apkSignatureV2SignerUnparser = createUint32LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
53
|
+
yield* apkSignatureV2SignedDataUnparser(input.signedData, unparserContext);
|
|
54
|
+
yield* apkSignatureV2SignaturesUnparser(input.signatures, unparserContext);
|
|
55
|
+
yield* apkSignatureV2PublicKeyUnparser(input.publicKey, unparserContext);
|
|
56
|
+
});
|
|
57
|
+
const apkSignatureV2SignersUnparser = createUint32LengthPrefixedUnparser(createArrayUnparser(apkSignatureV2SignerUnparser));
|
|
58
|
+
const apkSigningBlockPairUnparser = createUint64LengthPrefixedUnparser(async function* (input, unparserContext) {
|
|
59
|
+
yield* uint32LEUnparser(input.id, unparserContext);
|
|
60
|
+
if (input.value instanceof Uint8Array) {
|
|
61
|
+
yield input.value;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
yield* apkSignatureV2SignersUnparser(input.value, unparserContext);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const apkSigningBlockPairsUnparser = createArrayUnparser(apkSigningBlockPairUnparser);
|
|
68
|
+
export const apkSigningBlockUnparser = async function* (input, unparserContext) {
|
|
69
|
+
const pairs = [
|
|
70
|
+
...input.pairs,
|
|
71
|
+
...(input.signatureV2 ? [
|
|
72
|
+
{
|
|
73
|
+
id: 0x7109871a,
|
|
74
|
+
value: input.signatureV2.signers,
|
|
75
|
+
},
|
|
76
|
+
] : []),
|
|
77
|
+
...(input.zeroPaddingLength ? [
|
|
78
|
+
{
|
|
79
|
+
id: 0x42726577,
|
|
80
|
+
value: Buffer.alloc(input.zeroPaddingLength),
|
|
81
|
+
},
|
|
82
|
+
] : []),
|
|
83
|
+
];
|
|
84
|
+
const sizeOfBlockWriteLater = yield* unparserContext.writeLater(8);
|
|
85
|
+
yield* apkSigningBlockPairsUnparser(pairs, unparserContext);
|
|
86
|
+
const sizeOfBlock = unparserContext.position - sizeOfBlockWriteLater.position + 16;
|
|
87
|
+
yield* uint64LEUnparser(sizeOfBlock, unparserContext);
|
|
88
|
+
yield* unparserContext.writeEarlier(sizeOfBlockWriteLater, uint64LEUnparser, sizeOfBlock);
|
|
89
|
+
yield Buffer.from('APK Sig Block 42', 'utf8');
|
|
90
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
3
|
+
import { runParser } from './parser.js';
|
|
4
|
+
import { apkParser, apkSigningBlockParser } from './apkParser.js';
|
|
5
|
+
import { runUnparser } from './unparser.js';
|
|
6
|
+
import { apkSigningBlockUnparser } from './apkUnparser.js';
|
|
7
|
+
import { uint8ArrayUnparserOutputCompanion } from './unparserOutputCompanion.js';
|
|
8
|
+
import invariant from 'invariant';
|
|
9
|
+
for (const apkCid of [
|
|
10
|
+
'bafkreicckcmzrdxwoc3w2in3tivpyxrdtcfpct4zwauq3igew3nkpvfapu',
|
|
11
|
+
]) {
|
|
12
|
+
test('apk ' + apkCid, async (t) => {
|
|
13
|
+
const apkResponse = await fetch('https://ipfs.io/ipfs/' + apkCid);
|
|
14
|
+
const apkStream = apkResponse.body;
|
|
15
|
+
const apk = await runParser(apkParser, apkStream, uint8ArrayParserInputCompanion, {
|
|
16
|
+
errorJoinMode: 'all',
|
|
17
|
+
});
|
|
18
|
+
const apkSigningBlock = apk.signingBlock;
|
|
19
|
+
invariant(apkSigningBlock, 'APK has no signing block');
|
|
20
|
+
const apkSigningBlockStream = runUnparser(apkSigningBlockUnparser, apkSigningBlock, uint8ArrayUnparserOutputCompanion);
|
|
21
|
+
const actual = await runParser(apkSigningBlockParser, apkSigningBlockStream, uint8ArrayParserInputCompanion, {
|
|
22
|
+
errorJoinMode: 'all',
|
|
23
|
+
});
|
|
24
|
+
t.deepEqual(actual, apkSigningBlock);
|
|
25
|
+
});
|
|
26
|
+
}
|
package/build/arbitraryZip.d.ts
CHANGED
package/build/arbitraryZip.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import * as fc from 'fast-check';
|
|
2
|
-
import { arbitraryDosDateTime } from './arbitraryDosDateTime.js';
|
|
3
|
-
import { createArbitraryZipPermissions } from './arbitraryZipPermissions.js';
|
|
4
2
|
import invariant from 'invariant';
|
|
5
|
-
|
|
3
|
+
import { arbitraryDosDateTime } from './arbitraryDosDateTime.js';
|
|
6
4
|
const arbitraryPath = fc.string({ minLength: 1 }).filter(path => {
|
|
7
5
|
const pathSegments = path.split('/');
|
|
8
6
|
const pathHasEmptySegments = pathSegments.some(segment => segment.length === 0);
|
|
@@ -16,7 +14,10 @@ const createArbitraryZipEntry = (platform) => fc.oneof(fc.record({
|
|
|
16
14
|
path: arbitraryPath,
|
|
17
15
|
date: arbitraryDosDateTime,
|
|
18
16
|
comment: fc.string(),
|
|
19
|
-
|
|
17
|
+
hostSystem: fc.constant(platform),
|
|
18
|
+
attributes: fc.record({
|
|
19
|
+
directory: fc.constant(false),
|
|
20
|
+
}),
|
|
20
21
|
compression: fc.oneof(fc.constant('store'), fc.constant('deflate')),
|
|
21
22
|
content: fc.uint8Array(),
|
|
22
23
|
}).filter(zipFileEntry => {
|
|
@@ -24,23 +25,16 @@ const createArbitraryZipEntry = (platform) => fc.oneof(fc.record({
|
|
|
24
25
|
&& zipFileEntry.compression === 'deflate') {
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
27
|
-
if (zipFileEntry.permissions.type === 'dos'
|
|
28
|
-
&& zipFileEntry.permissions.dosPermissions & DOS_DIRECTORY_FLAG) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
28
|
return true;
|
|
32
29
|
}), fc.record({
|
|
33
30
|
type: fc.constant('directory'),
|
|
34
31
|
path: arbitraryPath,
|
|
35
32
|
date: arbitraryDosDateTime,
|
|
36
33
|
comment: fc.string(),
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
34
|
+
hostSystem: fc.constant(platform),
|
|
35
|
+
attributes: fc.record({
|
|
36
|
+
directory: fc.constant(false),
|
|
37
|
+
}),
|
|
44
38
|
}));
|
|
45
39
|
const createArbitraryZipEntries = (platform) => (fc
|
|
46
40
|
.array(createArbitraryZipEntry(platform))
|
|
@@ -70,10 +64,10 @@ const createArbitraryZipEntries = (platform) => (fc
|
|
|
70
64
|
path: directoryPath,
|
|
71
65
|
date: entry.date,
|
|
72
66
|
comment: '',
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
67
|
+
hostSystem: platform,
|
|
68
|
+
attributes: {
|
|
69
|
+
directory: true,
|
|
70
|
+
},
|
|
77
71
|
});
|
|
78
72
|
seenDirectoryPaths.add(directoryPath);
|
|
79
73
|
}
|
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const arbitraryZipUnixPermissions = fc.record({
|
|
3
|
-
type: fc.constant('unix'),
|
|
4
|
-
unixPermissions: (fc.nat({ max: 0b0000000111111111 })
|
|
5
|
-
.filter((unixPermissions) => unixPermissions > 0)),
|
|
6
|
-
});
|
|
7
|
-
const arbitraryZipDosPermissions = fc.record({
|
|
8
|
-
type: fc.constant('dos'),
|
|
9
|
-
dosPermissions: (fc.nat({ max: 0b00111111 })),
|
|
10
|
-
});
|
|
11
|
-
export const createArbitraryZipPermissions = (type) => {
|
|
12
|
-
if (type === 'unix') {
|
|
13
|
-
return arbitraryZipUnixPermissions;
|
|
14
|
-
}
|
|
15
|
-
return arbitraryZipDosPermissions;
|
|
16
|
-
};
|
|
1
|
+
export {};
|
|
@@ -4,8 +4,8 @@ function addZipEntryToZip(zip, zipEntry) {
|
|
|
4
4
|
const options = {
|
|
5
5
|
comment: zipEntry.comment,
|
|
6
6
|
date: zipEntry.date,
|
|
7
|
-
unixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
|
|
8
|
-
dosPermissions: zipEntry.permissions.type === 'dos' ? zipEntry.permissions.dosPermissions : undefined,
|
|
7
|
+
// unixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
|
|
8
|
+
// dosPermissions: zipEntry.permissions.type === 'dos' ? zipEntry.permissions.dosPermissions : undefined,
|
|
9
9
|
};
|
|
10
10
|
if (zipEntry.type === 'file') {
|
|
11
11
|
zip.file(zipEntry.path, zipEntry.content, {
|
|
@@ -30,7 +30,7 @@ export const arbitraryZipStream = arbitraryZip.map(zip => {
|
|
|
30
30
|
const zipInternalStream = jsZip.generateInternalStream({
|
|
31
31
|
type: 'uint8array',
|
|
32
32
|
comment: zip.comment,
|
|
33
|
-
platform: zip.entries.at(0)?.
|
|
33
|
+
platform: zip.entries.at(0)?.hostSystem.toUpperCase(),
|
|
34
34
|
});
|
|
35
35
|
const zipStream = new ReadableStream({
|
|
36
36
|
start(controller) {
|
package/build/arrayParser.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Parser } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
2
|
export declare const createArrayParser: <ElementOutput, Sequence>(elementParser: Parser<ElementOutput, Sequence>) => Parser<ElementOutput[], Sequence>;
|
package/build/arrayParser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getParserName, setParserName } from
|
|
2
|
-
import { ParserParsingFailedError } from
|
|
1
|
+
import { getParserName, setParserName } from './parser.js';
|
|
2
|
+
import { ParserParsingFailedError } from './parserError.js';
|
|
3
3
|
export const createArrayParser = (elementParser) => {
|
|
4
4
|
const arrayParser = async (parserContext) => {
|
|
5
5
|
const elements = [];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import { createArrayParser } from './arrayParser.js';
|
|
3
3
|
import { runParser } from './parser.js';
|
|
4
|
-
import {
|
|
4
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
5
5
|
test('does not loop forever with a child parser that does not consume anything', async (t) => {
|
|
6
6
|
const parser = createArrayParser(async () => undefined);
|
|
7
|
-
const result = await runParser(parser, 'foo',
|
|
7
|
+
const result = await runParser(parser, 'foo', stringParserInputCompanion);
|
|
8
8
|
t.deepEqual(result, []);
|
|
9
9
|
});
|
package/build/bsonParser.test.js
CHANGED
|
@@ -3,7 +3,7 @@ import { BSON } from 'bson';
|
|
|
3
3
|
import { bsonDocumentParser } from './bsonParser.js';
|
|
4
4
|
import { arbitrarilySlicedAsyncIterator } from './arbitrarilySlicedAsyncInterator.js';
|
|
5
5
|
import { runParser } from './parser.js';
|
|
6
|
-
import {
|
|
6
|
+
import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
7
7
|
testProp('bson', [
|
|
8
8
|
arbitrarilySlicedAsyncIterator(fc
|
|
9
9
|
.json()
|
|
@@ -17,7 +17,7 @@ testProp('bson', [
|
|
|
17
17
|
.map(jsonString => BSON.serialize(JSON.parse(jsonString)))),
|
|
18
18
|
], async (t, [bsonUint8Array, bsonUint8ArrayChunkIterator]) => {
|
|
19
19
|
const expected = BSON.deserialize(bsonUint8Array);
|
|
20
|
-
const actual = await runParser(bsonDocumentParser, bsonUint8ArrayChunkIterator,
|
|
20
|
+
const actual = await runParser(bsonDocumentParser, bsonUint8ArrayChunkIterator, uint8ArrayParserInputCompanion);
|
|
21
21
|
t.deepEqual(actual, expected);
|
|
22
22
|
}, {
|
|
23
23
|
verbose: true,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Constructor } from 'type-fest';
|
|
2
|
+
export type Falsy = '' | 0 | false | undefined;
|
|
3
|
+
export type ValueOrAccessor<T> = T | (() => T);
|
|
4
|
+
export declare function customInvariant<T>(ErrorConstructor: Constructor<Error, [message: string]> | ((message: string) => Error), value: T, formatOrFormatLines: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function customInvariant(ErrorConstructor, value, formatOrFormatLines, ...formatArguments) {
|
|
2
|
+
if (value) {
|
|
3
|
+
return value;
|
|
4
|
+
}
|
|
5
|
+
let format = typeof formatOrFormatLines === 'function' ? formatOrFormatLines() : formatOrFormatLines;
|
|
6
|
+
format = Array.isArray(format) ? format.join('\n') : format;
|
|
7
|
+
throw new ErrorConstructor(format.replaceAll('%s', () => {
|
|
8
|
+
const argumentOrAccessor = formatArguments.shift();
|
|
9
|
+
return typeof argumentOrAccessor === 'function' ? argumentOrAccessor() : argumentOrAccessor;
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Parser } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
2
|
export declare const createDebugLogParser: <Output, Sequence>(childParser: Parser<Output, Sequence>) => Parser<Output, Sequence>;
|
package/build/debugLogParser.js
CHANGED
package/build/elementParser.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Parser } from
|
|
2
|
-
import { DeriveSequenceElement } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
3
|
export declare const createElementParser: <Sequence, Element = DeriveSequenceElement<Sequence>>() => Parser<Element, Sequence, Element>;
|
package/build/elementParser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const createElementParser = () => parserContext => parserContext.read(0);
|
|
1
|
+
export const createElementParser = () => async (parserContext) => parserContext.read(0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Parser } from
|
|
2
|
-
import { DeriveSequenceElement } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
3
|
export declare const createEndOfInputParser: <Sequence, Element = DeriveSequenceElement<Sequence>>() => Parser<void, Sequence, Element>;
|
|
4
4
|
export declare const endOfInputParser: Parser<void, any, any>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type Parser } from './parser.js';
|
|
2
|
-
import { DeriveSequenceElement } from './sequence.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
3
|
export declare const createExactElementParser: <Sequence, Element = DeriveSequenceElement<Sequence>>(element: Element) => Parser<Element, Sequence, Element>;
|