@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.
Files changed (171) hide show
  1. package/build/apk.d.ts +29 -3
  2. package/build/apkParser.d.ts +15 -2
  3. package/build/apkParser.js +70 -41
  4. package/build/apkParser.test.js +2 -2
  5. package/build/apkUnparser.d.ts +4 -0
  6. package/build/apkUnparser.js +90 -0
  7. package/build/apkUnparser.test.d.ts +1 -0
  8. package/build/apkUnparser.test.js +26 -0
  9. package/build/arbitraryFileSystemEntry.js +1 -1
  10. package/build/arbitraryZip.d.ts +1 -1
  11. package/build/arbitraryZip.js +13 -19
  12. package/build/arbitraryZipPermissions.d.ts +1 -8
  13. package/build/arbitraryZipPermissions.js +1 -16
  14. package/build/arbitraryZipStream.d.ts +1 -1
  15. package/build/arbitraryZipStream.js +3 -3
  16. package/build/arrayParser.d.ts +1 -1
  17. package/build/arrayParser.js +2 -2
  18. package/build/arrayParser.test.js +2 -2
  19. package/build/arrayUnparser.d.ts +2 -0
  20. package/build/arrayUnparser.js +8 -0
  21. package/build/bsonParser.test.js +2 -2
  22. package/build/customInvariant.d.ts +4 -0
  23. package/build/customInvariant.js +11 -0
  24. package/build/debugLogParser.d.ts +1 -1
  25. package/build/debugLogParser.js +1 -1
  26. package/build/elementParser.d.ts +2 -2
  27. package/build/elementParser.js +1 -1
  28. package/build/endOfInputParser.d.ts +2 -2
  29. package/build/exactElementParser.d.ts +1 -1
  30. package/build/exactSequenceParser.js +1 -1
  31. package/build/index.d.ts +5 -2
  32. package/build/index.js +3 -0
  33. package/build/inputReader.d.ts +3 -3
  34. package/build/inputReader.js +6 -6
  35. package/build/inputReader.test.js +7 -7
  36. package/build/javaKeyStore.d.ts +1 -0
  37. package/build/javaKeyStore.js +1 -0
  38. package/build/javaKeyStoreParser.d.ts +2 -0
  39. package/build/javaKeyStoreParser.js +67 -0
  40. package/build/javaKeyStoreParser.test.d.ts +1 -0
  41. package/build/javaKeyStoreParser.test.js +16 -0
  42. package/build/javaKeystoreParser.d.ts +2 -0
  43. package/build/javaKeystoreParser.js +7 -0
  44. package/build/jsonParser.js +3 -2
  45. package/build/jsonParser.test.js +2 -2
  46. package/build/listParser.d.ts +1 -1
  47. package/build/listParser.js +5 -5
  48. package/build/negativeLookahead.d.ts +1 -1
  49. package/build/negativeLookahead.js +16 -18
  50. package/build/negativeLookaheadParser.d.ts +2 -0
  51. package/build/negativeLookaheadParser.js +18 -0
  52. package/build/optionalParser.d.ts +1 -1
  53. package/build/optionalParser.js +2 -2
  54. package/build/parser.d.ts +3 -3
  55. package/build/parser.js +3 -3
  56. package/build/parser.test.js +16 -16
  57. package/build/parserAccessorParser.d.ts +1 -1
  58. package/build/parserConsumedSequenceParser.d.ts +2 -0
  59. package/build/parserConsumedSequenceParser.js +17 -0
  60. package/build/parserContext.d.ts +6 -6
  61. package/build/parserContext.js +15 -14
  62. package/build/parserContext.test.js +7 -7
  63. package/build/parserCreatorCompose.d.ts +3 -3
  64. package/build/parserCreatorCompose.js +2 -2
  65. package/build/parserImplementationInvariant.d.ts +1 -1
  66. package/build/parserImplementationInvariant.js +2 -2
  67. package/build/parserInputCompanion.d.ts +20 -0
  68. package/build/parserInputCompanion.js +30 -0
  69. package/build/parserInvariant.d.ts +1 -1
  70. package/build/parserInvariant.js +1 -1
  71. package/build/quantifierParser.d.ts +2 -0
  72. package/build/quantifierParser.js +17 -0
  73. package/build/sequenceBuffer.d.ts +3 -3
  74. package/build/sequenceBuffer.js +6 -6
  75. package/build/sequenceBuffer.test.js +2 -2
  76. package/build/sequenceUnparser.d.ts +2 -0
  77. package/build/sequenceUnparser.js +6 -0
  78. package/build/sliceBoundedParser.d.ts +1 -1
  79. package/build/sliceBoundedParser.js +1 -1
  80. package/build/sliceBoundedParser.test.js +2 -2
  81. package/build/terminatedArrayParser.d.ts +1 -1
  82. package/build/terminatedArrayParser.js +3 -3
  83. package/build/uint8Array.d.ts +1 -0
  84. package/build/uint8Array.js +7 -0
  85. package/build/unparser.d.ts +8 -0
  86. package/build/unparser.js +104 -0
  87. package/build/unparser.test.d.ts +1 -0
  88. package/build/unparser.test.js +150 -0
  89. package/build/unparserContext.d.ts +31 -0
  90. package/build/unparserContext.js +74 -0
  91. package/build/unparserError.d.ts +9 -0
  92. package/build/unparserError.js +9 -0
  93. package/build/unparserImplementationInvariant.d.ts +2 -0
  94. package/build/unparserImplementationInvariant.js +5 -0
  95. package/build/unparserInputCompanion.d.ts +15 -0
  96. package/build/unparserInputCompanion.js +13 -0
  97. package/build/unparserOutputCompanion.d.ts +15 -0
  98. package/build/unparserOutputCompanion.js +13 -0
  99. package/build/zip.d.ts +9 -17
  100. package/build/zipParser.d.ts +13 -10
  101. package/build/zipParser.js +48 -60
  102. package/build/zipParser.test.js +2 -7
  103. package/build/zipUnparser.d.ts +5 -0
  104. package/build/zipUnparser.js +171 -0
  105. package/build/zipUnparser.test.d.ts +1 -0
  106. package/build/zipUnparser.test.js +80 -0
  107. package/package.json +4 -2
  108. package/src/apk.ts +35 -3
  109. package/src/apkParser.test.ts +2 -2
  110. package/src/apkParser.test.ts.md +114 -111
  111. package/src/apkParser.test.ts.snap +0 -0
  112. package/src/apkParser.ts +150 -85
  113. package/src/apkUnparser.test.ts +37 -0
  114. package/src/apkUnparser.ts +120 -0
  115. package/src/arbitraryFileSystemEntry.ts +2 -4
  116. package/src/arbitraryZip.ts +20 -27
  117. package/src/arbitraryZipPermissions.ts +0 -25
  118. package/src/arbitraryZipStream.ts +4 -4
  119. package/src/arrayParser.test.ts +3 -3
  120. package/src/arrayParser.ts +3 -2
  121. package/src/arrayUnparser.ts +13 -0
  122. package/src/bsonParser.test.ts +2 -2
  123. package/src/bsonParser.ts +3 -3
  124. package/src/{parserInvariant.ts → customInvariant.ts} +1 -1
  125. package/src/debugLogParser.ts +1 -1
  126. package/src/elementParser.ts +3 -3
  127. package/src/endOfInputParser.ts +4 -4
  128. package/src/exactElementParser.ts +1 -1
  129. package/src/exactSequenceParser.ts +2 -2
  130. package/src/index.ts +15 -2
  131. package/src/inputReader.test.ts +7 -7
  132. package/src/inputReader.ts +5 -5
  133. package/src/javaKeyStore.ts +0 -0
  134. package/src/javaKeyStoreParser.test.ts +23 -0
  135. package/src/javaKeyStoreParser.test.ts.md +103 -0
  136. package/src/javaKeyStoreParser.test.ts.snap +0 -0
  137. package/src/javaKeyStoreParser.ts +136 -0
  138. package/src/jsonParser.test.ts +2 -2
  139. package/src/jsonParser.ts +13 -12
  140. package/src/listParser.ts +6 -6
  141. package/src/negativeLookaheadParser.ts +24 -0
  142. package/src/optionalParser.ts +3 -3
  143. package/src/parser.test.ts +19 -17
  144. package/src/parser.ts +7 -7
  145. package/src/parserAccessorParser.ts +1 -1
  146. package/src/parserConsumedSequenceParser.ts +20 -0
  147. package/src/parserContext.test.ts +7 -7
  148. package/src/parserContext.ts +18 -14
  149. package/src/parserCreatorCompose.ts +6 -6
  150. package/src/parserImplementationInvariant.ts +2 -2
  151. package/src/{inputCompanion.ts → parserInputCompanion.ts} +10 -6
  152. package/src/quantifierParser.ts +25 -0
  153. package/src/sequenceBuffer.test.ts +2 -2
  154. package/src/sequenceBuffer.ts +5 -5
  155. package/src/sequenceUnparser.ts +9 -0
  156. package/src/sliceBoundedParser.test.ts +2 -2
  157. package/src/sliceBoundedParser.ts +2 -2
  158. package/src/terminatedArrayParser.ts +3 -3
  159. package/src/uint8Array.ts +10 -0
  160. package/src/unparser.test.ts +221 -0
  161. package/src/unparser.ts +209 -0
  162. package/src/unparserContext.ts +127 -0
  163. package/src/unparserError.ts +12 -0
  164. package/src/unparserImplementationInvariant.ts +6 -0
  165. package/src/unparserOutputCompanion.ts +24 -0
  166. package/src/zip.ts +10 -22
  167. package/src/zipParser.test.ts +2 -8
  168. package/src/zipParser.ts +147 -129
  169. package/src/zipUnparser.test.ts +119 -0
  170. package/src/zipUnparser.ts +239 -0
  171. 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 ApkSigningBlock = {
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
- signatureV2?: unknown;
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;
@@ -1,3 +1,16 @@
1
- import { Parser } from "./parser.js";
2
- import { Apk } from "./apk.js";
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>;
@@ -1,16 +1,17 @@
1
- import { createArrayParser } from "./arrayParser.js";
2
- import { createOptionalParser } from "./optionalParser.js";
3
- import { setParserName } from "./parser.js";
4
- import { promiseCompose } from "./promiseCompose.js";
5
- import { createTupleParser } from "./tupleParser.js";
6
- import { zip64EndOfCentralDirectoryLocatorParser, zip64EndOfCentralDirectoryRecordParser, zipArchiveDecryptionHeaderParser, zipArchiveExtraDataRecordParser, zipCentralDirectoryHeaderParser, zipEndOfCentralDirectoryRecordParser, zipFromZipSegments, zipLocalFileParser } from "./zipParser.js";
7
- import { createFixedLengthSequenceParser } from "./fixedLengthSequenceParser.js";
8
- import { parserCreatorCompose } from "./parserCreatorCompose.js";
9
- import { createExactSequenceParser } from "./exactSequenceParser.js";
10
- import { createSliceBoundedParser } from "./sliceBoundedParser.js";
11
- import { createDisjunctionParser } from "./disjunctionParser.js";
12
- import invariant from "invariant";
13
- import { createExactElementParser } from "./exactElementParser.js";
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
- apkSignatureSchemeV2SignersParser,
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?.signers,
64
+ signatureV2: signatureV2Pair ? {
65
+ signers: signatureV2Pair?.signers,
66
+ } : undefined,
64
67
  pairs: genericPairs,
65
68
  };
66
69
  }));
67
- const apkSignatureSchemeV2DigestParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
70
+ const apkSignatureV2DigestParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
68
71
  uint32LEParser,
69
72
  createUint32LengthPrefixedParser(digestLength => createFixedLengthSequenceParser(digestLength)),
70
73
  ]), ([signatureAlgorithmId, digest]) => ({ signatureAlgorithmId, digest })));
71
- const apkSignatureSchemeV2DigestsParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureSchemeV2DigestParser);
72
- const apkSignatureSchemeV2CertificateParser = createUint32LengthPrefixedParser(certificateLength => createFixedLengthSequenceParser(certificateLength));
73
- const apkSignatureSchemeV2CertificatesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureSchemeV2CertificateParser);
74
- const apkSignatureSchemeV2AdditionalAttributeParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
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
- const apkSignatureSchemeV2AdditionalAttributesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureSchemeV2AdditionalAttributeParser);
79
- const apkSignatureSchemeV2SignedDataParser = createUint32LengthPrefixedSliceBoundedParser(promiseCompose(createTupleParser([
80
- apkSignatureSchemeV2DigestsParser,
81
- apkSignatureSchemeV2CertificatesParser,
82
- createOptionalParser(apkSignatureSchemeV2AdditionalAttributesParser),
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 = [], certificates = [], additionalAttributes = [],]) => ({
89
+ ]), ([digests, certificates, additionalAttributes, zeroPadding,]) => ({
85
90
  digests,
86
91
  certificates,
87
92
  additionalAttributes,
93
+ zeroPaddingLength: zeroPadding.length,
88
94
  })));
89
- setParserName(apkSignatureSchemeV2SignedDataParser, 'apkSignatureSchemeV2SignedDataParser');
90
- const apkSignatureSchemeV2SignatureParser = createUint32LengthPrefixedParser(signatureLength => promiseCompose(createTupleParser([
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 apkSignatureSchemeV2SignaturesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureSchemeV2SignatureParser);
98
- setParserName(apkSignatureSchemeV2SignaturesParser, 'apkSignatureSchemeV2SignaturesParser');
99
- const apkSignatureSchemeV2PublicKeyParser = createUint32LengthPrefixedParser(publicKeyLength => createFixedLengthSequenceParser(publicKeyLength));
100
- setParserName(apkSignatureSchemeV2PublicKeyParser, 'apkSignatureSchemeV2PublicKeyParser');
101
- const apkSignatureSchemeV2SignerParser = createUint32LengthPrefixedSliceBoundedParser(promiseCompose(createTupleParser([
102
- apkSignatureSchemeV2SignedDataParser,
103
- apkSignatureSchemeV2SignaturesParser,
104
- apkSignatureSchemeV2PublicKeyParser,
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(apkSignatureSchemeV2SignerParser, 'apkSignatureSchemeV2SignerParser');
111
- const apkSignatureSchemeV2SignersParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureSchemeV2SignerParser);
112
- setParserName(apkSignatureSchemeV2SignersParser, 'apkSignatureSchemeV2SignersParser');
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
+ }));
@@ -1,5 +1,5 @@
1
1
  import test from 'ava';
2
- import { uint8ArrayInputCompanion } from './inputCompanion.js';
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, uint8ArrayInputCompanion, {
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
+ }
@@ -1,5 +1,5 @@
1
1
  import * as fc from 'fast-check';
2
- export const arbitraryFileSystemEntry = fc.letrec((tie) => ({
2
+ export const arbitraryFileSystemEntry = fc.letrec(tie => ({
3
3
  entry: fc.oneof(fc.record({
4
4
  type: fc.constant('file'),
5
5
  name: fc.string(),
@@ -1,5 +1,5 @@
1
1
  import * as fc from 'fast-check';
2
- import { ZipEntry } from './zip.js';
2
+ import { type ZipEntry } from './zip.js';
3
3
  export declare const arbitraryZip: fc.Arbitrary<{
4
4
  comment: string;
5
5
  entries: ZipEntry[];
@@ -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
- const DOS_DIRECTORY_FLAG = 0b00010000;
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
- permissions: createArbitraryZipPermissions(platform),
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
- permissions: createArbitraryZipPermissions(platform),
38
- }).filter(zipDirectoryEntry => {
39
- if (zipDirectoryEntry.permissions.type === 'dos'
40
- && !(zipDirectoryEntry.permissions.dosPermissions & DOS_DIRECTORY_FLAG)) {
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
- permissions: entry.permissions.type === 'dos' ? {
74
- type: 'dos',
75
- dosPermissions: entry.permissions.dosPermissions | DOS_DIRECTORY_FLAG,
76
- } : entry.permissions,
67
+ hostSystem: platform,
68
+ attributes: {
69
+ directory: true,
70
+ },
77
71
  });
78
72
  seenDirectoryPaths.add(directoryPath);
79
73
  }
@@ -1,8 +1 @@
1
- import * as fc from 'fast-check';
2
- export declare const createArbitraryZipPermissions: (type: "unix" | "dos") => fc.Arbitrary<{
3
- type: "unix";
4
- unixPermissions: number;
5
- }> | fc.Arbitrary<{
6
- type: "dos";
7
- dosPermissions: number;
8
- }>;
1
+ export {};
@@ -1,16 +1 @@
1
- import * as fc from 'fast-check';
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 {};
@@ -1,4 +1,4 @@
1
- import { ZipEntry } from './zip.js';
1
+ import { type ZipEntry } from './zip.js';
2
2
  export declare const arbitraryZipStream: import("fast-check").Arbitrary<readonly [{
3
3
  comment: string;
4
4
  entries: ZipEntry[];
@@ -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)?.permissions.type.toUpperCase(),
33
+ platform: zip.entries.at(0)?.hostSystem.toUpperCase(),
34
34
  });
35
35
  const zipStream = new ReadableStream({
36
36
  start(controller) {
@@ -1,2 +1,2 @@
1
- import { Parser } from "./parser.js";
1
+ import { type Parser } from './parser.js';
2
2
  export declare const createArrayParser: <ElementOutput, Sequence>(elementParser: Parser<ElementOutput, Sequence>) => Parser<ElementOutput[], Sequence>;
@@ -1,5 +1,5 @@
1
- import { getParserName, setParserName } from "./parser.js";
2
- import { ParserParsingFailedError } from "./parserError.js";
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 { stringInputCompanion } from './inputCompanion.js';
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', stringInputCompanion);
7
+ const result = await runParser(parser, 'foo', stringParserInputCompanion);
8
8
  t.deepEqual(result, []);
9
9
  });
@@ -0,0 +1,2 @@
1
+ import { Unparser } from "./unparser.js";
2
+ export declare const createArrayUnparser: <ElementInput, Sequence>(elementUnparser: Unparser<ElementInput, Sequence>) => Unparser<ElementInput[], Sequence>;
@@ -0,0 +1,8 @@
1
+ export const createArrayUnparser = (elementUnparser) => {
2
+ const arrayUnparser = async function* (input, unparserContext) {
3
+ for (const element of input) {
4
+ yield* elementUnparser(element, unparserContext);
5
+ }
6
+ };
7
+ return arrayUnparser;
8
+ };
@@ -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 { uint8ArrayInputCompanion } from './inputCompanion.js';
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, uint8ArrayInputCompanion);
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 "./parser.js";
1
+ import { type Parser } from './parser.js';
2
2
  export declare const createDebugLogParser: <Output, Sequence>(childParser: Parser<Output, Sequence>) => Parser<Output, Sequence>;
@@ -1,4 +1,4 @@
1
- import { getParserName, setParserName } from "./parser.js";
1
+ import { getParserName, setParserName } from './parser.js';
2
2
  export const createDebugLogParser = (childParser) => {
3
3
  let idCounter = 0;
4
4
  const debugLogParser = async (parserContext) => {
@@ -1,3 +1,3 @@
1
- import { Parser } from "./parser.js";
2
- import { DeriveSequenceElement } from "./sequence.js";
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>;
@@ -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 "./parser.js";
2
- import { DeriveSequenceElement } from "./sequence.js";
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>;