@c4roa0/agentpay-user 0.0.0-stage → 0.3.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/AGENTS.md +137 -0
- package/CONTRIBUTING.md +16 -0
- package/LICENSE +373 -0
- package/NOTICE.md +20 -0
- package/README.md +84 -2
- package/SECURITY.md +16 -0
- package/doc/README.md +52 -0
- package/doc/TODO.md +97 -0
- package/doc/architecture.md +96 -0
- package/doc/design.md +60 -0
- package/doc/develope.md +68 -0
- package/doc/plans/user-wallet-distribution.md +91 -0
- package/doc/reference/harness-skill-runtime.md +120 -0
- package/doc/reference/local-cache-foundation.md +176 -0
- package/doc/reference/local-safe-owner-ui.md +25 -0
- package/doc/reference/local-update.md +18 -0
- package/doc/reference/multi-service-runtime.md +119 -0
- package/doc/reference/npm-integration-verification.md +67 -0
- package/doc/reference/onboarding-writing.md +48 -0
- package/doc/reference/original-order-recovery.md +97 -0
- package/doc/reference/private-anvil-onboarding-config.example.json +18 -0
- package/doc/reference/public-deployment-settings.md +56 -0
- package/doc/reference/random-skill-contract.md +18 -0
- package/doc/reference/result-file-cache.md +166 -0
- package/doc/reference/runtime-address-recovery.md +42 -0
- package/doc/reference/runtime-result-cache.md +157 -0
- package/doc/reference/runtime-startup-recovery.md +141 -0
- package/doc/reference/skill-input-output-cache.md +93 -0
- package/doc/reference/wallet-identity-policy-history.md +23 -0
- package/doc/runbooks/commands.md +89 -0
- package/doc/runbooks/deployment-authorization-update.md +42 -0
- package/doc/runbooks/emergency-payment-stop.md +80 -0
- package/doc/runbooks/local-autostart.md +212 -0
- package/doc/runbooks/local-cache.md +115 -0
- package/doc/runbooks/local-update.md +84 -0
- package/doc/runbooks/market-connection.md +73 -0
- package/doc/runbooks/npm-publication.md +56 -0
- package/doc/runbooks/official-test-package.md +62 -0
- package/doc/runbooks/order-cancellation.md +56 -0
- package/doc/runbooks/order-support.md +41 -0
- package/doc/runbooks/policy-renewal.md +80 -0
- package/doc/runbooks/private-anvil-terminal-setup.md +58 -0
- package/doc/runbooks/runtime-skill-client.md +155 -0
- package/doc/runbooks/safe-owner-web.md +104 -0
- package/doc/runbooks/safe-policy-migration.md +36 -0
- package/doc/runbooks/safe-policy-setup.md +52 -0
- package/doc/runbooks/terminal-authorization-preview.md +38 -0
- package/doc/runbooks/unlock-wallet.md +68 -0
- package/doc/runbooks/user-onboarding.md +87 -0
- package/doc/runbooks/wallet-identity.md +59 -0
- package/doc/security/public-source-review-2026-11-06.md +71 -0
- package/doc/usage.md +54 -0
- package/package.json +49 -4
- package/progress.md +178 -0
- package/run +29 -0
- package/scripts/agentpay-cli.mjs +11 -0
- package/scripts/authorize-existing-safe.mjs +211 -0
- package/scripts/autostart.mjs +186 -0
- package/scripts/cancel-order.mjs +76 -0
- package/scripts/check-installation.mjs +26 -0
- package/scripts/check-official-test-package.mjs +35 -0
- package/scripts/check-purchase-readiness.mjs +275 -0
- package/scripts/configure-runtime-client.mjs +16 -0
- package/scripts/guide-policy.mjs +64 -0
- package/scripts/initialize-caller-credential.mjs +11 -0
- package/scripts/install-skill-bundle.mjs +176 -0
- package/scripts/install-user.mjs +24 -0
- package/scripts/local-service.mjs +60 -0
- package/scripts/lock.mjs +11 -0
- package/scripts/login-notify.mjs +39 -0
- package/scripts/migrate-safe-policy.mjs +165 -0
- package/scripts/official-paid-test.mjs +9 -0
- package/scripts/poll-unconfirmed-notice.mjs +75 -0
- package/scripts/prepare-onboarding.mjs +33 -0
- package/scripts/preview-policy.mjs +65 -0
- package/scripts/random-model-ack-smoke.mjs +235 -0
- package/scripts/random-reject-smoke.mjs +147 -0
- package/scripts/renew.mjs +9 -0
- package/scripts/repair.mjs +10 -0
- package/scripts/revoke.mjs +9 -0
- package/scripts/select-skill-bundle.mjs +39 -0
- package/scripts/setup-local.mjs +199 -0
- package/scripts/status.mjs +13 -0
- package/scripts/test-package.mjs +35 -0
- package/scripts/unlock.mjs +13 -0
- package/scripts/update.mjs +7 -0
- package/scripts/user-setup.mjs +219 -0
- package/scripts/verify-npm-release.mjs +32 -0
- package/src/active-skill.mjs +160 -0
- package/src/anvil-onboarding-state.mjs +96 -0
- package/src/anvil-onboarding.mjs +1036 -0
- package/src/authorization-question-checkpoint.mjs +114 -0
- package/src/autostart-files.mjs +50 -0
- package/src/cache-management-cli.mjs +302 -0
- package/src/cache-management.mjs +47 -0
- package/src/caller-auth.mjs +58 -0
- package/src/client-request-lock.mjs +44 -0
- package/src/connect-market.mjs +408 -0
- package/src/demo-unlock-secret.mjs +64 -0
- package/src/deployment-status.mjs +198 -0
- package/src/file-cache-cli.mjs +83 -0
- package/src/file-cache-owner.mjs +74 -0
- package/src/file-cache-settings.mjs +50 -0
- package/src/file-cache.mjs +790 -0
- package/src/file-download.mjs +281 -0
- package/src/finalization-disclosure.mjs +16 -0
- package/src/guided-setup.mjs +194 -0
- package/src/index.mjs +1231 -0
- package/src/install-and-setup.mjs +38 -0
- package/src/install-preflight.mjs +201 -0
- package/src/install-user.mjs +279 -0
- package/src/installation-paths.mjs +31 -0
- package/src/invocation-result.mjs +148 -0
- package/src/invocation-store.mjs +385 -0
- package/src/local-data-directory.mjs +117 -0
- package/src/local-info.mjs +181 -0
- package/src/local-services.mjs +156 -0
- package/src/local-time.mjs +36 -0
- package/src/local-update.mjs +306 -0
- package/src/local-wallet-ipc.mjs +93 -0
- package/src/login-reminder.mjs +28 -0
- package/src/market-download-url.mjs +21 -0
- package/src/node-version.mjs +12 -0
- package/src/npm-update.mjs +126 -0
- package/src/official-paid-test.mjs +407 -0
- package/src/official-test-package.mjs +41 -0
- package/src/official-test-update.mjs +162 -0
- package/src/order-cancellation.mjs +241 -0
- package/src/order-closure.mjs +42 -0
- package/src/order-list-panel.mjs +110 -0
- package/src/order-review.mjs +424 -0
- package/src/order-status-panel.mjs +65 -0
- package/src/order-support.mjs +365 -0
- package/src/owner-approval-server.mjs +332 -0
- package/src/owner-signer.mjs +67 -0
- package/src/policy-info.mjs +38 -0
- package/src/policy-migration.mjs +84 -0
- package/src/policy-operations.mjs +67 -0
- package/src/policy-preview-server.mjs +236 -0
- package/src/policy-terminal-guide.mjs +377 -0
- package/src/prepare-local-services.mjs +143 -0
- package/src/prepare-onboarding.mjs +210 -0
- package/src/private-journal-files.mjs +29 -0
- package/src/readiness-profile.mjs +30 -0
- package/src/renew-policy.mjs +605 -0
- package/src/repair-market-wallet.mjs +137 -0
- package/src/restore-wallet.mjs +255 -0
- package/src/result-cache-view.mjs +276 -0
- package/src/runtime-client.mjs +1145 -0
- package/src/runtime-connection-settings.mjs +101 -0
- package/src/runtime-recovery.mjs +667 -0
- package/src/runtime-status.mjs +32 -0
- package/src/safe-owner-anvil.mjs +115 -0
- package/src/safe-policy-plan.mjs +195 -0
- package/src/service-reference.mjs +233 -0
- package/src/service-url.mjs +52 -0
- package/src/settlement-response.mjs +69 -0
- package/src/setup-autostart.mjs +197 -0
- package/src/setup-demo.mjs +152 -0
- package/src/skill-bundle.mjs +142 -0
- package/src/skill-client.mjs +198 -0
- package/src/skill-install-prompt.mjs +31 -0
- package/src/skill-package.mjs +50 -0
- package/src/skill-zip.mjs +220 -0
- package/src/status-panel.mjs +589 -0
- package/src/transport.mjs +48 -0
- package/src/uninstall-local.mjs +299 -0
- package/src/user-cli.mjs +354 -0
- package/src/user-setup-guide.mjs +193 -0
- package/src/wallet-control.mjs +182 -0
- package/src/wallet-ipc-error.mjs +16 -0
- package/src/wallet-package.mjs +22 -0
- package/update-pair.json +6 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
3
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { createInterface } from "node:readline/promises";
|
|
5
|
+
|
|
6
|
+
export async function confirmSkillAction({
|
|
7
|
+
prompt,
|
|
8
|
+
details,
|
|
9
|
+
ask,
|
|
10
|
+
write = console.log,
|
|
11
|
+
}) {
|
|
12
|
+
const terminal = ask
|
|
13
|
+
? null
|
|
14
|
+
: createInterface({ input: process.stdin, output: process.stderr });
|
|
15
|
+
try {
|
|
16
|
+
while (true) {
|
|
17
|
+
const answer = (await (ask ? ask(prompt) : terminal.question(prompt)))
|
|
18
|
+
.trim()
|
|
19
|
+
.toLowerCase();
|
|
20
|
+
if (answer === "details") {
|
|
21
|
+
write(JSON.stringify(details, null, 2));
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (answer === "confirm") return true;
|
|
25
|
+
if (answer === "q") return false;
|
|
26
|
+
write("Type 'confirm', 'details', or 'q'.");
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
terminal?.close();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
3
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { normalizeServiceReference } from "@c4roa0/agentpay-protocol";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
export function skillPackageDigest(bytes) {
|
|
8
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
9
|
+
}
|
|
10
|
+
// Public reference inspection; no business-specific package or adapter parsing.
|
|
11
|
+
export function parseServicePackage(bytes, expected) {
|
|
12
|
+
if (!Buffer.isBuffer(bytes) || !bytes.length || bytes.length > 16384)
|
|
13
|
+
throw Error("SKILL_PACKAGE_SIZE_INVALID");
|
|
14
|
+
const reference = normalizeServiceReference(
|
|
15
|
+
JSON.parse(bytes.toString("utf8")),
|
|
16
|
+
),
|
|
17
|
+
profile = reference.profile;
|
|
18
|
+
const view = {
|
|
19
|
+
...reference,
|
|
20
|
+
reference,
|
|
21
|
+
providerId: profile.providerId,
|
|
22
|
+
serviceId: profile.serviceId,
|
|
23
|
+
endpointUrl: profile.paymentEndpoint,
|
|
24
|
+
};
|
|
25
|
+
if (
|
|
26
|
+
expected &&
|
|
27
|
+
["providerId", "serviceId", "skillId", "profileHash"].some(
|
|
28
|
+
(key) => view[key] !== expected[key],
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
throw Error("SKILL_PACKAGE_IDENTITY_MISMATCH");
|
|
32
|
+
if (
|
|
33
|
+
expected?.sourceUrl &&
|
|
34
|
+
profile.paymentEndpoint.replace(/\/invoke$/, "/skill-package") !==
|
|
35
|
+
expected.sourceUrl
|
|
36
|
+
)
|
|
37
|
+
throw Error("SKILL_PACKAGE_SOURCE_MISMATCH");
|
|
38
|
+
return Object.freeze(view);
|
|
39
|
+
}
|
|
40
|
+
export async function loadInstalledServiceReference(packageFile) {
|
|
41
|
+
const bytes = await readFile(packageFile);
|
|
42
|
+
if (
|
|
43
|
+
JSON.parse(bytes.toString("utf8"))?.version === "agentpay.active-skill.v1"
|
|
44
|
+
)
|
|
45
|
+
return (await import("./active-skill.mjs")).loadActiveSkill(packageFile);
|
|
46
|
+
const digest = (await readFile(packageFile + ".sha256", "utf8")).trim();
|
|
47
|
+
if (skillPackageDigest(bytes) !== digest)
|
|
48
|
+
throw Error("INSTALLED_SKILL_DIGEST_MISMATCH");
|
|
49
|
+
return parseServicePackage(bytes);
|
|
50
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
3
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { inflateRawSync } from "node:zlib";
|
|
5
|
+
import { TextDecoder } from "node:util";
|
|
6
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
7
|
+
const crcTable = Array.from({ length: 256 }, (_, i) => {
|
|
8
|
+
let c = i;
|
|
9
|
+
for (let bit = 0; bit < 8; bit++)
|
|
10
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
11
|
+
return c >>> 0;
|
|
12
|
+
});
|
|
13
|
+
export function zipCrc32(bytes) {
|
|
14
|
+
let crc = 0xffffffff;
|
|
15
|
+
for (const byte of bytes) crc = crcTable[(crc ^ byte) & 255] ^ (crc >>> 8);
|
|
16
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
17
|
+
}
|
|
18
|
+
function invalid(message) {
|
|
19
|
+
throw new Error(`ZIP_INVALID: ${message}`);
|
|
20
|
+
}
|
|
21
|
+
// Parse in memory only. No extraction, execution, ZIP64, encryption or links.
|
|
22
|
+
export function readSkillZip(bytes, limits) {
|
|
23
|
+
if (
|
|
24
|
+
!Buffer.isBuffer(bytes) ||
|
|
25
|
+
bytes.length < 22 ||
|
|
26
|
+
bytes.length > limits.compressed
|
|
27
|
+
)
|
|
28
|
+
invalid("compressed size limit");
|
|
29
|
+
const end = bytes.length - 22;
|
|
30
|
+
if (
|
|
31
|
+
bytes.readUInt32LE(end) !== 0x06054b50 ||
|
|
32
|
+
bytes.readUInt16LE(end + 20) !== 0
|
|
33
|
+
)
|
|
34
|
+
invalid("end record or archive comment");
|
|
35
|
+
const count = bytes.readUInt16LE(end + 10),
|
|
36
|
+
start = bytes.readUInt32LE(end + 16),
|
|
37
|
+
size = bytes.readUInt32LE(end + 12);
|
|
38
|
+
if (
|
|
39
|
+
bytes.readUInt16LE(end + 4) ||
|
|
40
|
+
bytes.readUInt16LE(end + 6) ||
|
|
41
|
+
bytes.readUInt16LE(end + 8) !== count ||
|
|
42
|
+
count === 65535 ||
|
|
43
|
+
count < 1 ||
|
|
44
|
+
count > limits.entries ||
|
|
45
|
+
start + size !== end
|
|
46
|
+
)
|
|
47
|
+
invalid("directory bounds or entry count");
|
|
48
|
+
const entries = [],
|
|
49
|
+
files = new Map(),
|
|
50
|
+
paths = new Set(),
|
|
51
|
+
ranges = [];
|
|
52
|
+
let cursor = start,
|
|
53
|
+
expanded = 0;
|
|
54
|
+
const extra = (at, length, name) => {
|
|
55
|
+
const stop = at + length;
|
|
56
|
+
while (at < stop) {
|
|
57
|
+
if (at + 4 > stop) invalid("extra field bounds");
|
|
58
|
+
const tag = bytes.readUInt16LE(at),
|
|
59
|
+
n = bytes.readUInt16LE(at + 2);
|
|
60
|
+
at += 4;
|
|
61
|
+
if (at + n > stop || [1, 0x6375, 0x9901].includes(tag))
|
|
62
|
+
invalid("unsupported extra field");
|
|
63
|
+
if (
|
|
64
|
+
tag === 0x7075 &&
|
|
65
|
+
(n < 5 ||
|
|
66
|
+
bytes[at] !== 1 ||
|
|
67
|
+
bytes.readUInt32LE(at + 1) !== zipCrc32(name) ||
|
|
68
|
+
!bytes.subarray(at + 5, at + n).equals(name))
|
|
69
|
+
)
|
|
70
|
+
invalid("Unicode path override");
|
|
71
|
+
at += n;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
for (let i = 0; i < count; i++) {
|
|
75
|
+
if (cursor + 46 > end || bytes.readUInt32LE(cursor) !== 0x02014b50)
|
|
76
|
+
invalid("central header");
|
|
77
|
+
const flags = bytes.readUInt16LE(cursor + 8),
|
|
78
|
+
method = bytes.readUInt16LE(cursor + 10),
|
|
79
|
+
crc = bytes.readUInt32LE(cursor + 16);
|
|
80
|
+
const compressed = bytes.readUInt32LE(cursor + 20),
|
|
81
|
+
length = bytes.readUInt32LE(cursor + 24);
|
|
82
|
+
const nameLength = bytes.readUInt16LE(cursor + 28),
|
|
83
|
+
extraLength = bytes.readUInt16LE(cursor + 30),
|
|
84
|
+
comment = bytes.readUInt16LE(cursor + 32);
|
|
85
|
+
const local = bytes.readUInt32LE(cursor + 42),
|
|
86
|
+
attributes = bytes.readUInt32LE(cursor + 38);
|
|
87
|
+
if (
|
|
88
|
+
cursor + 46 + nameLength + extraLength + comment > end ||
|
|
89
|
+
!nameLength ||
|
|
90
|
+
comment ||
|
|
91
|
+
bytes.readUInt16LE(cursor + 34) ||
|
|
92
|
+
flags & ~0x080e ||
|
|
93
|
+
(method !== 8 && flags & 6) ||
|
|
94
|
+
![0, 8].includes(method) ||
|
|
95
|
+
bytes.readUInt16LE(cursor + 6) > 20
|
|
96
|
+
)
|
|
97
|
+
invalid("unsupported entry");
|
|
98
|
+
const rawName = bytes.subarray(cursor + 46, cursor + 46 + nameLength);
|
|
99
|
+
let name;
|
|
100
|
+
try {
|
|
101
|
+
name = decoder.decode(rawName);
|
|
102
|
+
} catch {
|
|
103
|
+
invalid("names must use UTF-8");
|
|
104
|
+
}
|
|
105
|
+
const directory = name.endsWith("/"),
|
|
106
|
+
path = directory ? name.slice(0, -1) : name;
|
|
107
|
+
if (
|
|
108
|
+
!path ||
|
|
109
|
+
path.length > 240 ||
|
|
110
|
+
/[\\:\x00-\x1f\x7f]/.test(path) ||
|
|
111
|
+
path.startsWith("/") ||
|
|
112
|
+
path.split("/").some((part) => !part || part === "." || part === "..")
|
|
113
|
+
)
|
|
114
|
+
invalid("paths must be relative without traversal");
|
|
115
|
+
if (paths.has(path)) invalid("duplicate archive path");
|
|
116
|
+
const mode = attributes >>> 16,
|
|
117
|
+
type = mode & 0o170000;
|
|
118
|
+
if (
|
|
119
|
+
mode & 0o7000 ||
|
|
120
|
+
(type && type !== (directory ? 0o040000 : 0o100000)) ||
|
|
121
|
+
((attributes & 16) !== 0 && !directory)
|
|
122
|
+
)
|
|
123
|
+
invalid("links, special files or privileged modes");
|
|
124
|
+
if (length > limits.file || (directory && length !== 0))
|
|
125
|
+
invalid("file size limit");
|
|
126
|
+
expanded += length;
|
|
127
|
+
if (expanded > limits.expanded) invalid("expanded size limit");
|
|
128
|
+
extra(cursor + 46 + nameLength, extraLength, rawName);
|
|
129
|
+
if (
|
|
130
|
+
local + 30 > start ||
|
|
131
|
+
bytes.readUInt32LE(local) !== 0x04034b50 ||
|
|
132
|
+
bytes.readUInt16LE(local + 4) > 20 ||
|
|
133
|
+
bytes.readUInt16LE(local + 6) !== flags ||
|
|
134
|
+
bytes.readUInt16LE(local + 8) !== method
|
|
135
|
+
)
|
|
136
|
+
invalid("local header mismatch");
|
|
137
|
+
const localName = bytes.readUInt16LE(local + 26),
|
|
138
|
+
localExtra = bytes.readUInt16LE(local + 28);
|
|
139
|
+
const data = local + 30 + localName + localExtra,
|
|
140
|
+
stop = data + compressed;
|
|
141
|
+
if (
|
|
142
|
+
data > start ||
|
|
143
|
+
stop > start ||
|
|
144
|
+
!bytes.subarray(local + 30, local + 30 + localName).equals(rawName)
|
|
145
|
+
)
|
|
146
|
+
invalid("local name or data bounds");
|
|
147
|
+
extra(local + 30 + localName, localExtra, rawName);
|
|
148
|
+
const localCrc = bytes.readUInt32LE(local + 14),
|
|
149
|
+
localCompressed = bytes.readUInt32LE(local + 18),
|
|
150
|
+
localLength = bytes.readUInt32LE(local + 22);
|
|
151
|
+
let rangeEnd = stop;
|
|
152
|
+
if (flags & 8) {
|
|
153
|
+
if (
|
|
154
|
+
(localCrc && localCrc !== crc) ||
|
|
155
|
+
(localCompressed && localCompressed !== compressed) ||
|
|
156
|
+
(localLength && localLength !== length)
|
|
157
|
+
)
|
|
158
|
+
invalid("local descriptor mismatch");
|
|
159
|
+
if (stop + 12 > start) invalid("missing descriptor");
|
|
160
|
+
const descriptor =
|
|
161
|
+
bytes.readUInt32LE(stop) === 0x08074b50 ? stop + 4 : stop;
|
|
162
|
+
if (
|
|
163
|
+
descriptor + 12 > start ||
|
|
164
|
+
bytes.readUInt32LE(descriptor) !== crc ||
|
|
165
|
+
bytes.readUInt32LE(descriptor + 4) !== compressed ||
|
|
166
|
+
bytes.readUInt32LE(descriptor + 8) !== length
|
|
167
|
+
)
|
|
168
|
+
invalid("descriptor mismatch");
|
|
169
|
+
rangeEnd = descriptor + 12;
|
|
170
|
+
} else if (
|
|
171
|
+
localCrc !== crc ||
|
|
172
|
+
localCompressed !== compressed ||
|
|
173
|
+
localLength !== length
|
|
174
|
+
)
|
|
175
|
+
invalid("local size or checksum mismatch");
|
|
176
|
+
let content;
|
|
177
|
+
if (method === 0) {
|
|
178
|
+
if (compressed !== length) invalid("stored size mismatch");
|
|
179
|
+
content = Buffer.from(bytes.subarray(data, stop));
|
|
180
|
+
} else {
|
|
181
|
+
try {
|
|
182
|
+
const result = inflateRawSync(bytes.subarray(data, stop), {
|
|
183
|
+
maxOutputLength: Math.max(1, length),
|
|
184
|
+
info: true,
|
|
185
|
+
});
|
|
186
|
+
if (result.engine.bytesWritten !== compressed)
|
|
187
|
+
invalid("hidden compressed data");
|
|
188
|
+
content = result.buffer;
|
|
189
|
+
} catch {
|
|
190
|
+
invalid("invalid deflate data or expanded size");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (content.length !== length || zipCrc32(content) !== crc)
|
|
194
|
+
invalid("size or CRC mismatch");
|
|
195
|
+
paths.add(path);
|
|
196
|
+
entries.push({
|
|
197
|
+
path,
|
|
198
|
+
byteLength: length,
|
|
199
|
+
kind: directory ? "directory" : "file",
|
|
200
|
+
});
|
|
201
|
+
if (!directory) files.set(path, content);
|
|
202
|
+
ranges.push([local, rangeEnd]);
|
|
203
|
+
cursor += 46 + nameLength + extraLength + comment;
|
|
204
|
+
}
|
|
205
|
+
if (cursor !== end) invalid("central directory trailing data");
|
|
206
|
+
ranges.sort((a, b) => a[0] - b[0]);
|
|
207
|
+
let next = 0;
|
|
208
|
+
for (const [begin, stop] of ranges) {
|
|
209
|
+
if (begin !== next) invalid("overlap or hidden archive bytes");
|
|
210
|
+
next = stop;
|
|
211
|
+
}
|
|
212
|
+
if (next !== start) invalid("hidden data before directory");
|
|
213
|
+
for (const path of paths) {
|
|
214
|
+
const parts = path.split("/");
|
|
215
|
+
for (let i = 1; i < parts.length; i++)
|
|
216
|
+
if (files.has(parts.slice(0, i).join("/")))
|
|
217
|
+
invalid("file/directory path conflict");
|
|
218
|
+
}
|
|
219
|
+
return { entries, files, expandedByteLength: expanded };
|
|
220
|
+
}
|