@openclaw/fs-safe 0.11.0 → 0.13.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/CHANGELOG.md +119 -0
- package/README.md +15 -8
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +32 -11
- package/dist/advanced.d.ts +3 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +3 -1
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +4 -3
- package/dist/archive-gzip-tail.d.ts.map +1 -1
- package/dist/archive-gzip-tail.js +13 -9
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +6 -2
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +15 -2
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +7 -19
- package/dist/archive-plan.js +1 -1
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +55 -46
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +43 -10
- package/dist/archive-tar-inspect.d.ts.map +1 -1
- package/dist/archive-tar-inspect.js +4 -1
- package/dist/archive-zip-admission.d.ts +1 -1
- package/dist/archive-zip-admission.d.ts.map +1 -1
- package/dist/archive-zip-admission.js +2 -2
- package/dist/archive-zip-directory.d.ts +3 -0
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +13 -2
- package/dist/archive-zip-loader.d.ts +3 -2
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +30 -4
- package/dist/archive-zip-manifest.d.ts +5 -0
- package/dist/archive-zip-manifest.d.ts.map +1 -0
- package/dist/archive-zip-manifest.js +22 -0
- package/dist/archive-zip-names.d.ts +6 -1
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +50 -17
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +3 -2
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +9 -4
- package/dist/bounded-read.js +2 -2
- package/dist/darwin-acl.d.ts +4 -0
- package/dist/darwin-acl.d.ts.map +1 -0
- package/dist/darwin-acl.js +24 -0
- package/dist/deny-mutations.d.ts.map +1 -1
- package/dist/deny-mutations.js +8 -2
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +5 -3
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +67 -23
- package/dist/directory-entry-path.d.ts +3 -0
- package/dist/directory-entry-path.d.ts.map +1 -0
- package/dist/directory-entry-path.js +21 -0
- package/dist/directory-guard.d.ts +17 -1
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +134 -48
- package/dist/directory-mode-node.d.ts +12 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +102 -4
- package/dist/effective-uid.d.ts +2 -0
- package/dist/effective-uid.d.ts.map +1 -0
- package/dist/effective-uid.js +25 -0
- package/dist/file-handle-transfer.d.ts.map +1 -1
- package/dist/file-handle-transfer.js +98 -27
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +12 -2
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +36 -6
- package/dist/file-lock.d.ts.map +1 -1
- package/dist/file-lock.js +29 -9
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +6 -2
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +20 -65
- package/dist/file-store-copy-source.d.ts +5 -0
- package/dist/file-store-copy-source.d.ts.map +1 -0
- package/dist/file-store-copy-source.js +31 -0
- package/dist/file-store-path.d.ts.map +1 -1
- package/dist/file-store-path.js +4 -1
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +9 -1
- package/dist/file-store-sync-directory.d.ts +16 -0
- package/dist/file-store-sync-directory.d.ts.map +1 -0
- package/dist/file-store-sync-directory.js +349 -0
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +11 -28
- package/dist/filename.d.ts +1 -0
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +85 -23
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +3 -2
- package/dist/guarded-mkdir.d.ts +10 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +217 -33
- package/dist/guest.d.ts.map +1 -1
- package/dist/guest.js +16 -5
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +73 -10
- package/dist/install-path.d.ts +6 -0
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +67 -19
- package/dist/json-durable-queue-ownership.d.ts +8 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +134 -43
- package/dist/json-durable-queue-paths.d.ts +11 -0
- package/dist/json-durable-queue-paths.d.ts.map +1 -0
- package/dist/json-durable-queue-paths.js +42 -0
- package/dist/json-durable-queue-read.d.ts +6 -0
- package/dist/json-durable-queue-read.d.ts.map +1 -0
- package/dist/json-durable-queue-read.js +61 -0
- package/dist/json-durable-queue.d.ts +1 -1
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +83 -134
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +5 -1
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +54 -22
- package/dist/local-file-access.d.ts.map +1 -1
- package/dist/local-file-access.js +4 -0
- package/dist/local-file-descriptor.d.ts +17 -0
- package/dist/local-file-descriptor.d.ts.map +1 -0
- package/dist/local-file-descriptor.js +84 -0
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +35 -7
- package/dist/move-path-cleanup.d.ts +2 -0
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +44 -18
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +31 -6
- package/dist/native-binding.d.ts +21 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-directory-observation.d.ts +17 -0
- package/dist/native-directory-observation.d.ts.map +1 -0
- package/dist/native-directory-observation.js +37 -0
- package/dist/native-parent-admission.d.ts +31 -0
- package/dist/native-parent-admission.d.ts.map +1 -0
- package/dist/native-parent-admission.js +124 -0
- package/dist/native-pinned-write-windows.d.ts +0 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +0 -3
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +309 -40
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +15 -5
- package/dist/overwrite-file-handle.d.ts.map +1 -1
- package/dist/overwrite-file-handle.js +5 -1
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +2 -0
- package/dist/path-policy.d.ts.map +1 -1
- package/dist/path-policy.js +7 -2
- package/dist/path-prefix.d.ts +7 -0
- package/dist/path-prefix.d.ts.map +1 -0
- package/dist/path-prefix.js +82 -0
- package/dist/path-scope-lexical.d.ts +14 -0
- package/dist/path-scope-lexical.d.ts.map +1 -0
- package/dist/path-scope-lexical.js +37 -0
- package/dist/path-segment-route.d.ts +7 -0
- package/dist/path-segment-route.d.ts.map +1 -0
- package/dist/path-segment-route.js +24 -0
- package/dist/path-suffix-aliases.d.ts +10 -0
- package/dist/path-suffix-aliases.d.ts.map +1 -0
- package/dist/path-suffix-aliases.js +386 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +35 -6
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +14 -3
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +37 -8
- package/dist/pinned-mutation-admission.d.ts +25 -0
- package/dist/pinned-mutation-admission.d.ts.map +1 -0
- package/dist/pinned-mutation-admission.js +425 -0
- package/dist/pinned-mutation-observation.d.ts +34 -0
- package/dist/pinned-mutation-observation.d.ts.map +1 -0
- package/dist/pinned-mutation-observation.js +142 -0
- package/dist/pinned-mutation-shared-route.d.ts +24 -0
- package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
- package/dist/pinned-mutation-shared-route.js +70 -0
- package/dist/pinned-open.d.ts +6 -0
- package/dist/pinned-open.d.ts.map +1 -1
- package/dist/pinned-open.js +28 -10
- package/dist/pinned-write-types.d.ts +75 -0
- package/dist/pinned-write-types.d.ts.map +1 -0
- package/dist/pinned-write-types.js +1 -0
- package/dist/pinned-write.d.ts +7 -33
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +152 -17
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +2 -0
- package/dist/private-producer-handoff.d.ts +16 -0
- package/dist/private-producer-handoff.d.ts.map +1 -0
- package/dist/private-producer-handoff.js +272 -0
- package/dist/private-temp-workspace.d.ts +2 -39
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +183 -77
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +33 -29
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +56 -45
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +12 -5
- package/dist/replace-file-temp-owner.d.ts +1 -0
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +12 -1
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +24 -24
- package/dist/root-boundary.d.ts +29 -0
- package/dist/root-boundary.d.ts.map +1 -0
- package/dist/root-boundary.js +182 -0
- package/dist/root-context.d.ts +12 -1
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +89 -16
- package/dist/root-directory-creation.d.ts +13 -0
- package/dist/root-directory-creation.d.ts.map +1 -0
- package/dist/root-directory-creation.js +212 -0
- package/dist/root-directory-list.d.ts +16 -4
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +182 -33
- package/dist/root-directory.d.ts +23 -0
- package/dist/root-directory.d.ts.map +1 -0
- package/dist/root-directory.js +141 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +12 -1
- package/dist/root-file-final-admission.d.ts +21 -0
- package/dist/root-file-final-admission.d.ts.map +1 -0
- package/dist/root-file-final-admission.js +83 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +103 -24
- package/dist/root-impl.d.ts +1 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +316 -325
- package/dist/root-move-noreplace.d.ts +14 -0
- package/dist/root-move-noreplace.d.ts.map +1 -0
- package/dist/root-move-noreplace.js +202 -0
- package/dist/root-move-preflight.d.ts +8 -0
- package/dist/root-move-preflight.d.ts.map +1 -0
- package/dist/root-move-preflight.js +16 -0
- package/dist/root-observed-path.d.ts +9 -0
- package/dist/root-observed-path.d.ts.map +1 -0
- package/dist/root-observed-path.js +95 -0
- package/dist/root-path-errors.d.ts +12 -0
- package/dist/root-path-errors.d.ts.map +1 -0
- package/dist/root-path-errors.js +13 -0
- package/dist/root-path-existing.d.ts +2 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +63 -22
- package/dist/root-path-observation.d.ts +63 -0
- package/dist/root-path-observation.d.ts.map +1 -0
- package/dist/root-path-observation.js +180 -0
- package/dist/root-path-stat.d.ts +5 -0
- package/dist/root-path-stat.d.ts.map +1 -0
- package/dist/root-path-stat.js +101 -0
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +23 -4
- package/dist/root-path.d.ts +13 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +263 -73
- package/dist/root-paths-lexical.d.ts +9 -0
- package/dist/root-paths-lexical.d.ts.map +1 -0
- package/dist/root-paths-lexical.js +22 -0
- package/dist/root-paths.d.ts +3 -29
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +89 -178
- package/dist/root-read-admission.d.ts +26 -0
- package/dist/root-read-admission.d.ts.map +1 -0
- package/dist/root-read-admission.js +94 -0
- package/dist/root-remove-identity.d.ts +15 -0
- package/dist/root-remove-identity.d.ts.map +1 -0
- package/dist/root-remove-identity.js +89 -0
- package/dist/root-remove-receipt.d.ts +17 -0
- package/dist/root-remove-receipt.d.ts.map +1 -0
- package/dist/root-remove-receipt.js +37 -0
- package/dist/root-remove.d.ts +2 -1
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +172 -10
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +2 -1
- package/dist/root-write-admission.d.ts +68 -0
- package/dist/root-write-admission.d.ts.map +1 -0
- package/dist/root-write-admission.js +322 -0
- package/dist/root-write-compatibility.d.ts +13 -0
- package/dist/root-write-compatibility.d.ts.map +1 -0
- package/dist/root-write-compatibility.js +74 -0
- package/dist/root-write-complete-parent.d.ts +42 -0
- package/dist/root-write-complete-parent.d.ts.map +1 -0
- package/dist/root-write-complete-parent.js +195 -0
- package/dist/root-write-mode.d.ts +2 -0
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +20 -7
- package/dist/root-write-publication.d.ts +24 -0
- package/dist/root-write-publication.d.ts.map +1 -0
- package/dist/root-write-publication.js +85 -0
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +18 -7
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +3 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +62 -24
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +18 -13
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +5 -1
- package/dist/secure-file-windows.d.ts +10 -0
- package/dist/secure-file-windows.d.ts.map +1 -0
- package/dist/secure-file-windows.js +186 -0
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +98 -10
- package/dist/secure-temp-dir.d.ts +6 -3
- package/dist/secure-temp-dir.d.ts.map +1 -1
- package/dist/secure-temp-dir.js +121 -101
- package/dist/secure-temp-repair.d.ts +35 -0
- package/dist/secure-temp-repair.d.ts.map +1 -0
- package/dist/secure-temp-repair.js +106 -0
- package/dist/sibling-staged-file.d.ts +3 -1
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +181 -50
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +27 -12
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +45 -15
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +4 -2
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +2 -3
- package/dist/staged-directory.d.ts +14 -5
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +54 -3
- package/dist/standalone-publication-path.d.ts +2 -0
- package/dist/standalone-publication-path.d.ts.map +1 -0
- package/dist/standalone-publication-path.js +6 -0
- package/dist/stat-observation.d.ts +11 -0
- package/dist/stat-observation.d.ts.map +1 -0
- package/dist/stat-observation.js +64 -0
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/strict-file-identity.js +39 -2
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +7 -2
- package/dist/temp-target.d.ts +2 -0
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +133 -4
- package/dist/temp-workspace-admission.d.ts +22 -0
- package/dist/temp-workspace-admission.d.ts.map +1 -0
- package/dist/temp-workspace-admission.js +374 -0
- package/dist/temp-workspace-child-admission.d.ts +13 -0
- package/dist/temp-workspace-child-admission.d.ts.map +1 -0
- package/dist/temp-workspace-child-admission.js +95 -0
- package/dist/temp-workspace-descriptor.d.ts +48 -0
- package/dist/temp-workspace-descriptor.d.ts.map +1 -0
- package/dist/temp-workspace-descriptor.js +363 -0
- package/dist/temp-workspace-identity.d.ts +15 -0
- package/dist/temp-workspace-identity.d.ts.map +1 -0
- package/dist/temp-workspace-identity.js +41 -0
- package/dist/temp-workspace-owner.d.ts +7 -6
- package/dist/temp-workspace-owner.d.ts.map +1 -1
- package/dist/temp-workspace-owner.js +121 -61
- package/dist/temp-workspace-permissions.d.ts +4 -0
- package/dist/temp-workspace-permissions.d.ts.map +1 -0
- package/dist/temp-workspace-permissions.js +32 -0
- package/dist/temp-workspace-types.d.ts +40 -0
- package/dist/temp-workspace-types.d.ts.map +1 -0
- package/dist/temp-workspace-types.js +1 -0
- package/dist/temp.d.ts +1 -1
- package/dist/temp.d.ts.map +1 -1
- package/dist/temp.js +1 -1
- package/dist/test-hooks.d.ts +7 -0
- package/dist/test-hooks.d.ts.map +1 -1
- package/dist/text-atomic.d.ts.map +1 -1
- package/dist/text-atomic.js +3 -1
- package/dist/trash.d.ts.map +1 -1
- package/dist/trash.js +54 -8
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +20 -16
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +5 -0
- package/dist/windows-path-alias.d.ts +39 -0
- package/dist/windows-path-alias.d.ts.map +1 -0
- package/dist/windows-path-alias.js +153 -0
- package/docs/advanced.md +28 -1
- package/docs/archive.md +29 -2
- package/docs/atomic.md +27 -3
- package/docs/contributing.md +4 -1
- package/docs/copy.md +4 -1
- package/docs/durability.md +18 -2
- package/docs/errors.md +14 -6
- package/docs/file-store.md +30 -3
- package/docs/filename.md +21 -7
- package/docs/guest.md +5 -0
- package/docs/install-path.md +61 -15
- package/docs/install.md +12 -8
- package/docs/json-store.md +5 -1
- package/docs/json.md +11 -0
- package/docs/mutation-policy-proof.md +65 -0
- package/docs/native-helper.md +28 -9
- package/docs/native.md +46 -10
- package/docs/output.md +33 -11
- package/docs/path-prefix.md +64 -0
- package/docs/path-suffix-aliases.md +159 -0
- package/docs/path.md +12 -1
- package/docs/permissions.md +26 -1
- package/docs/private-file-store.md +14 -0
- package/docs/public-api.md +14 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +8 -1
- package/docs/root.md +21 -4
- package/docs/secret-file.md +3 -0
- package/docs/secure-file.md +21 -16
- package/docs/security-model.md +76 -9
- package/docs/sidecar-lock.md +28 -1
- package/docs/store.md +27 -2
- package/docs/temp.md +262 -34
- package/docs/test-hooks.md +14 -0
- package/docs/writing.md +38 -8
- package/package.json +10 -10
package/dist/archive-native.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { classifyArchiveParserError } from "./archive-parser-errors.js";
|
|
2
2
|
import { constants as fsConstants } from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
|
-
import { ArchiveFormatError,
|
|
5
|
-
import {
|
|
4
|
+
import { ArchiveFormatError, isArchiveFormatErrorMessage, } from "./archive-errors.js";
|
|
5
|
+
import { validateArchiveEntryPath } from "./archive-entry.js";
|
|
6
6
|
import { createArchiveEntryPlanner } from "./archive-plan.js";
|
|
7
7
|
import { stageArchiveFileForExtraction } from "./archive-input.js";
|
|
8
8
|
import { assertArchiveEntryCountWithinLimit, } from "./archive-limits.js";
|
|
9
9
|
import { prepareArchiveDestinationGuard, withStagedArchiveDestination, } from "./archive-staging.js";
|
|
10
10
|
import { mergePlannedArchiveIntoDestination } from "./archive-merge.js";
|
|
11
11
|
import { admitZipFile } from "./archive-zip-admission.js";
|
|
12
|
+
import { validateNativeZipManifest } from "./archive-zip-manifest.js";
|
|
12
13
|
export function throwMappedNativeArchiveError(error) {
|
|
13
14
|
if (error instanceof Error) {
|
|
14
15
|
const mapped = classifyArchiveParserError(error.message, { cause: error });
|
|
@@ -32,9 +33,9 @@ export async function extractNativeArchive(params) {
|
|
|
32
33
|
});
|
|
33
34
|
try {
|
|
34
35
|
const zipEntries = [];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
if (params.kind === "zip") {
|
|
37
|
+
await admitZipFile(stagedArchive.path, limits, params.deadline, (entry) => { zipEntries.push(entry); });
|
|
38
|
+
}
|
|
38
39
|
const destinationGuard = await prepareArchiveDestinationGuard(params.destDir);
|
|
39
40
|
const destinationRealDir = destinationGuard.realPath;
|
|
40
41
|
await withStagedArchiveDestination({
|
|
@@ -47,21 +48,8 @@ export async function extractNativeArchive(params) {
|
|
|
47
48
|
.catch(throwMappedNativeArchiveError);
|
|
48
49
|
params.deadline.check();
|
|
49
50
|
assertArchiveEntryCountWithinLimit(manifest.length, limits);
|
|
50
|
-
if (physicalCount !== undefined && manifest.length !== physicalCount) {
|
|
51
|
-
throw new ArchiveSecurityError("entry-path", "zip decoder collapsed entry names");
|
|
52
|
-
}
|
|
53
51
|
if (params.kind === "zip") {
|
|
54
|
-
|
|
55
|
-
const physical = zipEntries[ordinal];
|
|
56
|
-
// Native ZIP indices are physical central-directory ordinals. Legacy
|
|
57
|
-
// filename decoding remains native-selected; compare names when known.
|
|
58
|
-
if (!physical || physical.index !== ordinal || entry.index !== ordinal ||
|
|
59
|
-
entry.size !== physical.size ||
|
|
60
|
-
(physical.path !== undefined && stripArchivePath(entry.path, 0) !== stripArchivePath(physical.path, 0)) ||
|
|
61
|
-
(physical.creatorSystem === 3 && entry.mode !== physical.externalAttributes >>> 16)) {
|
|
62
|
-
throw new ArchiveFormatError("ZIP decoder disagrees with admitted directory metadata");
|
|
63
|
-
}
|
|
64
|
-
}
|
|
52
|
+
validateNativeZipManifest(manifest, zipEntries);
|
|
65
53
|
}
|
|
66
54
|
// Recheck the native manifest at the shared policy boundary before
|
|
67
55
|
// any caller callback observes an entry.
|
package/dist/archive-plan.js
CHANGED
|
@@ -17,7 +17,7 @@ export function createArchiveEntryPlanner(params, archiveKind) {
|
|
|
17
17
|
const canonicalPath = stripArchivePath(entry.path, 0);
|
|
18
18
|
if (!canonicalPath)
|
|
19
19
|
return null;
|
|
20
|
-
const relPath = stripArchivePath(canonicalPath, strip);
|
|
20
|
+
const relPath = strip === 0 ? canonicalPath : stripArchivePath(canonicalPath, strip);
|
|
21
21
|
if (!relPath)
|
|
22
22
|
return null;
|
|
23
23
|
validateArchiveEntryPath(relPath, { escapeLabel: params.escapeLabel });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-read.d.ts","sourceRoot":"","sources":["../src/archive-read.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive-read.d.ts","sourceRoot":"","sources":["../src/archive-read.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAiD,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA0OpG,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE,GAChD,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
package/dist/archive-read.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { classifyArchiveParserError } from "./archive-parser-errors.js";
|
|
2
2
|
import fsSync from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
|
-
import { Readable } from "node:stream";
|
|
4
|
+
import { Readable, Writable } from "node:stream";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
5
6
|
import { readBoundedAsync } from "./bounded-read.js";
|
|
6
7
|
import { ArchiveFormatError, ArchiveSecurityError, isArchiveFormatErrorMessage, } from "./archive-errors.js";
|
|
7
8
|
import { formatErrorDetail } from "./error-detail.js";
|
|
@@ -18,7 +19,9 @@ import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
|
18
19
|
import { realpathSync } from "./realpath.js";
|
|
19
20
|
import { getNativeBinding } from "./native.js";
|
|
20
21
|
import { admitZipBuffer } from "./archive-zip-admission.js";
|
|
22
|
+
import { validateNativeZipManifest } from "./archive-zip-manifest.js";
|
|
21
23
|
import { resolveExtractLimits, resolveTarMeterLimits } from "./archive-limits.js";
|
|
24
|
+
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
22
25
|
const ZIP_UNIX_FILE_TYPE_MASK = 0o170000;
|
|
23
26
|
const ZIP_UNIX_SYMLINK_TYPE = 0o120000;
|
|
24
27
|
function canonicalEntryPath(entryPath) {
|
|
@@ -32,40 +35,26 @@ function normalizedRequestedEntry(entryPath) {
|
|
|
32
35
|
}
|
|
33
36
|
return normalized;
|
|
34
37
|
}
|
|
35
|
-
async function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const chunks = [];
|
|
40
|
-
let total = 0;
|
|
41
|
-
readable.on("data", (chunk) => {
|
|
42
|
-
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
43
|
-
total += buffer.length;
|
|
44
|
-
if (total > maxBytes) {
|
|
45
|
-
readable.pause();
|
|
46
|
-
reject(new ArchiveLimitError(ARCHIVE_LIMIT_ERROR_CODE.ENTRY_EXTRACTED_SIZE_EXCEEDS_LIMIT));
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
chunks.push(buffer);
|
|
50
|
-
});
|
|
51
|
-
readable.once("end", () => resolve(Buffer.concat(chunks, total)));
|
|
52
|
-
readable.once("error", reject);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
const chunks = [];
|
|
38
|
+
async function readAdmittedTarPayload(stream, size) {
|
|
39
|
+
// Complete admission has bounded this exact range. Copy as it arrives so
|
|
40
|
+
// decoder chunks can be released before the caller receives the owned result.
|
|
41
|
+
const result = Buffer.allocUnsafe(size);
|
|
56
42
|
let total = 0;
|
|
57
43
|
for await (const chunk of stream) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (total > maxBytes) {
|
|
61
|
-
throw new ArchiveLimitError(ARCHIVE_LIMIT_ERROR_CODE.ENTRY_EXTRACTED_SIZE_EXCEEDS_LIMIT);
|
|
44
|
+
if (chunk.length > size - total) {
|
|
45
|
+
throw new ArchiveFormatError("invalid admitted TAR payload size");
|
|
62
46
|
}
|
|
63
|
-
|
|
47
|
+
chunk.copy(result, total);
|
|
48
|
+
total += chunk.length;
|
|
64
49
|
}
|
|
65
|
-
|
|
50
|
+
if (total !== size)
|
|
51
|
+
throw new ArchiveFormatError("truncated admitted TAR range");
|
|
52
|
+
return result;
|
|
66
53
|
}
|
|
67
54
|
async function readArchiveInput(archivePath) {
|
|
55
|
+
assertNoWindowsPathAlias(archivePath);
|
|
68
56
|
const resolved = realpathSync.native(archivePath);
|
|
57
|
+
assertNoWindowsPathAlias(resolved);
|
|
69
58
|
const before = await inspectFileIdentity(async () => {
|
|
70
59
|
const stat = fsSync.lstatSync(archivePath, { bigint: true });
|
|
71
60
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
@@ -104,8 +93,8 @@ async function readArchiveInput(archivePath) {
|
|
|
104
93
|
await handle.close().catch(() => undefined);
|
|
105
94
|
}
|
|
106
95
|
}
|
|
107
|
-
async function readZipEntry(buffer, entryPath, maxBytes,
|
|
108
|
-
const archive = await loadAdmittedZipArchive(buffer,
|
|
96
|
+
async function readZipEntry(buffer, entryPath, maxBytes, admitted) {
|
|
97
|
+
const archive = await loadAdmittedZipArchive(buffer, admitted);
|
|
109
98
|
let entry;
|
|
110
99
|
// JSZip keys retain some aliases and may use Unicode Path metadata. Scan the
|
|
111
100
|
// effective entries once, after raw ZIP admission has rejected collisions.
|
|
@@ -124,12 +113,31 @@ async function readZipEntry(buffer, entryPath, maxBytes, physicalCount) {
|
|
|
124
113
|
(entry.unixPermissions & ZIP_UNIX_FILE_TYPE_MASK) === ZIP_UNIX_SYMLINK_TYPE) {
|
|
125
114
|
throw new Error(`archive entry is a link: ${formatErrorDetail(entryPath)}`);
|
|
126
115
|
}
|
|
116
|
+
const integrity = createZipIntegrityTransform(entry);
|
|
127
117
|
const stream = typeof entry.nodeStream === "function"
|
|
128
118
|
? entry.nodeStream()
|
|
129
119
|
: Readable.from(await entry.async("nodebuffer"));
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
120
|
+
const chunks = [];
|
|
121
|
+
let total = 0;
|
|
122
|
+
const destination = new Writable({
|
|
123
|
+
write(chunk, _encoding, callback) {
|
|
124
|
+
total += chunk.length;
|
|
125
|
+
if (total > maxBytes) {
|
|
126
|
+
callback(new ArchiveLimitError(ARCHIVE_LIMIT_ERROR_CODE.ENTRY_EXTRACTED_SIZE_EXCEEDS_LIMIT));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
chunks.push(chunk);
|
|
130
|
+
callback();
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
try {
|
|
134
|
+
// Iterator teardown can mask limit errors on Node 22; keep them in stream callbacks.
|
|
135
|
+
await pipeline(stream, integrity, destination);
|
|
136
|
+
return Buffer.concat(chunks, total);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
throw normalizeZipIntegrityError(error);
|
|
140
|
+
}
|
|
133
141
|
}
|
|
134
142
|
async function readTarEntry(archiveBuffer, entryPath, maxBytes) {
|
|
135
143
|
const seenPaths = new Set();
|
|
@@ -162,15 +170,12 @@ async function readTarEntry(archiveBuffer, entryPath, maxBytes) {
|
|
|
162
170
|
return Buffer.from(archiveBuffer.subarray(selected.offset, end));
|
|
163
171
|
}
|
|
164
172
|
let result;
|
|
165
|
-
await replayTar({ archiveBuffer, limits, members: [selected], async consume(
|
|
166
|
-
result = await
|
|
173
|
+
await replayTar({ archiveBuffer, limits, members: [selected], async consume(member, payload) {
|
|
174
|
+
result = await readAdmittedTarPayload(payload, member.size);
|
|
167
175
|
} });
|
|
168
176
|
return result;
|
|
169
177
|
}
|
|
170
|
-
function selectNativeEntry(manifest, requested, displayPath
|
|
171
|
-
if (physicalCount !== undefined && manifest.length !== physicalCount) {
|
|
172
|
-
throw new ArchiveSecurityError("entry-path", "zip decoder collapsed entry names");
|
|
173
|
-
}
|
|
178
|
+
function selectNativeEntry(manifest, requested, displayPath) {
|
|
174
179
|
const seen = new Set();
|
|
175
180
|
let selected;
|
|
176
181
|
for (const entry of manifest) {
|
|
@@ -199,14 +204,17 @@ function throwNativeReadError(error) {
|
|
|
199
204
|
}
|
|
200
205
|
throw error;
|
|
201
206
|
}
|
|
202
|
-
async function readNativeBufferEntry(native, buffer, kind, requested, displayPath, maxBytes,
|
|
207
|
+
async function readNativeBufferEntry(native, buffer, kind, requested, displayPath, maxBytes, zipEntries) {
|
|
203
208
|
try {
|
|
204
209
|
const signal = new AbortController().signal;
|
|
205
210
|
const limits = resolveTarMeterLimits();
|
|
206
211
|
const reader = kind === "zip"
|
|
207
212
|
? await native.openZipBufferNative(buffer, limits, AbortSignal.any([signal]))
|
|
208
213
|
: await native.openTarBufferNative(buffer, kind, limits, AbortSignal.any([signal]));
|
|
209
|
-
const
|
|
214
|
+
const manifest = reader.entries;
|
|
215
|
+
if (kind === "zip")
|
|
216
|
+
validateNativeZipManifest(manifest, zipEntries);
|
|
217
|
+
const selected = selectNativeEntry(manifest, requested, displayPath);
|
|
210
218
|
return await reader.readEntry(selected.index, maxBytes, AbortSignal.any([signal]));
|
|
211
219
|
}
|
|
212
220
|
catch (error) {
|
|
@@ -222,14 +230,15 @@ export async function readArchiveEntry(archivePath, entryPath, options) {
|
|
|
222
230
|
throw new Error(`unsupported archive: ${archivePath}`);
|
|
223
231
|
}
|
|
224
232
|
const requestedEntry = normalizedRequestedEntry(entryPath);
|
|
233
|
+
assertNoWindowsPathAlias(archivePath, "filesystem", "archive source uses a Windows filesystem namespace alias");
|
|
225
234
|
const buffer = await readArchiveInput(archivePath);
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
235
|
+
const zipEntries = [];
|
|
236
|
+
if (kind === "zip")
|
|
237
|
+
admitZipBuffer(buffer, resolveExtractLimits(), entry => { zipEntries.push(entry); });
|
|
229
238
|
const native = getNativeBinding();
|
|
230
239
|
if (native)
|
|
231
|
-
return await readNativeBufferEntry(native, buffer, kind, requestedEntry, entryPath, options.maxBytes,
|
|
240
|
+
return await readNativeBufferEntry(native, buffer, kind, requestedEntry, entryPath, options.maxBytes, zipEntries);
|
|
232
241
|
assertPortableArchiveKind(kind);
|
|
233
|
-
return kind === "zip" ? await readZipEntry(buffer, requestedEntry, options.maxBytes,
|
|
242
|
+
return kind === "zip" ? await readZipEntry(buffer, requestedEntry, options.maxBytes, zipEntries)
|
|
234
243
|
: await readTarEntry(buffer, requestedEntry, options.maxBytes);
|
|
235
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-staging.d.ts","sourceRoot":"","sources":["../src/archive-staging.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EAErB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-staging.d.ts","sourceRoot":"","sources":["../src/archive-staging.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EAErB,MAAM,qBAAqB,CAAC;AAiB7B,MAAM,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAMrE,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAS1F,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAY9F;AAED,wBAAsB,4BAA4B,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAY9F;AAED,wBAAsB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2CpG;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF;AA0BD,wBAAsB,+BAA+B,CAAC,MAAM,EAAE;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBhB;AAiBD,KAAK,uBAAuB,GAAG;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,CAAC;AAkBF,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7F;AAED,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,uBAAuB,EAAE,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnE,gBAAgB,CAAC,EAAE,qBAAqB,GACvC,OAAO,CAAC,IAAI,CAAC,CAOf;AAkHD,wBAAsB,4BAA4B,CAAC,CAAC,EAAE,MAAM,EAAE;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiCb;AAED,OAAO,EAAE,iCAAiC,EAAE,MAAM,oBAAoB,CAAC;AAEvE,wBAAgB,kCAAkC,CAAC,YAAY,EAAE,MAAM,GAAG,oBAAoB,CAE7F"}
|
package/dist/archive-staging.js
CHANGED
|
@@ -14,6 +14,7 @@ import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
|
14
14
|
import { expandRelativePathWithHome } from "./root-context.js";
|
|
15
15
|
import { resolveRootPath } from "./root-path.js";
|
|
16
16
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
17
|
+
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
17
18
|
import { realpathSync } from "./realpath.js";
|
|
18
19
|
const ERROR_ARCHIVE_ENTRY_TRAVERSES_SYMLINK = "archive entry traverses symlink in destination";
|
|
19
20
|
const ARCHIVE_STAGING_MODE = 0o700;
|
|
@@ -25,8 +26,11 @@ function symlinkTraversalError(originalPath) {
|
|
|
25
26
|
return new ArchiveSecurityError("destination-symlink-traversal", `${ERROR_ARCHIVE_ENTRY_TRAVERSES_SYMLINK}: ${formatErrorDetail(originalPath)}`);
|
|
26
27
|
}
|
|
27
28
|
export async function createDirectoryIdentityGuard(dir) {
|
|
29
|
+
assertNoWindowsPathAlias(dir);
|
|
28
30
|
try {
|
|
29
|
-
|
|
31
|
+
const guard = await createAsyncDirectoryGuard(dir, { bigint: true });
|
|
32
|
+
assertNoWindowsPathAlias(guard.realPath);
|
|
33
|
+
return guard;
|
|
30
34
|
}
|
|
31
35
|
catch (err) {
|
|
32
36
|
if (err instanceof FsSafeError && err.code === "not-file") {
|
|
@@ -47,6 +51,7 @@ export async function assertDirectoryIdentityGuard(guard) {
|
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
export async function prepareArchiveDestinationGuard(destDir) {
|
|
54
|
+
assertNoWindowsPathAlias(destDir);
|
|
50
55
|
let stat;
|
|
51
56
|
try {
|
|
52
57
|
stat = inspectFileIdentitySync(() => {
|
|
@@ -69,6 +74,7 @@ export async function prepareArchiveDestinationGuard(destDir) {
|
|
|
69
74
|
throw err;
|
|
70
75
|
}
|
|
71
76
|
const realPath = realpathSync.native(destDir);
|
|
77
|
+
assertNoWindowsPathAlias(realPath);
|
|
72
78
|
const guard = { dir: destDir, realPath, stat };
|
|
73
79
|
try {
|
|
74
80
|
inspectFileIdentitySync(() => fsSync.statSync(realPath, { bigint: true }), stat);
|
|
@@ -106,9 +112,14 @@ async function assertNoSymlinkTraversal(params) {
|
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
export async function assertResolvedInsideDestination(params) {
|
|
115
|
+
const destinationRealDir = params.destinationRealDir;
|
|
116
|
+
const targetPath = params.targetPath;
|
|
117
|
+
const originalPath = params.originalPath;
|
|
118
|
+
assertNoWindowsPathAlias(destinationRealDir);
|
|
119
|
+
assertNoWindowsPathAlias(targetPath);
|
|
109
120
|
let resolved;
|
|
110
121
|
try {
|
|
111
|
-
resolved = realpathSync.native(
|
|
122
|
+
resolved = realpathSync.native(targetPath);
|
|
112
123
|
}
|
|
113
124
|
catch (err) {
|
|
114
125
|
if (isNotFoundPathError(err)) {
|
|
@@ -116,8 +127,9 @@ export async function assertResolvedInsideDestination(params) {
|
|
|
116
127
|
}
|
|
117
128
|
throw err;
|
|
118
129
|
}
|
|
119
|
-
|
|
120
|
-
|
|
130
|
+
assertNoWindowsPathAlias(resolved);
|
|
131
|
+
if (!isPathInside(destinationRealDir, resolved)) {
|
|
132
|
+
throw symlinkTraversalError(originalPath);
|
|
121
133
|
}
|
|
122
134
|
}
|
|
123
135
|
async function mkdirArchiveOutput(params) {
|
|
@@ -131,14 +143,28 @@ async function mkdirArchiveOutput(params) {
|
|
|
131
143
|
throw error;
|
|
132
144
|
}
|
|
133
145
|
}
|
|
146
|
+
function ownArchiveOutputPathParams(params) {
|
|
147
|
+
const deadline = params.deadline;
|
|
148
|
+
checkExtractionDeadline(deadline);
|
|
149
|
+
const destinationDir = params.destinationDir;
|
|
150
|
+
const destinationRealDir = params.destinationRealDir;
|
|
151
|
+
const relPath = params.relPath;
|
|
152
|
+
const outPath = params.outPath;
|
|
153
|
+
const originalPath = params.originalPath;
|
|
154
|
+
const isDirectory = params.isDirectory;
|
|
155
|
+
assertNoWindowsPathAlias(destinationDir);
|
|
156
|
+
assertNoWindowsPathAlias(destinationRealDir);
|
|
157
|
+
assertNoWindowsPathAlias(relPath, "relative");
|
|
158
|
+
assertNoWindowsPathAlias(outPath);
|
|
159
|
+
return { destinationDir, destinationRealDir, relPath, outPath, originalPath, isDirectory, deadline };
|
|
160
|
+
}
|
|
134
161
|
export async function prepareArchiveOutputPath(params) {
|
|
135
|
-
await prepareOutputPath(params);
|
|
162
|
+
await prepareOutputPath(ownArchiveOutputPathParams(params));
|
|
136
163
|
}
|
|
137
164
|
export async function preparePrivateArchiveOutputPath(params, assertGuards, destinationGuard) {
|
|
138
|
-
await prepareOutputPath(params, assertGuards, true, destinationGuard);
|
|
165
|
+
await prepareOutputPath(ownArchiveOutputPathParams(params), assertGuards, true, destinationGuard);
|
|
139
166
|
}
|
|
140
167
|
async function prepareOutputPath(params, assertGuards, privateWorkingMode = false, existingDestinationGuard) {
|
|
141
|
-
checkExtractionDeadline(params.deadline);
|
|
142
168
|
const targetRoot = privateWorkingMode ? {
|
|
143
169
|
async mkdir(relativePath) {
|
|
144
170
|
// Retain Root.mkdir's strict alias admission before the shared traversal,
|
|
@@ -231,6 +257,7 @@ async function prepareOutputPath(params, assertGuards, privateWorkingMode = fals
|
|
|
231
257
|
checkExtractionDeadline(params.deadline);
|
|
232
258
|
}
|
|
233
259
|
function assertSafeArchiveStagingPrefix(prefix) {
|
|
260
|
+
assertNoWindowsPathAlias(prefix, "relative");
|
|
234
261
|
if (!prefix ||
|
|
235
262
|
prefix === "." ||
|
|
236
263
|
prefix === ".." ||
|
|
@@ -242,16 +269,22 @@ function assertSafeArchiveStagingPrefix(prefix) {
|
|
|
242
269
|
return prefix;
|
|
243
270
|
}
|
|
244
271
|
export async function withStagedArchiveDestination(params) {
|
|
272
|
+
const destinationRealDir = params.destinationRealDir;
|
|
273
|
+
assertNoWindowsPathAlias(destinationRealDir);
|
|
245
274
|
const stagingRoot = resolveSecureTempRoot({
|
|
246
275
|
fallbackPrefix: "fs-safe-archive",
|
|
247
276
|
unsafeFallbackLabel: "archive staging temp dir",
|
|
248
277
|
warn: () => undefined,
|
|
249
278
|
});
|
|
250
|
-
|
|
279
|
+
assertNoWindowsPathAlias(stagingRoot);
|
|
280
|
+
if (isPathInside(destinationRealDir, stagingRoot)) {
|
|
251
281
|
throw new Error(`archive staging root must be outside destination: ${stagingRoot}`);
|
|
252
282
|
}
|
|
253
|
-
const
|
|
254
|
-
const
|
|
283
|
+
const stagingDirPrefix = params.stagingDirPrefix;
|
|
284
|
+
const stagingPrefix = assertSafeArchiveStagingPrefix(stagingDirPrefix ?? "fs-safe-archive-");
|
|
285
|
+
const stagingPathPrefix = path.join(stagingRoot, stagingPrefix);
|
|
286
|
+
assertNoWindowsPathAlias(stagingPathPrefix);
|
|
287
|
+
const stagingDir = await fs.mkdtemp(stagingPathPrefix);
|
|
255
288
|
const stagingGuard = await createDirectoryIdentityGuard(stagingDir);
|
|
256
289
|
try {
|
|
257
290
|
await fs.chmod(stagingDir, ARCHIVE_STAGING_MODE).catch(() => undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-tar-inspect.d.ts","sourceRoot":"","sources":["../src/archive-tar-inspect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-tar-inspect.d.ts","sourceRoot":"","sources":["../src/archive-tar-inspect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQrF,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,qBAAqB,EAC/D,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC,CAAC;AACzE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AAE3F,2FAA2F;AAC3F,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CA6C/G"}
|
|
@@ -8,14 +8,17 @@ import { resolveArchiveFilteredEntryPolicy } from "./archive-policy.js";
|
|
|
8
8
|
import { createTarEntryPlanner } from "./archive-tar.js";
|
|
9
9
|
import { inspectTar } from "./archive-tar-stream.js";
|
|
10
10
|
import { getNativeBinding } from "./native.js";
|
|
11
|
+
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
11
12
|
/** Complete TAR/gzip admission and zero-strip extraction policy, without output writes. */
|
|
12
13
|
export async function inspectTarArchive(params) {
|
|
14
|
+
const archivePath = params.archivePath;
|
|
13
15
|
const onFiltered = resolveArchiveFilteredEntryPolicy(params.onFiltered);
|
|
14
16
|
const limits = resolveExtractLimits(params.limits);
|
|
15
17
|
const tarLimits = resolveTarMeterLimits(limits);
|
|
16
18
|
const native = getNativeBinding();
|
|
19
|
+
assertNoWindowsPathAlias(archivePath, "filesystem", "archive source uses a Windows filesystem namespace alias");
|
|
17
20
|
return await withExtractionDeadline(params.timeoutMs, "inspect tar", async (deadline) => {
|
|
18
|
-
const staged = await stageArchiveFileForExtraction({ archivePath
|
|
21
|
+
const staged = await stageArchiveFileForExtraction({ archivePath, limits, deadline });
|
|
19
22
|
try {
|
|
20
23
|
// Staging closes descriptors asynchronously; expiry there must not start a decoder.
|
|
21
24
|
deadline.check();
|
|
@@ -2,7 +2,7 @@ import type { ExtractionDeadline } from "./archive-deadline.js";
|
|
|
2
2
|
import { type ResolvedArchiveExtractLimits } from "./archive-limits.js";
|
|
3
3
|
import { type ZipDirectoryEntry } from "./archive-zip-directory.js";
|
|
4
4
|
/** Admit physical records before a decoder can normalize or collapse names. */
|
|
5
|
-
export declare function admitZipBuffer(input: Uint8Array, limits: ResolvedArchiveExtractLimits): number;
|
|
5
|
+
export declare function admitZipBuffer(input: Uint8Array, limits: ResolvedArchiveExtractLimits, onEntry?: (entry: ZipDirectoryEntry) => void): number;
|
|
6
6
|
/** The extraction input is private and immutable; read bounded metadata windows. */
|
|
7
7
|
export declare function admitZipFile(archivePath: string, limits: ResolvedArchiveExtractLimits, deadline: ExtractionDeadline, onEntry?: (entry: ZipDirectoryEntry) => void): Promise<number>;
|
|
8
8
|
//# sourceMappingURL=archive-zip-admission.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-admission.d.ts","sourceRoot":"","sources":["../src/archive-zip-admission.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAA+C,KAAK,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAErH,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAUtF,+EAA+E;AAC/E,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"archive-zip-admission.d.ts","sourceRoot":"","sources":["../src/archive-zip-admission.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAA+C,KAAK,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAErH,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAUtF,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,4BAA4B,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GACpG,MAAM,CAUR;AAMD,oFAAoF;AACpF,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,QAAQ,EAAE,kBAAkB,EACvF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAC3C,OAAO,CAAC,MAAM,CAAC,CA8DjB"}
|
|
@@ -12,10 +12,10 @@ function checkSize(size, limits) {
|
|
|
12
12
|
zipFormat("invalid archive size");
|
|
13
13
|
}
|
|
14
14
|
/** Admit physical records before a decoder can normalize or collapse names. */
|
|
15
|
-
export function admitZipBuffer(input, limits) {
|
|
15
|
+
export function admitZipBuffer(input, limits, onEntry) {
|
|
16
16
|
checkSize(input.byteLength, limits);
|
|
17
17
|
const buffer = Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
|
18
|
-
const scan = scanZipDirectory(buffer.length, limits);
|
|
18
|
+
const scan = scanZipDirectory(buffer.length, limits, onEntry);
|
|
19
19
|
let step = scan.next();
|
|
20
20
|
while (!step.done) {
|
|
21
21
|
const { offset, length } = step.value;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ResolvedArchiveExtractLimits } from "./archive-limits.js";
|
|
2
|
+
import type { ArchiveEntryKind } from "./archive-policy.js";
|
|
2
3
|
export type ZipRead = {
|
|
3
4
|
offset: number;
|
|
4
5
|
length: number;
|
|
@@ -10,6 +11,8 @@ export type ZipDirectoryEntry = {
|
|
|
10
11
|
externalAttributes: number;
|
|
11
12
|
size: number;
|
|
12
13
|
path?: string;
|
|
14
|
+
portableKey: string;
|
|
15
|
+
kind: ArchiveEntryKind;
|
|
13
16
|
};
|
|
14
17
|
export declare function scanZipDirectory(size: number, limits: ResolvedArchiveExtractLimits, onEntry?: (entry: ZipDirectoryEntry) => void): ZipScan;
|
|
15
18
|
//# sourceMappingURL=archive-zip-directory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-directory.d.ts","sourceRoot":"","sources":["../src/archive-zip-directory.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-zip-directory.d.ts","sourceRoot":"","sources":["../src/archive-zip-directory.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,MAAM,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,gBAAgB,CAAC;CACxB,CAAC;AA4IF,wBAAiB,gBAAgB,CAC/B,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAC/F,OAAO,CAmET"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { assertArchiveEntryCountWithinLimit, } from "./archive-limits.js";
|
|
2
2
|
import { admitZipNames, zipExtraFields, zipFormat, zipUInt64 } from "./archive-zip-names.js";
|
|
3
|
+
function entryKind(attributes, directory) {
|
|
4
|
+
const type = (attributes >>> 16) & 0o170000;
|
|
5
|
+
// High-word symlinks remain links regardless of the creator or directory bits.
|
|
6
|
+
if (type === 0o120000)
|
|
7
|
+
return "symlink";
|
|
8
|
+
if ((attributes & 0x10) || type === 0o040000 || directory)
|
|
9
|
+
return "directory";
|
|
10
|
+
// Preserve the native decoder's rejection of unrecognized link-like types.
|
|
11
|
+
return (type & 0o120000) === 0o120000 ? "other" : "file";
|
|
12
|
+
}
|
|
3
13
|
function* read(offset, length, bound) {
|
|
4
14
|
if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length) || offset < 0 || length < 0 || length > bound - offset) {
|
|
5
15
|
zipFormat("record outside archive bounds");
|
|
@@ -193,7 +203,7 @@ export function* scanZipDirectory(size, limits, onEntry) {
|
|
|
193
203
|
const localExtraLength = local.readUInt16LE(28);
|
|
194
204
|
const localNames = yield* read(localAt + 30, localNameLength + localExtraLength, directory.start);
|
|
195
205
|
const localExtra = zipExtraFields(localNames.subarray(localNameLength));
|
|
196
|
-
const
|
|
206
|
+
const admittedName = admitZipNames({ central: centralName, local: localNames.subarray(0, localNameLength), flags, centralExtra, localExtra, seen });
|
|
197
207
|
const localValues = wideValues(local, localExtra, false);
|
|
198
208
|
const crc = central.readUInt32LE(16);
|
|
199
209
|
if (!(flags & 8) && (local.readUInt32LE(14) !== crc || localValues.compressed !== values.compressed || localValues.uncompressed !== values.uncompressed)) {
|
|
@@ -213,7 +223,8 @@ export function* scanZipDirectory(size, limits, onEntry) {
|
|
|
213
223
|
spans.push({ start: localAt, end: dataEnd });
|
|
214
224
|
onEntry?.({
|
|
215
225
|
index: count - 1, creatorSystem: central[5], externalAttributes: central.readUInt32LE(38),
|
|
216
|
-
size: values.uncompressed, path:
|
|
226
|
+
size: values.uncompressed, path: admittedName.path, portableKey: admittedName.portableKey,
|
|
227
|
+
kind: entryKind(central.readUInt32LE(38), admittedName.directory),
|
|
217
228
|
});
|
|
218
229
|
at = next;
|
|
219
230
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { ZipDirectoryEntry } from "./archive-zip-directory.js";
|
|
1
2
|
export type ZipArchiveWithFiles = {
|
|
2
3
|
files: Record<string, unknown>;
|
|
3
4
|
};
|
|
4
|
-
/** Internal: the caller has admitted these unchanged bytes and their
|
|
5
|
-
export declare function loadAdmittedZipArchive(buffer: Buffer | Uint8Array,
|
|
5
|
+
/** Internal: the caller has admitted these unchanged bytes and their metadata. */
|
|
6
|
+
export declare function loadAdmittedZipArchive(buffer: Buffer | Uint8Array, admitted: ZipDirectoryEntry[]): Promise<ZipArchiveWithFiles>;
|
|
6
7
|
//# sourceMappingURL=archive-zip-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-loader.d.ts","sourceRoot":"","sources":["../src/archive-zip-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive-zip-loader.d.ts","sourceRoot":"","sources":["../src/archive-zip-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIpE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAMF,kFAAkF;AAClF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,QAAQ,EAAE,iBAAiB,EAAE,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ArchiveFormatError, ArchiveSecurityError } from "./archive-errors.js";
|
|
2
2
|
import { validateArchiveEntryPath } from "./archive-entry.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { isZipSymlinkEntry } from "./archive-zip-entry.js";
|
|
4
|
+
import { zipPathKey } from "./archive-zip-names.js";
|
|
5
|
+
/** Internal: the caller has admitted these unchanged bytes and their metadata. */
|
|
6
|
+
export async function loadAdmittedZipArchive(buffer, admitted) {
|
|
5
7
|
const JSZip = await importOptionalJsZip();
|
|
6
8
|
let archive;
|
|
7
9
|
try {
|
|
@@ -11,11 +13,35 @@ export async function loadAdmittedZipArchive(buffer, entryCount) {
|
|
|
11
13
|
throw new ArchiveFormatError(`invalid ZIP archive: ${error instanceof Error ? error.message : String(error)}`, { cause: error instanceof Error ? error : undefined });
|
|
12
14
|
}
|
|
13
15
|
const names = Object.keys(archive.files);
|
|
14
|
-
if (names.length !==
|
|
16
|
+
if (names.length !== admitted.length) {
|
|
15
17
|
throw new ArchiveSecurityError("entry-path", "zip archive contains duplicate or colliding entry names");
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
// Object key order is not central-directory order (numeric names reorder).
|
|
20
|
+
// Use the admitted portable interpretation, including legacy UTF-8 decoding.
|
|
21
|
+
const physicalByPath = new Map();
|
|
22
|
+
for (const entry of admitted) {
|
|
23
|
+
physicalByPath.set(entry.portableKey, entry);
|
|
24
|
+
}
|
|
25
|
+
for (const name of names) {
|
|
18
26
|
validateArchiveEntryPath(name);
|
|
27
|
+
const key = zipPathKey(name);
|
|
28
|
+
const physical = physicalByPath.get(key);
|
|
29
|
+
const entry = archive.files[name];
|
|
30
|
+
const entryName = entry.name;
|
|
31
|
+
let entryKey = key;
|
|
32
|
+
if (entryName !== name) {
|
|
33
|
+
validateArchiveEntryPath(entryName);
|
|
34
|
+
entryKey = zipPathKey(entryName);
|
|
35
|
+
}
|
|
36
|
+
const kind = isZipSymlinkEntry(entry) ? "symlink" : entry.dir ? "directory" : "file";
|
|
37
|
+
if (!physical || entryKey !== key || kind !== physical.kind) {
|
|
38
|
+
throw new ArchiveFormatError("ZIP decoder disagrees with admitted directory metadata");
|
|
39
|
+
}
|
|
40
|
+
physicalByPath.delete(key);
|
|
41
|
+
}
|
|
42
|
+
if (physicalByPath.size) {
|
|
43
|
+
throw new ArchiveFormatError("ZIP decoder disagrees with admitted directory metadata");
|
|
44
|
+
}
|
|
19
45
|
return archive;
|
|
20
46
|
}
|
|
21
47
|
async function importOptionalJsZip() {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NativeArchiveEntry } from "./native-binding.js";
|
|
2
|
+
import type { ZipDirectoryEntry } from "./archive-zip-directory.js";
|
|
3
|
+
/** Associate all native entries with physical admission before exposing any. */
|
|
4
|
+
export declare function validateNativeZipManifest(manifest: NativeArchiveEntry[], admitted: ZipDirectoryEntry[]): void;
|
|
5
|
+
//# sourceMappingURL=archive-zip-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-zip-manifest.d.ts","sourceRoot":"","sources":["../src/archive-zip-manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,gFAAgF;AAChF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,kBAAkB,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAC5D,IAAI,CAkBN"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ArchiveFormatError, ArchiveSecurityError } from "./archive-errors.js";
|
|
2
|
+
import { stripArchivePath } from "./archive-entry.js";
|
|
3
|
+
/** Associate all native entries with physical admission before exposing any. */
|
|
4
|
+
export function validateNativeZipManifest(manifest, admitted) {
|
|
5
|
+
if (manifest.length !== admitted.length) {
|
|
6
|
+
throw new ArchiveSecurityError("entry-path", "zip decoder collapsed entry names");
|
|
7
|
+
}
|
|
8
|
+
for (const [ordinal, entry] of manifest.entries()) {
|
|
9
|
+
const physical = admitted[ordinal];
|
|
10
|
+
const physicalPath = physical?.path;
|
|
11
|
+
const pathMatches = physicalPath === undefined || entry.path === physicalPath ||
|
|
12
|
+
stripArchivePath(entry.path, 0) === stripArchivePath(physicalPath, 0);
|
|
13
|
+
// Native indices are physical central-directory ordinals. Legacy name
|
|
14
|
+
// decoding remains native-selected; compare names when admission knows them.
|
|
15
|
+
if (!physical || physical.index !== ordinal || entry.index !== ordinal ||
|
|
16
|
+
entry.size !== physical.size || entry.kind !== physical.kind ||
|
|
17
|
+
!pathMatches ||
|
|
18
|
+
(physical.creatorSystem === 3 && entry.mode !== physical.externalAttributes >>> 16)) {
|
|
19
|
+
throw new ArchiveFormatError("ZIP decoder disagrees with admitted directory metadata");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare function zipFormat(message: string): never;
|
|
2
2
|
export declare function zipUInt64(bytes: Buffer, offset: number): number;
|
|
3
3
|
export declare function zipExtraFields(bytes: Buffer): Map<number, Buffer>;
|
|
4
|
+
export declare function zipPathKey(name: string): string;
|
|
4
5
|
export declare function admitZipNames(params: {
|
|
5
6
|
central: Buffer;
|
|
6
7
|
local: Buffer;
|
|
@@ -8,5 +9,9 @@ export declare function admitZipNames(params: {
|
|
|
8
9
|
centralExtra: Map<number, Buffer>;
|
|
9
10
|
localExtra: Map<number, Buffer>;
|
|
10
11
|
seen: Set<string>;
|
|
11
|
-
}):
|
|
12
|
+
}): {
|
|
13
|
+
path?: string;
|
|
14
|
+
portableKey: string;
|
|
15
|
+
directory: boolean;
|
|
16
|
+
};
|
|
12
17
|
//# sourceMappingURL=archive-zip-names.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-names.d.ts","sourceRoot":"","sources":["../src/archive-zip-names.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive-zip-names.d.ts","sourceRoot":"","sources":["../src/archive-zip-names.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAEhD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcjE;AAUD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAoBD,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACpC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAC9C,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnB,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAiE7D"}
|