@futpib/parser 1.0.1 → 1.0.2
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/allSettledStream.js +32 -14
- package/build/allSettledStream.test.js +32 -0
- package/build/androidPackage.d.ts +39 -0
- package/build/androidPackageParser.d.ts +17 -0
- package/build/androidPackageParser.js +183 -0
- package/build/{apkParser.test.js → androidPackageParser.test.js} +6 -6
- package/build/androidPackageUnparser.d.ts +4 -0
- package/build/{apkUnparser.js → androidPackageUnparser.js} +23 -23
- package/build/androidPackageUnparser.test.js +26 -0
- package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
- package/build/arbitrarilySlicedAsyncInterable.js +3 -3
- package/build/arrayParser.test.js +3 -3
- package/build/backsmali.d.ts +1 -0
- package/build/backsmali.js +22 -0
- package/build/bsonParser.js +6 -2
- package/build/customInvariant.d.ts +1 -1
- package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
- package/build/dalvikBytecodeParser/formatParsers.js +169 -0
- package/build/dalvikBytecodeParser.d.ts +107 -0
- package/build/dalvikBytecodeParser.js +836 -0
- package/build/dalvikExecutable.d.ts +158 -0
- package/build/dalvikExecutable.js +20 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
- package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
- package/build/dalvikExecutableParser/typeParsers.js +34 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
- package/build/dalvikExecutableParser/typedNumbers.js +19 -0
- package/build/dalvikExecutableParser.d.ts +5 -0
- package/build/dalvikExecutableParser.js +1439 -0
- package/build/dalvikExecutableParser.test.js +70 -0
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
- package/build/debugLogInputParser.d.ts +4 -0
- package/build/debugLogInputParser.js +16 -0
- package/build/debugLogParser.js +14 -3
- package/build/disjunctionParser.d.ts +2 -1
- package/build/disjunctionParser.js +4 -2
- package/build/elementTerminatedArrayParser.d.ts +3 -0
- package/build/elementTerminatedArrayParser.js +18 -0
- package/build/elementTerminatedArrayParser.test.js +52 -0
- package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
- package/build/elementTerminatedSequenceArrayParser.js +32 -0
- package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
- package/build/elementTerminatedSequenceParser.d.ts +3 -0
- package/build/elementTerminatedSequenceParser.js +27 -0
- package/build/elementTerminatedSequenceParser.test.js +34 -0
- package/build/exactElementParser.js +10 -5
- package/build/exactSequenceParser.d.ts +2 -1
- package/build/exactSequenceParser.js +12 -2
- package/build/fetchCid.d.ts +1 -0
- package/build/fetchCid.js +107 -0
- package/build/fixedLengthSequenceParser.d.ts +1 -0
- package/build/fixedLengthSequenceParser.js +18 -1
- package/build/fixedLengthSequenceParser.test.js +41 -0
- package/build/hasExecutable.d.ts +1 -0
- package/build/hasExecutable.js +8 -0
- package/build/highResolutionTimer.d.ts +16 -0
- package/build/highResolutionTimer.js +42 -0
- package/build/inputReader.d.ts +11 -0
- package/build/inputReader.js +37 -0
- package/build/inputReader.test.js +165 -0
- package/build/inputReaderState.d.ts +10 -0
- package/build/inputReaderState.js +16 -0
- package/build/inspect.d.ts +1 -0
- package/build/inspect.js +7 -0
- package/build/javaKeyStoreParser.test.js +2 -2
- package/build/jsonParser.d.ts +2 -0
- package/build/jsonParser.js +11 -14
- package/build/leb128Parser.d.ts +7 -0
- package/build/leb128Parser.js +82 -0
- package/build/leb128Parser.test.js +107 -0
- package/build/lookaheadParser.d.ts +2 -0
- package/build/lookaheadParser.js +14 -0
- package/build/negativeLookaheadParser.js +21 -15
- package/build/negativeLookaheadParser.test.js +30 -0
- package/build/nonEmptyArrayParser.d.ts +2 -0
- package/build/nonEmptyArrayParser.js +32 -0
- package/build/nonEmptyArrayParser.test.js +16 -0
- package/build/parser.d.ts +10 -1
- package/build/parser.js +66 -31
- package/build/parser.test.js +79 -12
- package/build/parserAccessorParser.js +9 -1
- package/build/parserConsumedSequenceParser.js +20 -15
- package/build/parserContext.d.ts +14 -0
- package/build/parserContext.js +56 -27
- package/build/parserContext.test.js +27 -0
- package/build/parserCreatorCompose.d.ts +1 -0
- package/build/parserCreatorCompose.js +8 -2
- package/build/parserError.d.ts +6 -0
- package/build/parserError.js +6 -6
- package/build/parserInputCompanion.d.ts +15 -0
- package/build/parserInputCompanion.js +38 -0
- package/build/promiseCompose.d.ts +1 -1
- package/build/promiseCompose.js +12 -1
- package/build/promiseSettled.d.ts +1 -0
- package/build/promiseSettled.js +4 -0
- package/build/separatedArrayParser.d.ts +2 -0
- package/build/separatedArrayParser.js +39 -0
- package/build/separatedArrayParser.test.d.ts +1 -0
- package/build/separatedArrayParser.test.js +21 -0
- package/build/sequenceBuffer.d.ts +10 -0
- package/build/sequenceBuffer.js +54 -2
- package/build/sequenceBuffer.test.js +57 -0
- package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
- package/build/sequenceTerminatedSequenceParser.js +32 -0
- package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
- package/build/sequenceTerminatedSequenceParser.test.js +37 -0
- package/build/skipParser.d.ts +1 -1
- package/build/skipParser.js +4 -2
- package/build/skipToParser.d.ts +2 -0
- package/build/skipToParser.js +11 -0
- package/build/sliceBoundedParser.d.ts +1 -1
- package/build/sliceBoundedParser.js +7 -2
- package/build/sliceBoundedParser.test.js +35 -1
- package/build/smali.d.ts +1 -0
- package/build/smali.js +17 -0
- package/build/smaliParser.d.ts +12 -0
- package/build/smaliParser.js +656 -0
- package/build/smaliParser.test.d.ts +1 -0
- package/build/smaliParser.test.js +115 -0
- package/build/terminatedArrayParser.d.ts +3 -1
- package/build/terminatedArrayParser.js +79 -2
- package/build/terminatedArrayParser.test.d.ts +1 -0
- package/build/terminatedArrayParser.test.js +131 -0
- package/build/toAsyncIterable.d.ts +1 -0
- package/build/toAsyncIterable.js +7 -0
- package/build/toAsyncIterator.d.ts +1 -0
- package/build/toAsyncIterator.js +33 -0
- package/build/tupleParser.d.ts +4 -0
- package/build/tupleParser.js +1 -5
- package/build/unionParser.d.ts +2 -1
- package/build/unionParser.js +27 -12
- package/build/unionParser.test.d.ts +1 -0
- package/build/unionParser.test.js +60 -0
- package/build/zipParser.d.ts +7 -2
- package/build/zipParser.js +36 -12
- package/build/zipUnparser.d.ts +4 -1
- package/build/zipUnparser.js +55 -26
- package/build/zipUnparser.test.js +14 -14
- package/package.json +23 -7
- package/src/allSettledStream.test.ts +40 -0
- package/src/allSettledStream.ts +47 -15
- package/src/androidPackage.ts +48 -0
- package/src/{apkParser.test.ts → androidPackageParser.test.ts} +6 -7
- package/src/{apkParser.test.ts.md → androidPackageParser.test.ts.md} +4 -4
- package/src/androidPackageParser.test.ts.snap +0 -0
- package/src/androidPackageParser.ts +440 -0
- package/src/androidPackageUnparser.test.ts +36 -0
- package/src/androidPackageUnparser.ts +120 -0
- package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
- package/src/arrayParser.test.ts +3 -3
- package/src/backsmali.ts +30 -0
- package/src/bsonParser.ts +13 -2
- package/src/customInvariant.ts +1 -1
- package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
- package/src/dalvikBytecodeParser.ts +2074 -0
- package/src/dalvikExecutable.ts +220 -0
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
- package/src/dalvikExecutableParser/typeParsers.ts +65 -0
- package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
- package/src/dalvikExecutableParser.test.ts +89 -0
- package/src/dalvikExecutableParser.test.ts.md +634 -0
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +2768 -0
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
- package/src/debugLogInputParser.ts +28 -0
- package/src/debugLogParser.ts +19 -3
- package/src/disjunctionParser.ts +10 -5
- package/src/elementTerminatedArrayParser.test.ts +99 -0
- package/src/elementTerminatedArrayParser.ts +31 -0
- package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
- package/src/elementTerminatedSequenceArrayParser.ts +52 -0
- package/src/elementTerminatedSequenceParser.test.ts +54 -0
- package/src/elementTerminatedSequenceParser.ts +43 -0
- package/src/exactElementParser.ts +17 -11
- package/src/exactSequenceParser.ts +23 -2
- package/src/fetchCid.ts +125 -0
- package/src/fixedLengthSequenceParser.test.ts +77 -0
- package/src/fixedLengthSequenceParser.ts +28 -1
- package/src/hasExecutable.ts +11 -0
- package/src/highResolutionTimer.ts +49 -0
- package/src/inputReader.test.ts +209 -0
- package/src/inputReader.ts +75 -0
- package/src/inputReaderState.ts +33 -0
- package/src/inspect.ts +9 -0
- package/src/javaKeyStoreParser.test.ts +2 -3
- package/src/jsonParser.ts +13 -25
- package/src/leb128Parser.test.ts +171 -0
- package/src/leb128Parser.ts +125 -0
- package/src/lookaheadParser.ts +19 -0
- package/src/negativeLookaheadParser.test.ts +53 -0
- package/src/negativeLookaheadParser.ts +26 -14
- package/src/nonEmptyArrayParser.test.ts +20 -0
- package/src/nonEmptyArrayParser.ts +44 -0
- package/src/optionalParser.ts +1 -0
- package/src/parser.test.ts +131 -12
- package/src/parser.test.ts.md +21 -21
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +149 -45
- package/src/parserAccessorParser.ts +12 -2
- package/src/parserConsumedSequenceParser.ts +25 -16
- package/src/parserContext.test.ts +31 -0
- package/src/parserContext.ts +109 -37
- package/src/parserCreatorCompose.ts +20 -2
- package/src/parserError.ts +9 -6
- package/src/parserInputCompanion.ts +55 -0
- package/src/promiseCompose.ts +17 -3
- package/src/promiseSettled.ts +6 -0
- package/src/separatedArrayParser.test.ts +34 -0
- package/src/separatedArrayParser.ts +55 -0
- package/src/sequenceBuffer.test.ts +70 -0
- package/src/sequenceBuffer.ts +88 -2
- package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
- package/src/sequenceTerminatedSequenceParser.ts +62 -0
- package/src/skipParser.ts +7 -5
- package/src/skipToParser.ts +16 -0
- package/src/sliceBoundedParser.test.ts +43 -1
- package/src/sliceBoundedParser.ts +19 -1
- package/src/smali.ts +24 -0
- package/src/smaliParser.test.ts +132 -0
- package/src/smaliParser.test.ts.md +2320 -0
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +1166 -0
- package/src/terminatedArrayParser.test.ts +258 -0
- package/src/terminatedArrayParser.ts +108 -3
- package/src/toAsyncIterable.ts +7 -0
- package/src/toAsyncIterator.ts +48 -0
- package/src/tupleParser.ts +8 -5
- package/src/unionParser.test.ts +79 -0
- package/src/unionParser.ts +44 -16
- package/src/zipParser.ts +77 -18
- package/src/zipUnparser.test.ts +18 -18
- package/src/zipUnparser.ts +88 -27
- package/build/apk.d.ts +0 -39
- package/build/apkParser.d.ts +0 -16
- package/build/apkParser.js +0 -164
- package/build/apkUnparser.d.ts +0 -4
- package/build/apkUnparser.test.js +0 -26
- package/build/arbitraryDosDate.d.ts +0 -2
- package/build/arbitraryDosDate.js +0 -8
- package/build/arbitraryZipEntry.d.ts +0 -3
- package/build/arbitraryZipEntry.js +0 -26
- package/build/createDisjunctionParser.d.ts +0 -2
- package/build/createDisjunctionParser.js +0 -47
- package/build/createExactParser.d.ts +0 -2
- package/build/createExactParser.js +0 -12
- package/build/createSequentialUnionParser.d.ts +0 -2
- package/build/createSequentialUnionParser.js +0 -69
- package/build/fixedLengthChunkParser.d.ts +0 -2
- package/build/fixedLengthChunkParser.js +0 -12
- package/build/fixedLengthParser.d.ts +0 -2
- package/build/fixedLengthParser.js +0 -12
- package/build/inputChunkBuffer.d.ts +0 -15
- package/build/inputChunkBuffer.js +0 -40
- package/build/inputChunkBuffer.test.js +0 -34
- package/build/inputCompanion.d.ts +0 -18
- package/build/inputCompanion.js +0 -28
- package/build/invariantDefined.d.ts +0 -1
- package/build/invariantDefined.js +0 -5
- package/build/invariantIdentity.d.ts +0 -3
- package/build/invariantIdentity.js +0 -5
- package/build/javaKeystoreParser.d.ts +0 -2
- package/build/javaKeystoreParser.js +0 -7
- package/build/jsonParser2.d.ts +0 -3
- package/build/jsonParser2.js +0 -52
- package/build/jsonParser2.test.js +0 -22
- package/build/negativeLookahead.d.ts +0 -2
- package/build/negativeLookahead.js +0 -18
- package/build/parserCompose.d.ts +0 -3
- package/build/parserCompose.js +0 -7
- package/build/parserImplementationInvariantInvariant.d.ts +0 -3
- package/build/parserImplementationInvariantInvariant.js +0 -15
- package/build/parserInvariant.d.ts +0 -4
- package/build/parserInvariant.js +0 -11
- package/build/promiseFish.d.ts +0 -1
- package/build/promiseFish.js +0 -3
- package/build/sequenceParser.d.ts +0 -3
- package/build/sequenceParser.js +0 -10
- package/build/terminatedSequenceParser.d.ts +0 -2
- package/build/terminatedSequenceParser.js +0 -24
- package/build/unparserInputCompanion.d.ts +0 -15
- package/build/unparserInputCompanion.js +0 -13
- package/build/zipEntry.d.ts +0 -28
- package/build/zipFile.d.ts +0 -32
- package/build/zipFileEntry.d.ts +0 -6
- package/src/apk.ts +0 -48
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +0 -392
- package/src/apkUnparser.test.ts +0 -37
- package/src/apkUnparser.ts +0 -120
- package/src/invariantDefined.ts +0 -6
- package/src/invariantIdentity.ts +0 -8
- /package/build/{apk.js → androidPackage.js} +0 -0
- /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
- /package/build/{apkUnparser.test.d.ts → androidPackageUnparser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.d.ts → dalvikExecutableParser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.js → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
- /package/build/{inputChunkBuffer.test.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
- /package/build/{jsonParser2.test.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.js → fixedLengthSequenceParser.test.d.ts} +0 -0
- /package/build/{zipEntry.js → leb128Parser.test.d.ts} +0 -0
- /package/build/{zipFile.js → negativeLookaheadParser.test.d.ts} +0 -0
- /package/build/{zipFileEntry.js → nonEmptyArrayParser.test.d.ts} +0 -0
package/src/zipParser.ts
CHANGED
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
type ZipFileEntry,
|
|
19
19
|
} from './zip.js';
|
|
20
20
|
import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
|
|
21
|
+
import { createNegativeLookaheadParser } from './negativeLookaheadParser.js';
|
|
22
|
+
import { createSequenceTerminatedSequenceParser } from './sequenceTerminatedSequenceParser.js';
|
|
21
23
|
|
|
22
24
|
// https://pkwaredownloads.blob.core.windows.net/pem/APPNOTE.txt
|
|
23
25
|
|
|
@@ -65,7 +67,7 @@ const zipCompressionMethodParser: Parser<ZipCompression, Uint8Array> = promiseCo
|
|
|
65
67
|
},
|
|
66
68
|
);
|
|
67
69
|
|
|
68
|
-
type ZipLocalFileHeader = {
|
|
70
|
+
export type ZipLocalFileHeader = {
|
|
69
71
|
versionNeededToExtract: number;
|
|
70
72
|
generalPurposeBitFlag: number;
|
|
71
73
|
compressionMethod: ZipCompression;
|
|
@@ -78,8 +80,10 @@ type ZipLocalFileHeader = {
|
|
|
78
80
|
extraField: Uint8Array;
|
|
79
81
|
};
|
|
80
82
|
|
|
83
|
+
const zipLocalFileHeaderSignatureParser = createExactSequenceParser<Uint8Array>(Buffer.from('504b0304', 'hex'));
|
|
84
|
+
|
|
81
85
|
const zipLocalFileHeaderParser_ = createTupleParser([
|
|
82
|
-
|
|
86
|
+
zipLocalFileHeaderSignatureParser,
|
|
83
87
|
uint16LEParser,
|
|
84
88
|
uint16LEParser,
|
|
85
89
|
zipCompressionMethodParser,
|
|
@@ -133,31 +137,84 @@ const zipEncryptionHeaderParser: Parser<unknown, Uint8Array> = async parserConte
|
|
|
133
137
|
parserContext.invariant(false, 'Not implemented');
|
|
134
138
|
};
|
|
135
139
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
type ZipDataDescriptor = {
|
|
141
|
+
crc32: number;
|
|
142
|
+
compressedSize: number;
|
|
143
|
+
uncompressedSize: number;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const zipDataDescriptorSignature: Uint8Array = Buffer.from('504b0708', 'hex');
|
|
147
|
+
const zipDataDescriptorSignatureParser = createExactSequenceParser<Uint8Array>(
|
|
148
|
+
zipDataDescriptorSignature
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const zipDataDescriptorParser: Parser<ZipDataDescriptor, Uint8Array> = promiseCompose(
|
|
152
|
+
createTupleParser([
|
|
153
|
+
createNegativeLookaheadParser(
|
|
154
|
+
zipLocalFileHeaderSignatureParser,
|
|
155
|
+
),
|
|
156
|
+
// FIXME: optional in spec
|
|
157
|
+
//createOptionalParser(zipDataDescriptorSignatureParser),
|
|
158
|
+
zipDataDescriptorSignatureParser,
|
|
159
|
+
uint32LEParser,
|
|
160
|
+
uint32LEParser,
|
|
161
|
+
uint32LEParser,
|
|
162
|
+
]),
|
|
163
|
+
([
|
|
164
|
+
_notZipLocalFileHeaderSignature,
|
|
165
|
+
_zipDataDescriptorSignature,
|
|
166
|
+
crc32,
|
|
167
|
+
compressedSize,
|
|
168
|
+
uncompressedSize,
|
|
169
|
+
]) => ({
|
|
170
|
+
crc32,
|
|
171
|
+
compressedSize,
|
|
172
|
+
uncompressedSize,
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
setParserName(zipDataDescriptorParser, 'zipDataDescriptorParser');
|
|
144
177
|
|
|
145
178
|
export type ZipLocalFile = {
|
|
146
179
|
zipLocalFileHeader: ZipLocalFileHeader;
|
|
147
180
|
zipEncryptionHeader: unknown;
|
|
148
181
|
compressedData: Uint8Array;
|
|
149
|
-
zipDataDescriptor:
|
|
182
|
+
zipDataDescriptor: undefined | ZipDataDescriptor;
|
|
150
183
|
};
|
|
151
184
|
|
|
152
185
|
export const zipLocalFileParser: Parser<ZipLocalFile, Uint8Array> = promiseCompose(
|
|
153
186
|
parserCreatorCompose(
|
|
154
187
|
() => zipLocalFileHeaderParser,
|
|
155
|
-
zipLocalFileHeader =>
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
188
|
+
zipLocalFileHeader => {
|
|
189
|
+
const sizeInDataDescriptor = Boolean(
|
|
190
|
+
zipLocalFileHeader.generalPurposeBitFlag & 0b0000_0000_0000_1000
|
|
191
|
+
&& zipLocalFileHeader.crc32 === 0
|
|
192
|
+
&& zipLocalFileHeader.compressedSize === 0
|
|
193
|
+
&& zipLocalFileHeader.uncompressedSize === 0
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return createTupleParser([
|
|
197
|
+
async () => zipLocalFileHeader,
|
|
198
|
+
createOptionalParser(zipEncryptionHeaderParser),
|
|
199
|
+
(
|
|
200
|
+
sizeInDataDescriptor
|
|
201
|
+
? createSequenceTerminatedSequenceParser(
|
|
202
|
+
zipDataDescriptorSignature,
|
|
203
|
+
{
|
|
204
|
+
consumeTerminator: false,
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
: createFixedLengthSequenceParser(zipLocalFileHeader.compressedSize)
|
|
208
|
+
),
|
|
209
|
+
(
|
|
210
|
+
sizeInDataDescriptor
|
|
211
|
+
? (<T>(parser: T): T => parser)
|
|
212
|
+
: createOptionalParser
|
|
213
|
+
)(
|
|
214
|
+
zipDataDescriptorParser
|
|
215
|
+
),
|
|
216
|
+
]);
|
|
217
|
+
},
|
|
161
218
|
)(),
|
|
162
219
|
([
|
|
163
220
|
zipLocalFileHeader,
|
|
@@ -373,7 +430,7 @@ const zipEndOfCentralDirectoryRecordParser_ = createTupleParser([
|
|
|
373
430
|
zipFileCommentParser,
|
|
374
431
|
]);
|
|
375
432
|
|
|
376
|
-
setParserName(zipEndOfCentralDirectoryRecordParser_, '
|
|
433
|
+
setParserName(zipEndOfCentralDirectoryRecordParser_, 'zipEndOfCentralDirectoryRecordParser_');
|
|
377
434
|
|
|
378
435
|
export const zipEndOfCentralDirectoryRecordParser: Parser<ZipEndOfCentralDirectoryRecord, Uint8Array> = promiseCompose(
|
|
379
436
|
zipEndOfCentralDirectoryRecordParser_,
|
|
@@ -397,6 +454,8 @@ export const zipEndOfCentralDirectoryRecordParser: Parser<ZipEndOfCentralDirecto
|
|
|
397
454
|
}),
|
|
398
455
|
);
|
|
399
456
|
|
|
457
|
+
setParserName(zipEndOfCentralDirectoryRecordParser, 'zipEndOfCentralDirectoryRecordParser');
|
|
458
|
+
|
|
400
459
|
const zipParser_ = createTupleParser([
|
|
401
460
|
createArrayParser(zipLocalFileParser),
|
|
402
461
|
createOptionalParser(zipArchiveDecryptionHeaderParser),
|
package/src/zipUnparser.test.ts
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import { testProp } from '@fast-check/ava';
|
|
1
|
+
import { fc, testProp } from '@fast-check/ava';
|
|
2
2
|
import { temporaryFile } from 'tempy';
|
|
3
3
|
import { execa } from 'execa';
|
|
4
4
|
import fsPromises from 'node:fs/promises';
|
|
5
5
|
import { runUnparser } from './unparser.js';
|
|
6
|
-
import {
|
|
6
|
+
import { createZipUnparser } from './zipUnparser.js';
|
|
7
7
|
import { uint8ArrayUnparserOutputCompanion } from './unparserOutputCompanion.js';
|
|
8
8
|
import { runParser } from './parser.js';
|
|
9
9
|
import { zipParser } from './zipParser.js';
|
|
10
10
|
import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
11
11
|
import { arbitraryZip } from './arbitraryZip.js';
|
|
12
|
-
|
|
13
|
-
async function hasExecutable(executable: string) {
|
|
14
|
-
const hasExecutable = execa(executable).then(() => true, () => false);
|
|
15
|
-
|
|
16
|
-
if (!hasExecutable) {
|
|
17
|
-
console.warn(`Executable %o not found`, executable);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return hasExecutable;
|
|
21
|
-
}
|
|
12
|
+
import { hasExecutable } from './hasExecutable.js';
|
|
22
13
|
|
|
23
14
|
const hasZipinfoPromise = hasExecutable('zipinfo');
|
|
24
15
|
const has7zPromise = hasExecutable('7z');
|
|
@@ -57,21 +48,30 @@ testProp(
|
|
|
57
48
|
'zip',
|
|
58
49
|
[
|
|
59
50
|
arbitraryZip,
|
|
51
|
+
fc.record({
|
|
52
|
+
dataDescriptor: fc.boolean(),
|
|
53
|
+
}),
|
|
60
54
|
],
|
|
61
|
-
async (t, zip) => {
|
|
62
|
-
const
|
|
63
|
-
const actual = await runParser(zipParser, actualStream, uint8ArrayParserInputCompanion);
|
|
55
|
+
async (t, zip, options) => {
|
|
56
|
+
const zipUnparser = createZipUnparser(options);
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
{
|
|
59
|
+
const zipStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
return;
|
|
61
|
+
await fsPromises.writeFile('/tmp/zip.zip', zipStream);
|
|
69
62
|
}
|
|
70
63
|
|
|
64
|
+
const actualStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
|
|
65
|
+
const actual = await runParser(zipParser, actualStream, uint8ArrayParserInputCompanion);
|
|
66
|
+
|
|
67
|
+
t.deepEqual(actual, zip);
|
|
68
|
+
|
|
71
69
|
const hasZipinfo = await hasZipinfoPromise;
|
|
72
70
|
const has7z = await has7zPromise;
|
|
73
71
|
|
|
74
72
|
if (!hasZipinfo && !has7z) {
|
|
73
|
+
t.pass('no zipinfo or 7z, skipping zipfile check');
|
|
74
|
+
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
package/src/zipUnparser.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Unparser } from "./unparser.js";
|
|
|
3
3
|
import { Zip, ZipEntry, ZipFileEntry } from "./zip.js";
|
|
4
4
|
import { Readable } from 'node:stream';
|
|
5
5
|
import { pipeline } from 'node:stream/promises';
|
|
6
|
-
import { ZipEndOfCentralDirectoryRecord } from './zipParser.js';
|
|
6
|
+
import { ZipEndOfCentralDirectoryRecord, ZipLocalFileHeader } from './zipParser.js';
|
|
7
7
|
import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
|
|
8
8
|
|
|
9
9
|
const uint16LEUnparser: Unparser<number, Uint8Array> = async function * (uint16LE) {
|
|
@@ -66,7 +66,56 @@ export const zipEndOfCentralDirectoryRecordUnparser: Unparser<ZipEndOfCentralDir
|
|
|
66
66
|
yield * uint16LEPrefixedStringUnparser(zipEndOfCentralDirectoryRecord.zipFileComment, unparserContext);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
const zipDataDescriptorUnparser: Unparser<{
|
|
70
|
+
crc32: number;
|
|
71
|
+
compressedSize: number;
|
|
72
|
+
uncompressedSize: number;
|
|
73
|
+
}, Uint8Array> = async function * ({
|
|
74
|
+
crc32,
|
|
75
|
+
compressedSize,
|
|
76
|
+
uncompressedSize,
|
|
77
|
+
}, unparserContext) {
|
|
78
|
+
yield Buffer.from('504b0708', 'hex');
|
|
79
|
+
yield * uint32LEUnparser(crc32, unparserContext);
|
|
80
|
+
yield * uint32LEUnparser(compressedSize, unparserContext);
|
|
81
|
+
yield * uint32LEUnparser(uncompressedSize, unparserContext);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const zipLocalFileHeaderUnparser: Unparser<ZipLocalFileHeader, Uint8Array> = async function * ({
|
|
85
|
+
versionNeededToExtract,
|
|
86
|
+
generalPurposeBitFlag,
|
|
87
|
+
compressionMethod,
|
|
88
|
+
lastModifiedFile,
|
|
89
|
+
crc32,
|
|
90
|
+
compressedSize,
|
|
91
|
+
uncompressedSize,
|
|
92
|
+
|
|
93
|
+
filePath,
|
|
94
|
+
extraField,
|
|
95
|
+
}, unparserContext) {
|
|
96
|
+
yield Buffer.from('504b0304', 'hex');
|
|
97
|
+
|
|
98
|
+
yield * uint16LEUnparser(versionNeededToExtract, unparserContext);
|
|
99
|
+
yield * uint16LEUnparser(generalPurposeBitFlag, unparserContext);
|
|
100
|
+
yield * zipCompressionMethodUnparser(compressionMethod, unparserContext);
|
|
101
|
+
yield * dosDateTimeUnparser(lastModifiedFile, unparserContext);
|
|
102
|
+
yield * uint32LEUnparser(crc32, unparserContext);
|
|
103
|
+
yield * uint32LEUnparser(compressedSize, unparserContext);
|
|
104
|
+
yield * uint32LEUnparser(uncompressedSize, unparserContext);
|
|
105
|
+
|
|
106
|
+
const filePathBuffer = Buffer.from(filePath, 'utf8');
|
|
107
|
+
|
|
108
|
+
yield * uint16LEUnparser(filePathBuffer.length, unparserContext);
|
|
109
|
+
yield * uint16LEUnparser(extraField.length, unparserContext);
|
|
110
|
+
yield filePathBuffer;
|
|
111
|
+
yield extraField;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const createZipUnparser = ({
|
|
115
|
+
dataDescriptor = false,
|
|
116
|
+
}: {
|
|
117
|
+
dataDescriptor?: boolean;
|
|
118
|
+
} = {}): Unparser<Zip, Uint8Array> => async function * (zip, unparserContext) {
|
|
70
119
|
const compressedContentByZipFileEntry = new Map<ZipFileEntry, undefined | Promise<Uint8Array>>(
|
|
71
120
|
zip.entries.flatMap(zipEntry => {
|
|
72
121
|
if (zipEntry.type !== 'file') {
|
|
@@ -100,44 +149,54 @@ export const zipUnparser: Unparser<Zip, Uint8Array> = async function * (zip, unp
|
|
|
100
149
|
for (const zipEntry of zip.entries) {
|
|
101
150
|
localHeaderPositionByZipEntry.set(zipEntry, unparserContext.position);
|
|
102
151
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
yield * uint16LEUnparser(10, unparserContext); // version needed to extract
|
|
106
|
-
yield * uint16LEUnparser(0, unparserContext); // general purpose bit flag
|
|
152
|
+
const filePath = filePathByZipEntry.get(zipEntry)!;
|
|
107
153
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
154
|
+
const zipLocalFileHeader: ZipLocalFileHeader = {
|
|
155
|
+
versionNeededToExtract: 20,
|
|
156
|
+
generalPurposeBitFlag: 0,
|
|
157
|
+
compressionMethod: 'store',
|
|
158
|
+
lastModifiedFile: zipEntry.date,
|
|
159
|
+
crc32: 0,
|
|
160
|
+
compressedSize: 0,
|
|
161
|
+
uncompressedSize: 0,
|
|
162
|
+
filePath,
|
|
163
|
+
extraField: Buffer.alloc(0),
|
|
164
|
+
};
|
|
113
165
|
|
|
114
|
-
|
|
166
|
+
let shouldWriteDataDescriptor = false;
|
|
115
167
|
|
|
116
168
|
if (zipEntry.type === 'file') {
|
|
117
169
|
const compressedContent = await compressedContentByZipFileEntry.get(zipEntry)!;
|
|
118
170
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
yield * uint32LEUnparser(0, unparserContext);
|
|
124
|
-
yield * uint32LEUnparser(0, unparserContext);
|
|
125
|
-
yield * uint32LEUnparser(0, unparserContext);
|
|
126
|
-
}
|
|
171
|
+
zipLocalFileHeader.compressionMethod = zipEntry.compression;
|
|
172
|
+
zipLocalFileHeader.crc32 = 0; // TODO
|
|
173
|
+
zipLocalFileHeader.compressedSize = compressedContent.length;
|
|
174
|
+
zipLocalFileHeader.uncompressedSize = zipEntry.content.length;
|
|
127
175
|
|
|
128
|
-
|
|
176
|
+
if (dataDescriptor) {
|
|
177
|
+
shouldWriteDataDescriptor = true;
|
|
129
178
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
179
|
+
zipLocalFileHeader.generalPurposeBitFlag |= 0b0000_0000_0000_1000;
|
|
180
|
+
zipLocalFileHeader.crc32 = 0;
|
|
181
|
+
zipLocalFileHeader.compressedSize = 0;
|
|
182
|
+
zipLocalFileHeader.uncompressedSize = 0;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
yield * zipLocalFileHeaderUnparser(zipLocalFileHeader, unparserContext);
|
|
136
187
|
|
|
137
188
|
if (zipEntry.type === 'file') {
|
|
138
189
|
const compressedContent = await compressedContentByZipFileEntry.get(zipEntry)!;
|
|
139
190
|
|
|
140
191
|
yield compressedContent;
|
|
192
|
+
|
|
193
|
+
if (shouldWriteDataDescriptor) {
|
|
194
|
+
yield * zipDataDescriptorUnparser({
|
|
195
|
+
crc32: zipLocalFileHeader.crc32,
|
|
196
|
+
compressedSize: zipLocalFileHeader.compressedSize,
|
|
197
|
+
uncompressedSize: zipLocalFileHeader.uncompressedSize,
|
|
198
|
+
}, unparserContext);
|
|
199
|
+
}
|
|
141
200
|
}
|
|
142
201
|
}
|
|
143
202
|
|
|
@@ -237,3 +296,5 @@ export const zipUnparser: Unparser<Zip, Uint8Array> = async function * (zip, unp
|
|
|
237
296
|
zipFileComment: zip.comment,
|
|
238
297
|
}, unparserContext);
|
|
239
298
|
}
|
|
299
|
+
|
|
300
|
+
export const zipUnparser = createZipUnparser();
|
package/build/apk.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { type Zip } from './zip.js';
|
|
2
|
-
export type ApkSigningBlockPair = {
|
|
3
|
-
id: number;
|
|
4
|
-
value: Uint8Array;
|
|
5
|
-
};
|
|
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[];
|
|
18
|
-
zeroPaddingLength?: number;
|
|
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 = {
|
|
33
|
-
pairs: ApkSigningBlockPair[];
|
|
34
|
-
signatureV2?: ApkSignatureV2;
|
|
35
|
-
zeroPaddingLength?: number;
|
|
36
|
-
};
|
|
37
|
-
export type Apk = Zip & {
|
|
38
|
-
signingBlock?: ApkSigningBlock;
|
|
39
|
-
};
|
package/build/apkParser.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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>;
|
|
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
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
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';
|
|
15
|
-
// https://source.android.com/docs/security/features/apksigning/v2#apk-signing-block
|
|
16
|
-
const uint32LEParser = promiseCompose(createFixedLengthSequenceParser(4), array => Buffer.from(array).readUInt32LE());
|
|
17
|
-
setParserName(uint32LEParser, 'uint32LEParser');
|
|
18
|
-
const uint64LEParser = promiseCompose(createFixedLengthSequenceParser(8), array => Buffer.from(array).readBigUInt64LE());
|
|
19
|
-
setParserName(uint64LEParser, 'uint64LEParser');
|
|
20
|
-
const createUint32LengthPrefixedParser = (createInnerParser) => parserCreatorCompose(() => uint32LEParser, length => createInnerParser(length))();
|
|
21
|
-
const createUint64LengthPrefixedParser = (createInnerParser) => parserCreatorCompose(() => uint64LEParser, length => createInnerParser(length))();
|
|
22
|
-
const createUint32LengthPrefixedSliceBoundedParser = (innerParser) => createUint32LengthPrefixedParser(length => createSliceBoundedParser(innerParser, length));
|
|
23
|
-
const createUint32LengthPrefixedSliceBoundedArrayParser = (innerParser) => createUint32LengthPrefixedSliceBoundedParser(createArrayParser(innerParser));
|
|
24
|
-
const createApkSigningBlockZeroPaddingPairInnerParser = (length) => promiseCompose(createTupleParser([
|
|
25
|
-
createExactSequenceParser(Buffer.from('77657242', 'hex')),
|
|
26
|
-
createFixedLengthSequenceParser(length - 4),
|
|
27
|
-
]), ([_magic, zeroPadding]) => ({ type: 'zeroPadding', length: zeroPadding.length }));
|
|
28
|
-
const createApkSigningBlockSignatureV2PairInnerParser = (length) => {
|
|
29
|
-
const apkSigningBlockSignatureV2PairInnerParser = promiseCompose(createTupleParser([
|
|
30
|
-
createExactSequenceParser(Buffer.from('1a870971', 'hex')),
|
|
31
|
-
apkSignatureV2SignersParser,
|
|
32
|
-
]), ([_magic, signers = []]) => ({ type: 'signatureV2', signers }));
|
|
33
|
-
return setParserName(apkSigningBlockSignatureV2PairInnerParser, 'apkSigningBlockSignatureV2PairInnerParser');
|
|
34
|
-
};
|
|
35
|
-
const createApkSigningBlockGenericPairInnerParser = (length) => promiseCompose(createTupleParser([
|
|
36
|
-
uint32LEParser,
|
|
37
|
-
createFixedLengthSequenceParser(length - 4),
|
|
38
|
-
]), ([id, value]) => ({ type: 'generic', pair: { id, value } }));
|
|
39
|
-
const createApkSigningBlockPairInnerParser = (length) => createDisjunctionParser([
|
|
40
|
-
createApkSigningBlockZeroPaddingPairInnerParser(length),
|
|
41
|
-
createApkSigningBlockSignatureV2PairInnerParser(length),
|
|
42
|
-
createApkSigningBlockGenericPairInnerParser(length),
|
|
43
|
-
]);
|
|
44
|
-
const apkSigningBlockPairParser = createUint64LengthPrefixedParser(length => createApkSigningBlockPairInnerParser(Number(length)));
|
|
45
|
-
setParserName(apkSigningBlockPairParser, 'apkSigningBlockPairParser');
|
|
46
|
-
const apkSigningBlockPairsParser = createArrayParser(apkSigningBlockPairParser);
|
|
47
|
-
export const apkSigningBlockParser = createUint64LengthPrefixedParser(sizeOfBlock => promiseCompose(createTupleParser([
|
|
48
|
-
apkSigningBlockPairsParser,
|
|
49
|
-
uint64LEParser,
|
|
50
|
-
createExactSequenceParser(Buffer.from('APK Sig Block 42', 'utf8')),
|
|
51
|
-
]), async ([pairs, sizeOfBlockRepeated, _magic]) => {
|
|
52
|
-
invariant(sizeOfBlock === sizeOfBlockRepeated, 'Size of block mismatch: %s !== %s.', sizeOfBlock, sizeOfBlockRepeated);
|
|
53
|
-
const zeroPaddingPair = pairs.find(pair => pair.type === 'zeroPadding');
|
|
54
|
-
const signatureV2Pair = pairs.find(pair => pair.type === 'signatureV2');
|
|
55
|
-
const genericPairs = (pairs
|
|
56
|
-
.filter(pair => (pair !== zeroPaddingPair
|
|
57
|
-
&& pair !== signatureV2Pair))
|
|
58
|
-
.map(pair => {
|
|
59
|
-
invariant(pair.type === 'generic', 'Expected generic pair, got %s.', pair.type);
|
|
60
|
-
return pair.pair;
|
|
61
|
-
}));
|
|
62
|
-
return {
|
|
63
|
-
zeroPaddingLength: zeroPaddingPair?.length,
|
|
64
|
-
signatureV2: signatureV2Pair ? {
|
|
65
|
-
signers: signatureV2Pair?.signers,
|
|
66
|
-
} : undefined,
|
|
67
|
-
pairs: genericPairs,
|
|
68
|
-
};
|
|
69
|
-
}));
|
|
70
|
-
const apkSignatureV2DigestParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
|
|
71
|
-
uint32LEParser,
|
|
72
|
-
createUint32LengthPrefixedParser(digestLength => createFixedLengthSequenceParser(digestLength)),
|
|
73
|
-
]), ([signatureAlgorithmId, digest]) => ({ signatureAlgorithmId, digest })));
|
|
74
|
-
const apkSignatureV2DigestsParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2DigestParser);
|
|
75
|
-
const apkSignatureV2CertificateParser = createUint32LengthPrefixedParser(certificateLength => createFixedLengthSequenceParser(certificateLength));
|
|
76
|
-
const apkSignatureV2CertificatesParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2CertificateParser);
|
|
77
|
-
const apkSignatureV2AdditionalAttributeParser = createUint32LengthPrefixedParser(pairLength => promiseCompose(createTupleParser([
|
|
78
|
-
uint32LEParser,
|
|
79
|
-
createFixedLengthSequenceParser(pairLength - 4),
|
|
80
|
-
]), ([id, value]) => ({ id, value })));
|
|
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,
|
|
88
|
-
createArrayParser(createExactElementParser(0)),
|
|
89
|
-
]), ([digests, certificates, additionalAttributes, zeroPadding,]) => ({
|
|
90
|
-
digests,
|
|
91
|
-
certificates,
|
|
92
|
-
additionalAttributes,
|
|
93
|
-
zeroPaddingLength: zeroPadding.length,
|
|
94
|
-
})));
|
|
95
|
-
setParserName(apkSignatureV2SignedDataParser, 'apkSignatureV2SignedDataParser');
|
|
96
|
-
const apkSignatureV2SignatureParser = createUint32LengthPrefixedParser(signatureLength => promiseCompose(createTupleParser([
|
|
97
|
-
uint32LEParser,
|
|
98
|
-
createUint32LengthPrefixedParser(signatureLength => createFixedLengthSequenceParser(signatureLength)),
|
|
99
|
-
]), ([signatureAlgorithmId, signature,]) => ({
|
|
100
|
-
signatureAlgorithmId,
|
|
101
|
-
signature,
|
|
102
|
-
})));
|
|
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,]) => ({
|
|
112
|
-
signedData,
|
|
113
|
-
signatures,
|
|
114
|
-
publicKey,
|
|
115
|
-
})));
|
|
116
|
-
setParserName(apkSignatureV2SignerParser, 'apkSignatureV2SignerParser');
|
|
117
|
-
const apkSignatureV2SignersParser = createUint32LengthPrefixedSliceBoundedArrayParser(apkSignatureV2SignerParser);
|
|
118
|
-
setParserName(apkSignatureV2SignersParser, 'apkSignatureV2SignersParser');
|
|
119
|
-
const apkParser_ = createTupleParser([
|
|
120
|
-
createArrayParser(zipLocalFileParser),
|
|
121
|
-
createOptionalParser(zipArchiveDecryptionHeaderParser),
|
|
122
|
-
createOptionalParser(zipArchiveExtraDataRecordParser),
|
|
123
|
-
createOptionalParser(apkSigningBlockParser),
|
|
124
|
-
createArrayParser(zipCentralDirectoryHeaderParser),
|
|
125
|
-
createOptionalParser(zip64EndOfCentralDirectoryRecordParser),
|
|
126
|
-
createOptionalParser(zip64EndOfCentralDirectoryLocatorParser),
|
|
127
|
-
zipEndOfCentralDirectoryRecordParser,
|
|
128
|
-
]);
|
|
129
|
-
setParserName(apkParser_, 'apkParser_');
|
|
130
|
-
export const apkParser = promiseCompose(apkParser_, async ([zipLocalFiles, zipArchiveDecryptionHeader, zipArchiveExtraDataRecord, apkSigningBlock, zipCentralDirectoryHeaders, zip64EndOfCentralDirectoryRecord, zip64EndOfCentralDirectoryLocator, zipEndOfCentralDirectoryRecord,]) => {
|
|
131
|
-
const zip = await zipFromZipSegments({
|
|
132
|
-
zipLocalFiles,
|
|
133
|
-
zipCentralDirectoryHeaders,
|
|
134
|
-
zipEndOfCentralDirectoryRecord,
|
|
135
|
-
});
|
|
136
|
-
return {
|
|
137
|
-
...zip,
|
|
138
|
-
signingBlock: apkSigningBlock,
|
|
139
|
-
};
|
|
140
|
-
});
|
|
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/apkUnparser.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
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>;
|
|
@@ -1,26 +0,0 @@
|
|
|
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,26 +0,0 @@
|
|
|
1
|
-
import * as fc from 'fast-check';
|
|
2
|
-
export const arbitraryZipEntry = fc.letrec((tie) => ({
|
|
3
|
-
entry: fc.oneof(fc.record({
|
|
4
|
-
type: fc.constant('file'),
|
|
5
|
-
name: fc.string({ minLength: 1 }),
|
|
6
|
-
date: fc.date(),
|
|
7
|
-
comment: fc.uint8Array(),
|
|
8
|
-
unixPermissions: fc.integer(),
|
|
9
|
-
dosPermissions: fc.integer(),
|
|
10
|
-
compression: fc.oneof(fc.record({
|
|
11
|
-
type: fc.constant('store'),
|
|
12
|
-
}), fc.record({
|
|
13
|
-
type: fc.constant('deflate'),
|
|
14
|
-
level: fc.nat({ max: 9 }),
|
|
15
|
-
})),
|
|
16
|
-
content: fc.uint8Array(),
|
|
17
|
-
}), fc.record({
|
|
18
|
-
type: fc.constant('directory'),
|
|
19
|
-
name: fc.string({ minLength: 1 }),
|
|
20
|
-
date: fc.date(),
|
|
21
|
-
comment: fc.uint8Array(),
|
|
22
|
-
unixPermissions: fc.integer(),
|
|
23
|
-
dosPermissions: fc.integer(),
|
|
24
|
-
entries: fc.array(tie('entry')),
|
|
25
|
-
})),
|
|
26
|
-
})).entry;
|