@push.rocks/smartlinuxrepo 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.smartconfig.json +64 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/alpine/apkindex.d.ts +39 -0
- package/dist_ts/alpine/apkindex.js +211 -0
- package/dist_ts/alpine/pkginfo.d.ts +45 -0
- package/dist_ts/alpine/pkginfo.js +159 -0
- package/dist_ts/alpine/reader.d.ts +20 -0
- package/dist_ts/alpine/reader.js +89 -0
- package/dist_ts/arch/builder.d.ts +41 -0
- package/dist_ts/arch/builder.js +234 -0
- package/dist_ts/arch/reader.d.ts +16 -0
- package/dist_ts/arch/reader.js +271 -0
- package/dist_ts/arch/signer.d.ts +21 -0
- package/dist_ts/arch/signer.js +66 -0
- package/dist_ts/arch/vercmp.d.ts +12 -0
- package/dist_ts/arch/vercmp.js +170 -0
- package/dist_ts/debian/control.d.ts +22 -0
- package/dist_ts/debian/control.js +137 -0
- package/dist_ts/debian/gostring.d.ts +26 -0
- package/dist_ts/debian/gostring.js +145 -0
- package/dist_ts/debian/indexbuilder.d.ts +47 -0
- package/dist_ts/debian/indexbuilder.js +299 -0
- package/dist_ts/debian/mailaddress.d.ts +12 -0
- package/dist_ts/debian/mailaddress.js +736 -0
- package/dist_ts/debian/reader.d.ts +30 -0
- package/dist_ts/debian/reader.js +110 -0
- package/dist_ts/index.d.ts +23 -0
- package/dist_ts/index.js +18 -0
- package/dist_ts/plugins.d.ts +8 -0
- package/dist_ts/plugins.js +11 -0
- package/dist_ts/readers/ar.d.ts +31 -0
- package/dist_ts/readers/ar.js +87 -0
- package/dist_ts/readers/bytes.d.ts +58 -0
- package/dist_ts/readers/bytes.js +147 -0
- package/dist_ts/readers/bytesource.d.ts +40 -0
- package/dist_ts/readers/bytesource.js +154 -0
- package/dist_ts/readers/decompress.d.ts +43 -0
- package/dist_ts/readers/decompress.js +269 -0
- package/dist_ts/readers/gzipmember.d.ts +32 -0
- package/dist_ts/readers/gzipmember.js +176 -0
- package/dist_ts/readers/tar.d.ts +85 -0
- package/dist_ts/readers/tar.js +731 -0
- package/dist_ts/readers/text.d.ts +16 -0
- package/dist_ts/readers/text.js +96 -0
- package/dist_ts/rpm/builder.d.ts +28 -0
- package/dist_ts/rpm/builder.js +208 -0
- package/dist_ts/rpm/header.d.ts +138 -0
- package/dist_ts/rpm/header.js +546 -0
- package/dist_ts/rpm/reader.d.ts +20 -0
- package/dist_ts/rpm/reader.js +306 -0
- package/dist_ts/rpm/repoconfig.d.ts +15 -0
- package/dist_ts/rpm/repoconfig.js +38 -0
- package/dist_ts/rpm/repodata.d.ts +44 -0
- package/dist_ts/rpm/repodata.js +148 -0
- package/dist_ts/rpm/sign.d.ts +30 -0
- package/dist_ts/rpm/sign.js +183 -0
- package/dist_ts/rpm/updates.d.ts +38 -0
- package/dist_ts/rpm/updates.js +265 -0
- package/dist_ts/rpm/xml.d.ts +18 -0
- package/dist_ts/rpm/xml.js +90 -0
- package/dist_ts/shared/architecture.d.ts +8 -0
- package/dist_ts/shared/architecture.js +17 -0
- package/dist_ts/shared/errors.d.ts +38 -0
- package/dist_ts/shared/errors.js +22 -0
- package/dist_ts/shared/gopath.d.ts +13 -0
- package/dist_ts/shared/gopath.js +53 -0
- package/dist_ts/shared/gostrings.d.ts +14 -0
- package/dist_ts/shared/gostrings.js +29 -0
- package/dist_ts/shared/limits.d.ts +47 -0
- package/dist_ts/shared/limits.js +57 -0
- package/dist_ts/shared/types.d.ts +213 -0
- package/dist_ts/shared/types.js +13 -0
- package/dist_ts/shared/url.d.ts +18 -0
- package/dist_ts/shared/url.js +371 -0
- package/dist_ts/shared/validation.d.ts +21 -0
- package/dist_ts/shared/validation.js +58 -0
- package/dist_ts/signing/keys.d.ts +36 -0
- package/dist_ts/signing/keys.js +89 -0
- package/dist_ts/signing/openpgpframing.d.ts +33 -0
- package/dist_ts/signing/openpgpframing.js +93 -0
- package/dist_ts/signing/signers.d.ts +63 -0
- package/dist_ts/signing/signers.js +248 -0
- package/dist_ts/writers/gotar.d.ts +43 -0
- package/dist_ts/writers/gotar.js +218 -0
- package/license.md +19 -0
- package/package.json +56 -3
- package/readme.md +176 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/alpine/apkindex.ts +241 -0
- package/ts/alpine/pkginfo.ts +183 -0
- package/ts/alpine/reader.ts +96 -0
- package/ts/arch/builder.ts +283 -0
- package/ts/arch/reader.ts +307 -0
- package/ts/arch/signer.ts +70 -0
- package/ts/arch/vercmp.ts +188 -0
- package/ts/debian/control.ts +150 -0
- package/ts/debian/gostring.ts +150 -0
- package/ts/debian/indexbuilder.ts +355 -0
- package/ts/debian/mailaddress.ts +754 -0
- package/ts/debian/reader.ts +126 -0
- package/ts/index.ts +46 -0
- package/ts/plugins.ts +13 -0
- package/ts/readers/ar.ts +102 -0
- package/ts/readers/bytes.ts +182 -0
- package/ts/readers/bytesource.ts +164 -0
- package/ts/readers/decompress.ts +332 -0
- package/ts/readers/gzipmember.ts +209 -0
- package/ts/readers/tar.ts +835 -0
- package/ts/readers/text.ts +91 -0
- package/ts/rpm/builder.ts +253 -0
- package/ts/rpm/header.ts +628 -0
- package/ts/rpm/reader.ts +317 -0
- package/ts/rpm/repoconfig.ts +45 -0
- package/ts/rpm/repodata.ts +219 -0
- package/ts/rpm/sign.ts +200 -0
- package/ts/rpm/updates.ts +314 -0
- package/ts/rpm/xml.ts +101 -0
- package/ts/shared/architecture.ts +16 -0
- package/ts/shared/errors.ts +78 -0
- package/ts/shared/gopath.ts +54 -0
- package/ts/shared/gostrings.ts +31 -0
- package/ts/shared/limits.ts +93 -0
- package/ts/shared/types.ts +251 -0
- package/ts/shared/url.ts +387 -0
- package/ts/shared/validation.ts +71 -0
- package/ts/signing/keys.ts +110 -0
- package/ts/signing/openpgpframing.ts +115 -0
- package/ts/signing/signers.ts +315 -0
- package/ts/writers/gotar.ts +256 -0
- package/README.md +0 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ILinuxPackageLimits } from '../shared/limits.js';
|
|
2
|
+
import type { IDebianPackageRecord } from '../shared/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reads a `.deb` package in one pass into Gitea 28.2.0's record
|
|
5
|
+
* (`modules/packages/debian/metadata.go:92-163`).
|
|
6
|
+
*
|
|
7
|
+
* - The `ar` members are walked in order; `debian-binary` is not required.
|
|
8
|
+
* The first member whose name starts with `control.tar` (a trailing `/`
|
|
9
|
+
* stripped from the suffix) is decompressed: `control.tar`, `.gz`, `.xz` or
|
|
10
|
+
* `.zst`; any other suffix is `unsupported-compression`.
|
|
11
|
+
* - In it, the first regular entry whose base name is `control` is parsed. A
|
|
12
|
+
* control archive without one moves on to the next `ar` member, as Gitea
|
|
13
|
+
* does; none at all is `missing-field` (`control`).
|
|
14
|
+
* - The control member is decoded to the decoder's end on both paths, after
|
|
15
|
+
* the control file is parsed and when it holds none: a cut or corrupt
|
|
16
|
+
* control member is `truncated` or `malformed-archive` in every form, where
|
|
17
|
+
* Gitea, which stops at the control entry, accepts it. For a plain
|
|
18
|
+
* `control.tar` the end is the end of its `ar` member; the bytes after the
|
|
19
|
+
* tar end marker are read, not parsed.
|
|
20
|
+
* - Once the control file is parsed the `ar` archive is not walked further:
|
|
21
|
+
* the rest of the input is only hashed (`metadata.go:155-156`).
|
|
22
|
+
* - Bounds: the control member's compressed size by `maxMetadataBytes`, its
|
|
23
|
+
* decompressed bytes by `maxDecompressedMetadataBytes` (Gitea's 32 MiB),
|
|
24
|
+
* tar entries and `ar` members by `maxEntries`, tar header chains and
|
|
25
|
+
* control lines by `maxHeaderBytes`, the whole input by `maxPackageBytes`.
|
|
26
|
+
* A control member that decompresses past `maxDecompressedMetadataBytes` is
|
|
27
|
+
* `limit-exceeded` even when `control` comes first, where Gitea cuts the
|
|
28
|
+
* stream at 32 MiB and keeps a `control` found before the cut.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readDebianPackage(source: AsyncIterable<Uint8Array>, limits?: Partial<ILinuxPackageLimits>): Promise<IDebianPackageRecord>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { LinuxRepoError, limitExceeded } from '../shared/errors.js';
|
|
2
|
+
import { resolveLinuxPackageLimits } from '../shared/limits.js';
|
|
3
|
+
import { goPathBase } from '../shared/gopath.js';
|
|
4
|
+
import { ArReader } from '../readers/ar.js';
|
|
5
|
+
import { skipToEnd } from '../readers/bytes.js';
|
|
6
|
+
import { PackageByteSource } from '../readers/bytesource.js';
|
|
7
|
+
import { withDecompressingReader } from '../readers/decompress.js';
|
|
8
|
+
import { readTarEntryData, TarReader } from '../readers/tar.js';
|
|
9
|
+
import { parseDebianControlFile } from './control.js';
|
|
10
|
+
const CONTROL_TAR = 'control.tar';
|
|
11
|
+
/** The control archive forms Gitea 28.2.0 reads (`metadata.go:108-136`). */
|
|
12
|
+
const CONTROL_COMPRESSIONS = {
|
|
13
|
+
'': 'none',
|
|
14
|
+
'.gz': 'gzip',
|
|
15
|
+
'.xz': 'xz',
|
|
16
|
+
'.zst': 'zstd',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Reads a `.deb` package in one pass into Gitea 28.2.0's record
|
|
20
|
+
* (`modules/packages/debian/metadata.go:92-163`).
|
|
21
|
+
*
|
|
22
|
+
* - The `ar` members are walked in order; `debian-binary` is not required.
|
|
23
|
+
* The first member whose name starts with `control.tar` (a trailing `/`
|
|
24
|
+
* stripped from the suffix) is decompressed: `control.tar`, `.gz`, `.xz` or
|
|
25
|
+
* `.zst`; any other suffix is `unsupported-compression`.
|
|
26
|
+
* - In it, the first regular entry whose base name is `control` is parsed. A
|
|
27
|
+
* control archive without one moves on to the next `ar` member, as Gitea
|
|
28
|
+
* does; none at all is `missing-field` (`control`).
|
|
29
|
+
* - The control member is decoded to the decoder's end on both paths, after
|
|
30
|
+
* the control file is parsed and when it holds none: a cut or corrupt
|
|
31
|
+
* control member is `truncated` or `malformed-archive` in every form, where
|
|
32
|
+
* Gitea, which stops at the control entry, accepts it. For a plain
|
|
33
|
+
* `control.tar` the end is the end of its `ar` member; the bytes after the
|
|
34
|
+
* tar end marker are read, not parsed.
|
|
35
|
+
* - Once the control file is parsed the `ar` archive is not walked further:
|
|
36
|
+
* the rest of the input is only hashed (`metadata.go:155-156`).
|
|
37
|
+
* - Bounds: the control member's compressed size by `maxMetadataBytes`, its
|
|
38
|
+
* decompressed bytes by `maxDecompressedMetadataBytes` (Gitea's 32 MiB),
|
|
39
|
+
* tar entries and `ar` members by `maxEntries`, tar header chains and
|
|
40
|
+
* control lines by `maxHeaderBytes`, the whole input by `maxPackageBytes`.
|
|
41
|
+
* A control member that decompresses past `maxDecompressedMetadataBytes` is
|
|
42
|
+
* `limit-exceeded` even when `control` comes first, where Gitea cuts the
|
|
43
|
+
* stream at 32 MiB and keeps a `control` found before the cut.
|
|
44
|
+
*/
|
|
45
|
+
export async function readDebianPackage(source, limits) {
|
|
46
|
+
const resolved = resolveLinuxPackageLimits(limits);
|
|
47
|
+
const input = new PackageByteSource(source, resolved.maxPackageBytes);
|
|
48
|
+
const control = await readControl(input, resolved);
|
|
49
|
+
await input.drain();
|
|
50
|
+
return {
|
|
51
|
+
format: 'debian',
|
|
52
|
+
name: control.name,
|
|
53
|
+
version: control.version,
|
|
54
|
+
architecture: control.architecture,
|
|
55
|
+
fileName: `${control.name}_${control.version}_${control.architecture}.deb`,
|
|
56
|
+
digests: input.digests(),
|
|
57
|
+
metadata: control.metadata,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async function readControl(inputArg, limitsArg) {
|
|
61
|
+
const archive = new ArReader(inputArg, limitsArg.maxEntries);
|
|
62
|
+
for (;;) {
|
|
63
|
+
const member = await archive.next();
|
|
64
|
+
if (member === null) {
|
|
65
|
+
throw new LinuxRepoError('missing-field', 'the package has no control file', { field: 'control' });
|
|
66
|
+
}
|
|
67
|
+
if (!member.name.startsWith(CONTROL_TAR)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const suffix = member.name.slice(CONTROL_TAR.length).replace(/\/$/, '');
|
|
71
|
+
const compression = Object.hasOwn(CONTROL_COMPRESSIONS, suffix) ? CONTROL_COMPRESSIONS[suffix] : undefined;
|
|
72
|
+
if (compression === undefined) {
|
|
73
|
+
throw new LinuxRepoError('unsupported-compression', `unsupported control archive "${member.name}"`, {
|
|
74
|
+
field: 'control.tar',
|
|
75
|
+
value: member.name,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (member.size > limitsArg.maxMetadataBytes) {
|
|
79
|
+
throw limitExceeded('maxMetadataBytes', limitsArg.maxMetadataBytes, `control member ${member.name}`);
|
|
80
|
+
}
|
|
81
|
+
const control = await withDecompressingReader(member.body, compression, { maxOutputBytes: limitsArg.maxDecompressedMetadataBytes, outputLimit: 'maxDecompressedMetadataBytes' }, async (decompressed) => {
|
|
82
|
+
const tar = new TarReader(decompressed, {
|
|
83
|
+
maxEntries: limitsArg.maxEntries,
|
|
84
|
+
maxHeaderBytes: limitsArg.maxHeaderBytes,
|
|
85
|
+
});
|
|
86
|
+
let parsed = null;
|
|
87
|
+
for (;;) {
|
|
88
|
+
const entry = await tar.next();
|
|
89
|
+
if (entry === null) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (entry.typeflag !== '0' || goPathBase(entry.name) !== 'control') {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const bytes = await readTarEntryData(entry, limitsArg.maxDecompressedMetadataBytes, 'maxDecompressedMetadataBytes');
|
|
96
|
+
parsed = parseDebianControlFile(bytes, limitsArg.maxHeaderBytes);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
// Gitea stops at the control entry; the codec decodes the member to
|
|
100
|
+
// the decoder's end, so a cut or corrupt control member is refused in
|
|
101
|
+
// every form (a plain control.tar ends with its ar member)
|
|
102
|
+
await skipToEnd(decompressed);
|
|
103
|
+
return parsed;
|
|
104
|
+
});
|
|
105
|
+
if (control !== null) {
|
|
106
|
+
return control;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGViaWFuL3JlYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSx5QkFBeUIsRUFBNEIsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFakQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsdUJBQXVCLEVBQTBCLE1BQU0sMEJBQTBCLENBQUM7QUFDM0YsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxzQkFBc0IsRUFBdUIsTUFBTSxjQUFjLENBQUM7QUFFM0UsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDO0FBRWxDLDRFQUE0RTtBQUM1RSxNQUFNLG9CQUFvQixHQUFzQztJQUM5RCxFQUFFLEVBQUUsTUFBTTtJQUNWLEtBQUssRUFBRSxNQUFNO0lBQ2IsS0FBSyxFQUFFLElBQUk7SUFDWCxNQUFNLEVBQUUsTUFBTTtDQUNmLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQkc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGlCQUFpQixDQUNyQyxNQUFpQyxFQUNqQyxNQUFxQztJQUVyQyxNQUFNLFFBQVEsR0FBRyx5QkFBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuRCxNQUFNLEtBQUssR0FBRyxJQUFJLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUM7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
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type { TLinuxPackageFormat, ILinuxPackageDigests, IAlpinePackageDigests, ILinuxPackageRecordBase, IAlpinePackageMetadata, IAlpinePackageRecord, IDebianPackageMetadata, IDebianPackageRecord, IRpmDependency, IRpmFile, IRpmChangelog, IRpmPackageMetadata, IRpmPackageRecord, IRpmUpdate, IRpmUpdateReference, IRpmUpdateCollection, IRpmUpdatePackage, IArchPackageMetadata, IArchPackageRecord, TLinuxPackageRecord, TLinuxIndexFileStage, ILinuxIndexFile, } from './shared/types.js';
|
|
2
|
+
export { DEFAULT_LINUX_PACKAGE_LIMITS } from './shared/limits.js';
|
|
3
|
+
export type { ILinuxPackageLimits } from './shared/limits.js';
|
|
4
|
+
export { LinuxRepoError } from './shared/errors.js';
|
|
5
|
+
export type { TLinuxRepoErrorCode, ILinuxRepoErrorDetail } from './shared/errors.js';
|
|
6
|
+
export { isIndexableArchitecture } from './shared/architecture.js';
|
|
7
|
+
export { createAlpineSigner, createOpenPgpSigner } from './signing/signers.js';
|
|
8
|
+
export type { IAlpineSigner, IOpenPgpSigner } from './signing/signers.js';
|
|
9
|
+
export { generateAlpineKeyPair, generateOpenPgpKeyPair, giteaAlpineKeyName } from './signing/keys.js';
|
|
10
|
+
export type { IAlpineKeyPair, IOpenPgpKeyPair } from './signing/keys.js';
|
|
11
|
+
export { readDebianPackage } from './debian/reader.js';
|
|
12
|
+
export { buildDebianIndex } from './debian/indexbuilder.js';
|
|
13
|
+
export { readRpmPackage } from './rpm/reader.js';
|
|
14
|
+
export { signRpmPackage } from './rpm/sign.js';
|
|
15
|
+
export { buildRpmIndex } from './rpm/builder.js';
|
|
16
|
+
export { mergeRpmUpdates } from './rpm/updates.js';
|
|
17
|
+
export { renderRpmRepoConfig } from './rpm/repoconfig.js';
|
|
18
|
+
export { readArchPackage } from './arch/reader.js';
|
|
19
|
+
export { buildArchIndex } from './arch/builder.js';
|
|
20
|
+
export type { IArchIndexEntry } from './arch/builder.js';
|
|
21
|
+
export { signArchPackage } from './arch/signer.js';
|
|
22
|
+
export { readAlpinePackage } from './alpine/reader.js';
|
|
23
|
+
export { buildAlpineIndex } from './alpine/apkindex.js';
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { DEFAULT_LINUX_PACKAGE_LIMITS } from './shared/limits.js';
|
|
2
|
+
export { LinuxRepoError } from './shared/errors.js';
|
|
3
|
+
export { isIndexableArchitecture } from './shared/architecture.js';
|
|
4
|
+
export { createAlpineSigner, createOpenPgpSigner } from './signing/signers.js';
|
|
5
|
+
export { generateAlpineKeyPair, generateOpenPgpKeyPair, giteaAlpineKeyName } from './signing/keys.js';
|
|
6
|
+
export { readDebianPackage } from './debian/reader.js';
|
|
7
|
+
export { buildDebianIndex } from './debian/indexbuilder.js';
|
|
8
|
+
export { readRpmPackage } from './rpm/reader.js';
|
|
9
|
+
export { signRpmPackage } from './rpm/sign.js';
|
|
10
|
+
export { buildRpmIndex } from './rpm/builder.js';
|
|
11
|
+
export { mergeRpmUpdates } from './rpm/updates.js';
|
|
12
|
+
export { renderRpmRepoConfig } from './rpm/repoconfig.js';
|
|
13
|
+
export { readArchPackage } from './arch/reader.js';
|
|
14
|
+
export { buildArchIndex } from './arch/builder.js';
|
|
15
|
+
export { signArchPackage } from './arch/signer.js';
|
|
16
|
+
export { readAlpinePackage } from './alpine/reader.js';
|
|
17
|
+
export { buildAlpineIndex } from './alpine/apkindex.js';
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUF3QkEsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXBELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRS9FLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXRHLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzVELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9DLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbkQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVuRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUMifQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import * as stream from 'node:stream';
|
|
3
|
+
import * as streamWeb from 'node:stream/web';
|
|
4
|
+
import * as zlib from 'node:zlib';
|
|
5
|
+
export { crypto, stream, streamWeb, zlib };
|
|
6
|
+
import * as lzma from '@napi-rs/lzma';
|
|
7
|
+
import * as openpgp from 'openpgp';
|
|
8
|
+
export { lzma, openpgp };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// node native scope
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
import * as stream from 'node:stream';
|
|
4
|
+
import * as streamWeb from 'node:stream/web';
|
|
5
|
+
import * as zlib from 'node:zlib';
|
|
6
|
+
export { crypto, stream, streamWeb, zlib };
|
|
7
|
+
// third party scope
|
|
8
|
+
import * as lzma from '@napi-rs/lzma';
|
|
9
|
+
import * as openpgp from 'openpgp';
|
|
10
|
+
export { lzma, openpgp };
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxTQUFTLE1BQU0saUJBQWlCLENBQUM7QUFDN0MsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDO0FBRTNDLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssT0FBTyxNQUFNLFNBQVMsQ0FBQztBQUVuQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDIn0=
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LimitedReader, type IByteReader } from './bytes.js';
|
|
2
|
+
export interface IArMember {
|
|
3
|
+
/**
|
|
4
|
+
* The header name with trailing spaces removed. Nothing else is resolved: a
|
|
5
|
+
* GNU trailing `/` stays, and GNU (`//`) or BSD (`#1/`) long-name forms are
|
|
6
|
+
* ordinary member names, as Gitea's `blakesmith/ar` reports them.
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
size: number;
|
|
10
|
+
/** Exactly `size` bytes; reading past the input's end fails with `truncated`. */
|
|
11
|
+
body: LimitedReader;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A bounded reader for `ar` archives (the `.deb` container). It checks the
|
|
15
|
+
* `!<arch>\n` magic, the header terminator and the decimal size, which
|
|
16
|
+
* `blakesmith/ar` does not; every real `ar` writer produces them. A missing
|
|
17
|
+
* padding byte at the very end of the input ends the archive cleanly, as in
|
|
18
|
+
* `blakesmith/ar`.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ArReader {
|
|
21
|
+
private readonly input;
|
|
22
|
+
private readonly maxEntries;
|
|
23
|
+
private started;
|
|
24
|
+
private done;
|
|
25
|
+
private current;
|
|
26
|
+
private pad;
|
|
27
|
+
private members;
|
|
28
|
+
constructor(input: IByteReader, maxEntries: number);
|
|
29
|
+
next(): Promise<IArMember | null>;
|
|
30
|
+
private readMagic;
|
|
31
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { LinuxRepoError, limitExceeded, truncated } from '../shared/errors.js';
|
|
2
|
+
import { LimitedReader, readUpTo } from './bytes.js';
|
|
3
|
+
import { decodeGoUtf8, decodeLatin1 } from './text.js';
|
|
4
|
+
const AR_MAGIC = '!<arch>\n';
|
|
5
|
+
const AR_HEADER_BYTES = 60;
|
|
6
|
+
/**
|
|
7
|
+
* A bounded reader for `ar` archives (the `.deb` container). It checks the
|
|
8
|
+
* `!<arch>\n` magic, the header terminator and the decimal size, which
|
|
9
|
+
* `blakesmith/ar` does not; every real `ar` writer produces them. A missing
|
|
10
|
+
* padding byte at the very end of the input ends the archive cleanly, as in
|
|
11
|
+
* `blakesmith/ar`.
|
|
12
|
+
*/
|
|
13
|
+
export class ArReader {
|
|
14
|
+
input;
|
|
15
|
+
maxEntries;
|
|
16
|
+
started = false;
|
|
17
|
+
done = false;
|
|
18
|
+
current = null;
|
|
19
|
+
pad = 0;
|
|
20
|
+
members = 0;
|
|
21
|
+
constructor(input, maxEntries) {
|
|
22
|
+
this.input = input;
|
|
23
|
+
this.maxEntries = maxEntries;
|
|
24
|
+
}
|
|
25
|
+
async next() {
|
|
26
|
+
if (this.done) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (!this.started) {
|
|
30
|
+
await this.readMagic();
|
|
31
|
+
this.started = true;
|
|
32
|
+
}
|
|
33
|
+
if (this.current !== null) {
|
|
34
|
+
await this.current.skipRest();
|
|
35
|
+
this.current = null;
|
|
36
|
+
}
|
|
37
|
+
if (this.pad > 0) {
|
|
38
|
+
this.pad = 0;
|
|
39
|
+
const padding = await readUpTo(this.input, 1);
|
|
40
|
+
if (padding.length === 0) {
|
|
41
|
+
this.done = true;
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const header = await readUpTo(this.input, AR_HEADER_BYTES);
|
|
46
|
+
if (header.length === 0) {
|
|
47
|
+
this.done = true;
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
if (header.length < AR_HEADER_BYTES) {
|
|
51
|
+
throw truncated('ar member header');
|
|
52
|
+
}
|
|
53
|
+
if (header[58] !== 0x60 || header[59] !== 0x0a) {
|
|
54
|
+
throw malformed('ar member header has no "`\\n" terminator');
|
|
55
|
+
}
|
|
56
|
+
const name = decodeGoUtf8(header.subarray(0, 16)).replace(/ +$/, '');
|
|
57
|
+
const sizeText = decodeLatin1(header.subarray(48, 58)).replace(/ +$/, '');
|
|
58
|
+
if (!/^[0-9]+$/.test(sizeText)) {
|
|
59
|
+
throw malformed('ar member size is not a decimal number');
|
|
60
|
+
}
|
|
61
|
+
const size = Number(sizeText);
|
|
62
|
+
if (!Number.isSafeInteger(size)) {
|
|
63
|
+
throw malformed('ar member size is out of range');
|
|
64
|
+
}
|
|
65
|
+
this.members += 1;
|
|
66
|
+
if (this.members > this.maxEntries) {
|
|
67
|
+
throw limitExceeded('maxEntries', this.maxEntries, 'ar member count');
|
|
68
|
+
}
|
|
69
|
+
this.current = new LimitedReader(this.input, size, 'ar member data');
|
|
70
|
+
this.pad = size % 2;
|
|
71
|
+
return { name, size, body: this.current };
|
|
72
|
+
}
|
|
73
|
+
async readMagic() {
|
|
74
|
+
const magic = await readUpTo(this.input, AR_MAGIC.length);
|
|
75
|
+
const text = decodeLatin1(magic);
|
|
76
|
+
if (!AR_MAGIC.startsWith(text)) {
|
|
77
|
+
throw new LinuxRepoError('malformed-archive', 'input is not an ar archive', { field: 'ar magic' });
|
|
78
|
+
}
|
|
79
|
+
if (magic.length < AR_MAGIC.length) {
|
|
80
|
+
throw truncated('ar magic');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function malformed(messageArg) {
|
|
85
|
+
return new LinuxRepoError('malformed-archive', messageArg, { field: 'ar member header' });
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZWFkZXJzL2FyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFvQixNQUFNLFlBQVksQ0FBQztBQUN2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV2RCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUM7QUFDN0IsTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFDO0FBYzNCOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxRQUFRO0lBUUEsS0FBSztJQUNMLFVBQVU7SUFSckIsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNoQixJQUFJLEdBQUcsS0FBSyxDQUFDO0lBQ2IsT0FBTyxHQUF5QixJQUFJLENBQUM7SUFDckMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNSLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFFcEIsWUFDbUIsS0FBa0IsRUFDbEIsVUFBa0I7cUJBRGxCLEtBQUs7MEJBQ0wsVUFBVTtJQUMxQixDQUFDO0lBRUcsS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNkLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDdEIsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUMxQixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLE9BQU8s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
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A pull-based byte reader. `read` returns between 1 and `max` bytes, or
|
|
3
|
+
* `null` at the end of input. `unread` pushes bytes back so the next `read`
|
|
4
|
+
* returns them first (used where a decoder consumed less than it was given).
|
|
5
|
+
*/
|
|
6
|
+
export interface IByteReader {
|
|
7
|
+
read(maxArg: number): Promise<Uint8Array | null>;
|
|
8
|
+
unread(bytesArg: Uint8Array): void;
|
|
9
|
+
}
|
|
10
|
+
/** The read size the readers use when they pull without a structural bound. */
|
|
11
|
+
export declare const READ_CHUNK_BYTES: number;
|
|
12
|
+
export declare function concatBytes(chunksArg: Uint8Array[], totalArg?: number): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* Reads up to `lengthArg` bytes; returns fewer only when the input ends.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readUpTo(readerArg: IByteReader, lengthArg: number): Promise<Uint8Array>;
|
|
17
|
+
/**
|
|
18
|
+
* Reads exactly `lengthArg` bytes, or fails with `truncated` naming `whatArg`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readExact(readerArg: IByteReader, lengthArg: number, whatArg: string): Promise<Uint8Array>;
|
|
21
|
+
/**
|
|
22
|
+
* Skips exactly `lengthArg` bytes, or fails with `truncated` naming `whatArg`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function skipExact(readerArg: IByteReader, lengthArg: number, whatArg: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads and discards `readerArg` until it reports its end. The reader's own
|
|
27
|
+
* bounds apply: a decompressing reader counts the output against its
|
|
28
|
+
* `maxOutputBytes` and reports a cut or corrupt stream when its decoder does.
|
|
29
|
+
*/
|
|
30
|
+
export declare function skipToEnd(readerArg: IByteReader): Promise<void>;
|
|
31
|
+
/** A reader over bytes already in memory. */
|
|
32
|
+
export declare class BufferReader implements IByteReader {
|
|
33
|
+
private bytes;
|
|
34
|
+
private offset;
|
|
35
|
+
private pushedBack;
|
|
36
|
+
constructor(bytesArg: Uint8Array);
|
|
37
|
+
read(maxArg: number): Promise<Uint8Array | null>;
|
|
38
|
+
unread(bytesArg: Uint8Array): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Exposes exactly `lengthArg` bytes of an inner reader. Reading past the inner
|
|
42
|
+
* end fails with `truncated` naming `whatArg`; `skipRest` consumes what the
|
|
43
|
+
* consumer left.
|
|
44
|
+
*/
|
|
45
|
+
export declare class LimitedReader implements IByteReader {
|
|
46
|
+
private readonly inner;
|
|
47
|
+
private readonly what;
|
|
48
|
+
private remaining;
|
|
49
|
+
private pushedBack;
|
|
50
|
+
constructor(inner: IByteReader, lengthArg: number, what: string);
|
|
51
|
+
/** Bytes of the window the consumer has not read yet. */
|
|
52
|
+
get unreadBytes(): number;
|
|
53
|
+
read(maxArg: number): Promise<Uint8Array | null>;
|
|
54
|
+
unread(bytesArg: Uint8Array): void;
|
|
55
|
+
skipRest(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/** Splits `chunkArg` at `maxArg`, pushing the tail back onto `stackArg`. */
|
|
58
|
+
export declare function takeFront(chunkArg: Uint8Array, maxArg: number, stackArg: Uint8Array[]): Uint8Array;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { truncated } from '../shared/errors.js';
|
|
2
|
+
/** The read size the readers use when they pull without a structural bound. */
|
|
3
|
+
export const READ_CHUNK_BYTES = 64 * 1024;
|
|
4
|
+
export function concatBytes(chunksArg, totalArg) {
|
|
5
|
+
if (chunksArg.length === 1) {
|
|
6
|
+
return chunksArg[0];
|
|
7
|
+
}
|
|
8
|
+
const total = totalArg ?? chunksArg.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
9
|
+
const result = new Uint8Array(total);
|
|
10
|
+
let offset = 0;
|
|
11
|
+
for (const chunk of chunksArg) {
|
|
12
|
+
result.set(chunk, offset);
|
|
13
|
+
offset += chunk.length;
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reads up to `lengthArg` bytes; returns fewer only when the input ends.
|
|
19
|
+
*/
|
|
20
|
+
export async function readUpTo(readerArg, lengthArg) {
|
|
21
|
+
const chunks = [];
|
|
22
|
+
let total = 0;
|
|
23
|
+
while (total < lengthArg) {
|
|
24
|
+
const chunk = await readerArg.read(lengthArg - total);
|
|
25
|
+
if (chunk === null) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
chunks.push(chunk);
|
|
29
|
+
total += chunk.length;
|
|
30
|
+
}
|
|
31
|
+
return chunks.length === 0 ? new Uint8Array(0) : concatBytes(chunks, total);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reads exactly `lengthArg` bytes, or fails with `truncated` naming `whatArg`.
|
|
35
|
+
*/
|
|
36
|
+
export async function readExact(readerArg, lengthArg, whatArg) {
|
|
37
|
+
const bytes = await readUpTo(readerArg, lengthArg);
|
|
38
|
+
if (bytes.length !== lengthArg) {
|
|
39
|
+
throw truncated(whatArg);
|
|
40
|
+
}
|
|
41
|
+
return bytes;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Skips exactly `lengthArg` bytes, or fails with `truncated` naming `whatArg`.
|
|
45
|
+
*/
|
|
46
|
+
export async function skipExact(readerArg, lengthArg, whatArg) {
|
|
47
|
+
let remaining = lengthArg;
|
|
48
|
+
while (remaining > 0) {
|
|
49
|
+
const chunk = await readerArg.read(Math.min(remaining, READ_CHUNK_BYTES));
|
|
50
|
+
if (chunk === null) {
|
|
51
|
+
throw truncated(whatArg);
|
|
52
|
+
}
|
|
53
|
+
remaining -= chunk.length;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reads and discards `readerArg` until it reports its end. The reader's own
|
|
58
|
+
* bounds apply: a decompressing reader counts the output against its
|
|
59
|
+
* `maxOutputBytes` and reports a cut or corrupt stream when its decoder does.
|
|
60
|
+
*/
|
|
61
|
+
export async function skipToEnd(readerArg) {
|
|
62
|
+
while ((await readerArg.read(READ_CHUNK_BYTES)) !== null) {
|
|
63
|
+
// the bytes are discarded; the reader counts and checks them
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** A reader over bytes already in memory. */
|
|
67
|
+
export class BufferReader {
|
|
68
|
+
bytes;
|
|
69
|
+
offset = 0;
|
|
70
|
+
pushedBack = [];
|
|
71
|
+
constructor(bytesArg) {
|
|
72
|
+
this.bytes = bytesArg;
|
|
73
|
+
}
|
|
74
|
+
async read(maxArg) {
|
|
75
|
+
const pushed = this.pushedBack.pop();
|
|
76
|
+
if (pushed !== undefined) {
|
|
77
|
+
return takeFront(pushed, maxArg, this.pushedBack);
|
|
78
|
+
}
|
|
79
|
+
if (this.offset >= this.bytes.length) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const end = Math.min(this.bytes.length, this.offset + Math.max(1, maxArg));
|
|
83
|
+
const chunk = this.bytes.subarray(this.offset, end);
|
|
84
|
+
this.offset = end;
|
|
85
|
+
return chunk;
|
|
86
|
+
}
|
|
87
|
+
unread(bytesArg) {
|
|
88
|
+
if (bytesArg.length > 0) {
|
|
89
|
+
this.pushedBack.push(bytesArg);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Exposes exactly `lengthArg` bytes of an inner reader. Reading past the inner
|
|
95
|
+
* end fails with `truncated` naming `whatArg`; `skipRest` consumes what the
|
|
96
|
+
* consumer left.
|
|
97
|
+
*/
|
|
98
|
+
export class LimitedReader {
|
|
99
|
+
inner;
|
|
100
|
+
what;
|
|
101
|
+
remaining;
|
|
102
|
+
pushedBack = [];
|
|
103
|
+
constructor(inner, lengthArg, what) {
|
|
104
|
+
this.inner = inner;
|
|
105
|
+
this.what = what;
|
|
106
|
+
this.remaining = lengthArg;
|
|
107
|
+
}
|
|
108
|
+
/** Bytes of the window the consumer has not read yet. */
|
|
109
|
+
get unreadBytes() {
|
|
110
|
+
return this.remaining + this.pushedBack.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
111
|
+
}
|
|
112
|
+
async read(maxArg) {
|
|
113
|
+
const pushed = this.pushedBack.pop();
|
|
114
|
+
if (pushed !== undefined) {
|
|
115
|
+
return takeFront(pushed, maxArg, this.pushedBack);
|
|
116
|
+
}
|
|
117
|
+
if (this.remaining === 0) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const chunk = await this.inner.read(Math.min(Math.max(1, maxArg), this.remaining));
|
|
121
|
+
if (chunk === null) {
|
|
122
|
+
throw truncated(this.what);
|
|
123
|
+
}
|
|
124
|
+
this.remaining -= chunk.length;
|
|
125
|
+
return chunk;
|
|
126
|
+
}
|
|
127
|
+
unread(bytesArg) {
|
|
128
|
+
if (bytesArg.length > 0) {
|
|
129
|
+
this.pushedBack.push(bytesArg);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async skipRest() {
|
|
133
|
+
this.pushedBack = [];
|
|
134
|
+
await skipExact(this.inner, this.remaining, this.what);
|
|
135
|
+
this.remaining = 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** Splits `chunkArg` at `maxArg`, pushing the tail back onto `stackArg`. */
|
|
139
|
+
export function takeFront(chunkArg, maxArg, stackArg) {
|
|
140
|
+
const max = Math.max(1, maxArg);
|
|
141
|
+
if (chunkArg.length <= max) {
|
|
142
|
+
return chunkArg;
|
|
143
|
+
}
|
|
144
|
+
stackArg.push(chunkArg.subarray(max));
|
|
145
|
+
return chunkArg.subarray(0, max);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnl0ZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZWFkZXJzL2J5dGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQVloRCwrRUFBK0U7QUFDL0UsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUUxQyxNQUFNLFVBQVUsV0FBVyxDQUFDLFNBQXVCLEVBQUUsUUFBaUI7SUFDcEUsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxRQUFRLElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xGLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNmLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7UUFDOUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDekIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsUUFBUSxDQUFDLFNBQXNCLEVBQUUsU0FBaUI7SUFDdEUsTUFBTSxNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUNoQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxPQUFPLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQztRQUN6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
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ILinuxPackageDigests } from '../shared/types.js';
|
|
2
|
+
import { type IByteReader } from './bytes.js';
|
|
3
|
+
/**
|
|
4
|
+
* The digest tee: pulls the caller's package bytes once, counts them against
|
|
5
|
+
* `maxPackageBytes`, and feeds every byte exactly once into MD5, SHA-1,
|
|
6
|
+
* SHA-256 and SHA-512 at the moment it is pulled.
|
|
7
|
+
*
|
|
8
|
+
* - It pulls with `next()` only. It never calls `return()` or `throw()` on the
|
|
9
|
+
* caller's iterator, so a web `ReadableStream` is never cancelled.
|
|
10
|
+
* - An error from the caller's iterator propagates unchanged. After any error
|
|
11
|
+
* the source stops pulling for good.
|
|
12
|
+
* - `drain()` reads the rest of the input so the digests cover the whole file;
|
|
13
|
+
* `digests()` is available only after the input has ended.
|
|
14
|
+
*/
|
|
15
|
+
export declare class PackageByteSource implements IByteReader {
|
|
16
|
+
private readonly source;
|
|
17
|
+
private readonly maxPackageBytes;
|
|
18
|
+
private iterator;
|
|
19
|
+
private readonly pushedBack;
|
|
20
|
+
private readonly hashes;
|
|
21
|
+
private pulledBytes;
|
|
22
|
+
private deliveredBytes;
|
|
23
|
+
private ended;
|
|
24
|
+
private failure;
|
|
25
|
+
private failed;
|
|
26
|
+
private finalDigests;
|
|
27
|
+
constructor(sourceArg: AsyncIterable<Uint8Array>, maxPackageBytesArg: number);
|
|
28
|
+
/** Offset of the next byte `read` returns, counted from the start of the file. */
|
|
29
|
+
get position(): number;
|
|
30
|
+
/** Bytes pulled from the caller so far. */
|
|
31
|
+
get pulled(): number;
|
|
32
|
+
read(maxArg: number): Promise<Uint8Array | null>;
|
|
33
|
+
unread(bytesArg: Uint8Array): void;
|
|
34
|
+
/** Reads and discards the rest of the input. */
|
|
35
|
+
drain(): Promise<void>;
|
|
36
|
+
/** Size and digests of the whole input; only after the input has ended. */
|
|
37
|
+
digests(): ILinuxPackageDigests;
|
|
38
|
+
private pull;
|
|
39
|
+
private fail;
|
|
40
|
+
}
|