@theia/filesystem 1.77.0-next.99 → 1.77.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/lib/browser/breadcrumbs/filepath-breadcrumb.js +4 -8
- package/lib/browser/breadcrumbs/filepath-breadcrumb.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js +18 -25
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts +5 -5
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js +27 -33
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js.map +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser/download/file-download-command-contribution.js +28 -33
- package/lib/browser/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser/download/file-download-frontend-module.js +8 -10
- package/lib/browser/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser/download/file-download-service.d.ts +1 -1
- package/lib/browser/download/file-download-service.d.ts.map +1 -1
- package/lib/browser/download/file-download-service.js +19 -24
- package/lib/browser/download/file-download-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.js +25 -30
- package/lib/browser/file-dialog/file-dialog-container.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js +13 -21
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-model.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.js +20 -27
- package/lib/browser/file-dialog/file-dialog-model.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-module.js +21 -23
- package/lib/browser/file-dialog/file-dialog-module.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.d.ts +4 -4
- package/lib/browser/file-dialog/file-dialog-service.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.js +29 -38
- package/lib/browser/file-dialog/file-dialog-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js +16 -21
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js +9 -11
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-tree.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree.js +8 -11
- package/lib/browser/file-dialog/file-dialog-tree.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-widget.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.js +18 -23
- package/lib/browser/file-dialog/file-dialog-widget.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog.d.ts +6 -6
- package/lib/browser/file-dialog/file-dialog.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog.js +114 -132
- package/lib/browser/file-dialog/file-dialog.js.map +1 -1
- package/lib/browser/file-dialog/index.d.ts +4 -4
- package/lib/browser/file-dialog/index.d.ts.map +1 -1
- package/lib/browser/file-dialog/index.js +4 -7
- package/lib/browser/file-dialog/index.js.map +1 -1
- package/lib/browser/file-resource.d.ts +2 -2
- package/lib/browser/file-resource.d.ts.map +1 -1
- package/lib/browser/file-resource.js +64 -71
- package/lib/browser/file-resource.js.map +1 -1
- package/lib/browser/file-resource.spec.js +39 -42
- package/lib/browser/file-resource.spec.js.map +1 -1
- package/lib/browser/file-selection.d.ts +1 -1
- package/lib/browser/file-selection.d.ts.map +1 -1
- package/lib/browser/file-selection.js +7 -10
- package/lib/browser/file-selection.js.map +1 -1
- package/lib/browser/file-service-activation.spec.js +14 -16
- package/lib/browser/file-service-activation.spec.js.map +1 -1
- package/lib/browser/file-service-copy.spec.js +44 -47
- package/lib/browser/file-service-copy.spec.js.map +1 -1
- package/lib/browser/file-service-watcher.spec.js +199 -202
- package/lib/browser/file-service-watcher.spec.js.map +1 -1
- package/lib/browser/file-service.d.ts +3 -3
- package/lib/browser/file-service.d.ts.map +1 -1
- package/lib/browser/file-service.js +166 -181
- package/lib/browser/file-service.js.map +1 -1
- package/lib/browser/file-tree/file-tree-container.js +12 -15
- package/lib/browser/file-tree/file-tree-container.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.js +23 -31
- package/lib/browser/file-tree/file-tree-decorator-adapter.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js +26 -29
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.js +13 -18
- package/lib/browser/file-tree/file-tree-label-provider.js.map +1 -1
- package/lib/browser/file-tree/file-tree-model.d.ts +5 -5
- package/lib/browser/file-tree/file-tree-model.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-model.js +48 -52
- package/lib/browser/file-tree/file-tree-model.js.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts +3 -3
- package/lib/browser/file-tree/file-tree-widget.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.js +66 -72
- package/lib/browser/file-tree/file-tree-widget.js.map +1 -1
- package/lib/browser/file-tree/file-tree.d.ts +3 -3
- package/lib/browser/file-tree/file-tree.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree.js +26 -31
- package/lib/browser/file-tree/file-tree.js.map +1 -1
- package/lib/browser/file-tree/index.d.ts +6 -6
- package/lib/browser/file-tree/index.d.ts.map +1 -1
- package/lib/browser/file-tree/index.js +6 -9
- package/lib/browser/file-tree/index.js.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.d.ts +6 -6
- package/lib/browser/filesystem-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.js +75 -90
- package/lib/browser/filesystem-frontend-contribution.js.map +1 -1
- package/lib/browser/filesystem-frontend-module.js +47 -50
- package/lib/browser/filesystem-frontend-module.js.map +1 -1
- package/lib/browser/filesystem-saveable-service.d.ts +2 -2
- package/lib/browser/filesystem-saveable-service.d.ts.map +1 -1
- package/lib/browser/filesystem-saveable-service.js +35 -44
- package/lib/browser/filesystem-saveable-service.js.map +1 -1
- package/lib/browser/filesystem-watcher-error-handler.js +13 -18
- package/lib/browser/filesystem-watcher-error-handler.js.map +1 -1
- package/lib/browser/index.d.ts +4 -4
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +4 -7
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/location/index.d.ts +2 -2
- package/lib/browser/location/index.d.ts.map +1 -1
- package/lib/browser/location/index.js +2 -5
- package/lib/browser/location/index.js.map +1 -1
- package/lib/browser/location/location-renderer.d.ts +3 -3
- package/lib/browser/location/location-renderer.d.ts.map +1 -1
- package/lib/browser/location/location-renderer.js +42 -51
- package/lib/browser/location/location-renderer.js.map +1 -1
- package/lib/browser/location/location-renderer.spec.js +61 -64
- package/lib/browser/location/location-renderer.spec.js.map +1 -1
- package/lib/browser/location/location-service.js +1 -2
- package/lib/browser/location/location-service.js.map +1 -1
- package/lib/browser/remote-file-service-contribution.d.ts +2 -2
- package/lib/browser/remote-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/remote-file-service-contribution.js +8 -12
- package/lib/browser/remote-file-service-contribution.js.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.js +55 -64
- package/lib/browser/upload/file-upload-service-impl.js.map +1 -1
- package/lib/browser/vscode-file-service-contribution.d.ts +2 -2
- package/lib/browser/vscode-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/vscode-file-service-contribution.js +23 -28
- package/lib/browser/vscode-file-service-contribution.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +21 -23
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.js +10 -13
- package/lib/browser-only/browser-only-filesystem-provider-server.js.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.js +14 -19
- package/lib/browser-only/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser-only/download/file-download-frontend-module.js +8 -10
- package/lib/browser-only/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser-only/download/file-download-service.d.ts +3 -3
- package/lib/browser-only/download/file-download-service.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-service.js +26 -33
- package/lib/browser-only/download/file-download-service.js.map +1 -1
- package/lib/browser-only/file-search.d.ts.map +1 -1
- package/lib/browser-only/file-search.js +9 -15
- package/lib/browser-only/file-search.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.js +6 -9
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.d.ts +2 -2
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.js +60 -68
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser-only/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.js +51 -60
- package/lib/browser-only/upload/file-upload-service-impl.js.map +1 -1
- package/lib/common/delegating-file-system-provider.d.ts +1 -1
- package/lib/common/delegating-file-system-provider.d.ts.map +1 -1
- package/lib/common/delegating-file-system-provider.js +18 -22
- package/lib/common/delegating-file-system-provider.js.map +1 -1
- package/lib/common/download/file-download.js +5 -8
- package/lib/common/download/file-download.js.map +1 -1
- package/lib/common/file-upload.js +1 -4
- package/lib/common/file-upload.js.map +1 -1
- package/lib/common/files.js +38 -59
- package/lib/common/files.js.map +1 -1
- package/lib/common/files.spec.js +22 -25
- package/lib/common/files.spec.js.map +1 -1
- package/lib/common/filesystem-preferences.js +39 -44
- package/lib/common/filesystem-preferences.js.map +1 -1
- package/lib/common/filesystem-utils.d.ts +1 -1
- package/lib/common/filesystem-utils.d.ts.map +1 -1
- package/lib/common/filesystem-utils.js +2 -5
- package/lib/common/filesystem-utils.js.map +1 -1
- package/lib/common/filesystem-utils.spec.js +227 -229
- package/lib/common/filesystem-utils.spec.js.map +1 -1
- package/lib/common/filesystem-watcher-protocol.d.ts +1 -1
- package/lib/common/filesystem-watcher-protocol.d.ts.map +1 -1
- package/lib/common/filesystem-watcher-protocol.js +2 -5
- package/lib/common/filesystem-watcher-protocol.js.map +1 -1
- package/lib/common/filesystem.js +2 -5
- package/lib/common/filesystem.js.map +1 -1
- package/lib/common/index.d.ts +3 -3
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -6
- package/lib/common/index.js.map +1 -1
- package/lib/common/io.d.ts +2 -2
- package/lib/common/io.d.ts.map +1 -1
- package/lib/common/io.js +10 -13
- package/lib/common/io.js.map +1 -1
- package/lib/common/remote-file-system-provider.d.ts +5 -5
- package/lib/common/remote-file-system-provider.d.ts.map +1 -1
- package/lib/common/remote-file-system-provider.js +81 -93
- package/lib/common/remote-file-system-provider.js.map +1 -1
- package/lib/common/upload/file-upload.js +1 -4
- package/lib/common/upload/file-upload.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js +6 -8
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts +3 -3
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js +21 -23
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js +33 -12
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js.map +1 -1
- package/lib/electron-browser/preload.js +6 -9
- package/lib/electron-browser/preload.js.map +1 -1
- package/lib/electron-common/electron-api.d.ts +4 -0
- package/lib/electron-common/electron-api.d.ts.map +1 -1
- package/lib/electron-common/electron-api.js +2 -5
- package/lib/electron-common/electron-api.js.map +1 -1
- package/lib/electron-main/electron-api-main.d.ts.map +1 -1
- package/lib/electron-main/electron-api-main.js +19 -18
- package/lib/electron-main/electron-api-main.js.map +1 -1
- package/lib/electron-main/electron-main-module.js +6 -8
- package/lib/electron-main/electron-main-module.js.map +1 -1
- package/lib/node/archive/archive-extractor.d.ts +86 -0
- package/lib/node/archive/archive-extractor.d.ts.map +1 -0
- package/lib/node/archive/archive-extractor.js +290 -0
- package/lib/node/archive/archive-extractor.js.map +1 -0
- package/lib/node/archive/archive-extractor.spec.d.ts +2 -0
- package/lib/node/archive/archive-extractor.spec.d.ts.map +1 -0
- package/lib/node/archive/archive-extractor.spec.js +317 -0
- package/lib/node/archive/archive-extractor.spec.js.map +1 -0
- package/lib/node/archive/test/test-archives.d.ts +20 -0
- package/lib/node/archive/test/test-archives.d.ts.map +1 -0
- package/lib/node/archive/test/test-archives.js +97 -0
- package/lib/node/archive/test/test-archives.js.map +1 -0
- package/lib/node/disk-file-system-provider.d.ts +2 -2
- package/lib/node/disk-file-system-provider.d.ts.map +1 -1
- package/lib/node/disk-file-system-provider.js +111 -119
- package/lib/node/disk-file-system-provider.js.map +1 -1
- package/lib/node/disk-file-system-provider.spec.js +53 -56
- package/lib/node/disk-file-system-provider.spec.js.map +1 -1
- package/lib/node/download/directory-archiver.js +13 -16
- package/lib/node/download/directory-archiver.js.map +1 -1
- package/lib/node/download/directory-archiver.spec.js +20 -23
- package/lib/node/download/directory-archiver.spec.js.map +1 -1
- package/lib/node/download/file-download-backend-module.js +14 -16
- package/lib/node/download/file-download-backend-module.js.map +1 -1
- package/lib/node/download/file-download-cache.js +11 -15
- package/lib/node/download/file-download-cache.js.map +1 -1
- package/lib/node/download/file-download-endpoint.d.ts +1 -1
- package/lib/node/download/file-download-endpoint.d.ts.map +1 -1
- package/lib/node/download/file-download-endpoint.js +25 -31
- package/lib/node/download/file-download-endpoint.js.map +1 -1
- package/lib/node/download/file-download-handler.d.ts +2 -2
- package/lib/node/download/file-download-handler.d.ts.map +1 -1
- package/lib/node/download/file-download-handler.js +70 -76
- package/lib/node/download/file-download-handler.js.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.js +2 -6
- package/lib/node/download/test/mock-directory-archiver.js.map +1 -1
- package/lib/node/file-change-collection.d.ts +1 -1
- package/lib/node/file-change-collection.d.ts.map +1 -1
- package/lib/node/file-change-collection.js +1 -5
- package/lib/node/file-change-collection.js.map +1 -1
- package/lib/node/file-change-collection.spec.js +5 -8
- package/lib/node/file-change-collection.spec.js.map +1 -1
- package/lib/node/filesystem-backend-module.d.ts +1 -1
- package/lib/node/filesystem-backend-module.d.ts.map +1 -1
- package/lib/node/filesystem-backend-module.js +60 -64
- package/lib/node/filesystem-backend-module.js.map +1 -1
- package/lib/node/filesystem-watcher-client.d.ts +2 -2
- package/lib/node/filesystem-watcher-client.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-client.js +11 -16
- package/lib/node/filesystem-watcher-client.js.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.js +9 -13
- package/lib/node/filesystem-watcher-dispatcher.js.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.d.ts +3 -3
- package/lib/node/filesystem-watcher-service-impl.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.js +7 -11
- package/lib/node/filesystem-watcher-service-impl.js.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.spec.js +23 -26
- package/lib/node/filesystem-watcher-service-impl.spec.js.map +1 -1
- package/lib/node/filesystem-watcher.d.ts +1 -1
- package/lib/node/filesystem-watcher.d.ts.map +1 -1
- package/lib/node/filesystem-watcher.js +6 -11
- package/lib/node/filesystem-watcher.js.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts +4 -4
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.js +20 -26
- package/lib/node/nodejs-watcher/node-directory-watcher.js.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js +51 -54
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js.map +1 -1
- package/lib/node/nodejs-watcher/watch-request-router.d.ts +3 -3
- package/lib/node/nodejs-watcher/watch-request-router.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/watch-request-router.js +8 -13
- package/lib/node/nodejs-watcher/watch-request-router.js.map +1 -1
- package/lib/node/nodejs-watcher/watcher-host.d.ts +1 -1
- package/lib/node/nodejs-watcher/watcher-host.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/watcher-host.js +7 -12
- package/lib/node/nodejs-watcher/watcher-host.js.map +1 -1
- package/lib/node/parcel-watcher/index.js +6 -9
- package/lib/node/parcel-watcher/index.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts +4 -4
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.js +4 -8
- package/lib/node/parcel-watcher/parcel-filesystem-service.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js +23 -26
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-options.js +1 -4
- package/lib/node/parcel-watcher/parcel-options.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js +11 -16
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js +11 -16
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher.d.ts +3 -3
- package/lib/node/parcel-watcher/parcel-watcher.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher.js +28 -32
- package/lib/node/parcel-watcher/parcel-watcher.js.map +1 -1
- package/lib/node/test/watcher-test-helper.d.ts +1 -1
- package/lib/node/test/watcher-test-helper.d.ts.map +1 -1
- package/lib/node/test/watcher-test-helper.js +5 -10
- package/lib/node/test/watcher-test-helper.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts.map +1 -1
- package/lib/node/upload/node-file-upload-service.js +20 -25
- package/lib/node/upload/node-file-upload-service.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.spec.js +21 -24
- package/lib/node/upload/node-file-upload-service.spec.js.map +1 -1
- package/package.json +21 -5
- package/src/browser/breadcrumbs/filepath-breadcrumb.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-container.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-contribution.ts +5 -5
- package/src/browser/download/file-download-command-contribution.ts +1 -1
- package/src/browser/download/file-download-frontend-module.ts +3 -3
- package/src/browser/download/file-download-service.ts +1 -1
- package/src/browser/file-dialog/file-dialog-container.ts +5 -5
- package/src/browser/file-dialog/file-dialog-hidden-files-renderer.tsx +1 -1
- package/src/browser/file-dialog/file-dialog-model.ts +2 -2
- package/src/browser/file-dialog/file-dialog-module.ts +5 -5
- package/src/browser/file-dialog/file-dialog-service.ts +4 -4
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.spec.ts +2 -2
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.tsx +1 -1
- package/src/browser/file-dialog/file-dialog-tree.ts +2 -2
- package/src/browser/file-dialog/file-dialog-widget.ts +2 -2
- package/src/browser/file-dialog/file-dialog.ts +16 -13
- package/src/browser/file-dialog/index.ts +4 -4
- package/src/browser/file-resource.spec.ts +3 -3
- package/src/browser/file-resource.ts +3 -3
- package/src/browser/file-selection.ts +1 -1
- package/src/browser/file-service-activation.spec.ts +2 -2
- package/src/browser/file-service-copy.spec.ts +2 -2
- package/src/browser/file-service-watcher.spec.ts +2 -2
- package/src/browser/file-service.ts +6 -6
- package/src/browser/file-tree/file-tree-container.ts +3 -3
- package/src/browser/file-tree/file-tree-decorator-adapter.spec.ts +1 -1
- package/src/browser/file-tree/file-tree-decorator-adapter.ts +1 -1
- package/src/browser/file-tree/file-tree-label-provider.ts +1 -1
- package/src/browser/file-tree/file-tree-model.ts +12 -6
- package/src/browser/file-tree/file-tree-widget.tsx +8 -5
- package/src/browser/file-tree/file-tree.ts +3 -3
- package/src/browser/file-tree/index.ts +6 -6
- package/src/browser/filesystem-frontend-contribution.ts +6 -6
- package/src/browser/filesystem-frontend-module.ts +14 -14
- package/src/browser/filesystem-saveable-service.ts +2 -2
- package/src/browser/index.ts +4 -4
- package/src/browser/location/index.ts +2 -2
- package/src/browser/location/location-renderer.spec.ts +3 -3
- package/src/browser/location/location-renderer.tsx +3 -3
- package/src/browser/remote-file-service-contribution.ts +2 -2
- package/src/browser/upload/file-upload-service-impl.ts +5 -5
- package/src/browser/vscode-file-service-contribution.ts +2 -2
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +7 -7
- package/src/browser-only/browser-only-filesystem-provider-server.ts +1 -1
- package/src/browser-only/download/file-download-command-contribution.ts +2 -2
- package/src/browser-only/download/file-download-frontend-module.ts +3 -3
- package/src/browser-only/download/file-download-service.ts +3 -3
- package/src/browser-only/file-search.ts +2 -1
- package/src/browser-only/opfs-filesystem-initialization.ts +1 -1
- package/src/browser-only/opfs-filesystem-provider.ts +3 -3
- package/src/browser-only/upload/file-upload-service-impl.ts +4 -4
- package/src/common/delegating-file-system-provider.ts +1 -1
- package/src/common/files.spec.ts +1 -1
- package/src/common/filesystem-utils.spec.ts +2 -2
- package/src/common/filesystem-utils.ts +1 -1
- package/src/common/filesystem-watcher-protocol.ts +1 -1
- package/src/common/index.ts +3 -3
- package/src/common/io.ts +2 -2
- package/src/common/remote-file-system-provider.ts +1 -1
- package/src/electron-browser/file-dialog/electron-file-dialog-module.ts +2 -2
- package/src/electron-browser/file-dialog/electron-file-dialog-service.spec.ts +30 -3
- package/src/electron-browser/file-dialog/electron-file-dialog-service.ts +8 -6
- package/src/electron-browser/preload.ts +1 -1
- package/src/electron-common/electron-api.ts +4 -0
- package/src/electron-main/electron-api-main.ts +7 -3
- package/src/electron-main/electron-main-module.ts +1 -1
- package/src/node/archive/archive-extractor.spec.ts +359 -0
- package/src/node/archive/archive-extractor.ts +350 -0
- package/src/node/archive/test/test-archives.ts +117 -0
- package/src/node/disk-file-system-provider.spec.ts +3 -3
- package/src/node/disk-file-system-provider.ts +7 -6
- package/src/node/download/directory-archiver.spec.ts +1 -1
- package/src/node/download/file-download-backend-module.ts +4 -4
- package/src/node/download/file-download-endpoint.ts +4 -3
- package/src/node/download/file-download-handler.ts +3 -3
- package/src/node/download/test/mock-directory-archiver.ts +1 -1
- package/src/node/file-change-collection.spec.ts +2 -2
- package/src/node/file-change-collection.ts +1 -1
- package/src/node/filesystem-backend-module.ts +15 -12
- package/src/node/filesystem-watcher-client.ts +2 -2
- package/src/node/filesystem-watcher-dispatcher.ts +1 -1
- package/src/node/filesystem-watcher-service-impl.spec.ts +5 -5
- package/src/node/filesystem-watcher-service-impl.ts +4 -4
- package/src/node/filesystem-watcher.ts +1 -1
- package/src/node/nodejs-watcher/node-directory-watcher.spec.ts +5 -5
- package/src/node/nodejs-watcher/node-directory-watcher.ts +5 -5
- package/src/node/nodejs-watcher/watch-request-router.ts +4 -4
- package/src/node/nodejs-watcher/watcher-host.ts +1 -1
- package/src/node/parcel-watcher/index.ts +2 -2
- package/src/node/parcel-watcher/parcel-filesystem-service.ts +4 -4
- package/src/node/parcel-watcher/parcel-filesystem-watcher.spec.ts +2 -2
- package/src/node/parcel-watcher/parcel-watcher-exclude.spec.ts +4 -8
- package/src/node/parcel-watcher/parcel-watcher-retry.spec.ts +4 -6
- package/src/node/parcel-watcher/parcel-watcher.ts +7 -6
- package/src/node/test/watcher-test-helper.ts +1 -1
- package/src/node/upload/node-file-upload-service.spec.ts +1 -1
- package/src/node/upload/node-file-upload-service.ts +6 -6
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
import { __decorate } from "tslib";
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import { Readable } from 'stream';
|
|
20
|
+
import { pipeline } from 'stream/promises';
|
|
21
|
+
import { createGunzip } from 'zlib';
|
|
22
|
+
import * as yauzl from 'yauzl';
|
|
23
|
+
import * as tarStream from 'tar-stream';
|
|
24
|
+
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
|
25
|
+
import { ILogger } from '@theia/core/lib/common/logger';
|
|
26
|
+
export const ArchiveExtractor = Symbol('ArchiveExtractor');
|
|
27
|
+
const S_IFMT = 0o170000;
|
|
28
|
+
const S_IFREG = 0o100000;
|
|
29
|
+
const S_IFDIR = 0o040000;
|
|
30
|
+
const PERMISSION_BITS = 0o777;
|
|
31
|
+
/**
|
|
32
|
+
* Existing links are rejected before a file is opened; `O_NOFOLLOW` additionally guards against a link created in between
|
|
33
|
+
* where the platform supports it, which Windows does not.
|
|
34
|
+
*/
|
|
35
|
+
const WRITE_FLAGS = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_TRUNC | (fs.constants.O_NOFOLLOW ?? 0);
|
|
36
|
+
let ArchiveExtractorImpl = class ArchiveExtractorImpl {
|
|
37
|
+
async extract(source, destination, options = {}) {
|
|
38
|
+
await fs.promises.mkdir(destination, { recursive: true });
|
|
39
|
+
const root = await fs.promises.realpath(destination);
|
|
40
|
+
const verifiedDirectories = new Set([root]);
|
|
41
|
+
const entries = [];
|
|
42
|
+
const skipped = [];
|
|
43
|
+
await this.readEntries(source, options.format, async (entry) => {
|
|
44
|
+
const entryPath = this.toEntryPath(entry.name);
|
|
45
|
+
if (!entryPath) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (entry.kind === 'unsupported') {
|
|
49
|
+
skipped.push(entryPath);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const target = path.join(root, ...entryPath.split('/'));
|
|
53
|
+
if (entry.kind === 'directory') {
|
|
54
|
+
await this.createDirectory(root, target, verifiedDirectories);
|
|
55
|
+
entries.push({ path: entryPath, type: 'directory', mode: entry.mode });
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
await this.createDirectory(root, path.dirname(target), verifiedDirectories);
|
|
59
|
+
await this.assertNoLink(root, target);
|
|
60
|
+
await this.writeFile(target, await entry.open(), entry.mode);
|
|
61
|
+
entries.push({ path: entryPath, type: 'file', mode: entry.mode });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
this.reportSkipped(source, skipped);
|
|
65
|
+
return entries;
|
|
66
|
+
}
|
|
67
|
+
async readFiles(source, options = {}) {
|
|
68
|
+
const files = [];
|
|
69
|
+
const skipped = [];
|
|
70
|
+
await this.readEntries(source, options.format, async (entry) => {
|
|
71
|
+
const entryPath = this.toEntryPath(entry.name);
|
|
72
|
+
if (entryPath && entry.kind === 'unsupported') {
|
|
73
|
+
skipped.push(entryPath);
|
|
74
|
+
}
|
|
75
|
+
if (!entryPath || entry.kind !== 'file' || (options.filter && !options.filter(entryPath))) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const chunks = [];
|
|
79
|
+
for await (const chunk of await entry.open()) {
|
|
80
|
+
chunks.push(chunk);
|
|
81
|
+
}
|
|
82
|
+
files.push({ path: entryPath, type: 'file', mode: entry.mode, data: Buffer.concat(chunks) });
|
|
83
|
+
});
|
|
84
|
+
this.reportSkipped(source, skipped);
|
|
85
|
+
return files;
|
|
86
|
+
}
|
|
87
|
+
async readEntries(source, format, visit) {
|
|
88
|
+
switch (format ?? await this.detectFormat(source)) {
|
|
89
|
+
case 'zip':
|
|
90
|
+
return this.readZipEntries(source, visit);
|
|
91
|
+
case 'tar':
|
|
92
|
+
return this.readTarEntries(source, false, visit);
|
|
93
|
+
case 'tgz':
|
|
94
|
+
return this.readTarEntries(source, true, visit);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Detects the format of an archive from its first bytes.
|
|
99
|
+
*/
|
|
100
|
+
async detectFormat(source) {
|
|
101
|
+
const header = await this.readHeader(source, 512);
|
|
102
|
+
if (header.length >= 4 && header[0] === 0x50 && header[1] === 0x4b && ((header[2] === 0x03 && header[3] === 0x04) || (header[2] === 0x05 && header[3] === 0x06))) {
|
|
103
|
+
return 'zip';
|
|
104
|
+
}
|
|
105
|
+
if (header.length >= 2 && header[0] === 0x1f && header[1] === 0x8b) {
|
|
106
|
+
return 'tgz';
|
|
107
|
+
}
|
|
108
|
+
if (header.length >= 262 && header.toString('latin1', 257, 262) === 'ustar') {
|
|
109
|
+
return 'tar';
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Unsupported archive format${typeof source === 'string' ? `: ${source}` : ''}`);
|
|
112
|
+
}
|
|
113
|
+
async readHeader(source, length) {
|
|
114
|
+
if (typeof source !== 'string') {
|
|
115
|
+
return Buffer.from(source.subarray(0, length));
|
|
116
|
+
}
|
|
117
|
+
const handle = await fs.promises.open(source, 'r');
|
|
118
|
+
try {
|
|
119
|
+
const buffer = Buffer.alloc(length);
|
|
120
|
+
const { bytesRead } = await handle.read(buffer, 0, length, 0);
|
|
121
|
+
return buffer.subarray(0, bytesRead);
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
await handle.close();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async readZipEntries(source, visit) {
|
|
128
|
+
const zipFile = typeof source === 'string'
|
|
129
|
+
? await yauzl.openPromise(source)
|
|
130
|
+
: await yauzl.fromBufferPromise(Buffer.from(source));
|
|
131
|
+
try {
|
|
132
|
+
for await (const entry of zipFile.eachEntry()) {
|
|
133
|
+
// The upper 16 bits hold the Unix mode if the archive was created on a Unix system, and are 0 otherwise.
|
|
134
|
+
const unixMode = entry.externalFileAttributes >>> 16;
|
|
135
|
+
const fileType = unixMode & S_IFMT;
|
|
136
|
+
let kind;
|
|
137
|
+
if (entry.fileName.endsWith('/') || fileType === S_IFDIR) {
|
|
138
|
+
kind = 'directory';
|
|
139
|
+
}
|
|
140
|
+
else if (fileType === 0 || fileType === S_IFREG) {
|
|
141
|
+
kind = 'file';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
kind = 'unsupported';
|
|
145
|
+
}
|
|
146
|
+
await visit({
|
|
147
|
+
name: entry.fileName,
|
|
148
|
+
kind,
|
|
149
|
+
mode: this.toMode(unixMode),
|
|
150
|
+
open: () => zipFile.openReadStreamPromise(entry)
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
if (zipFile.isOpen) {
|
|
156
|
+
zipFile.close();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async readTarEntries(source, gzipped, visit) {
|
|
161
|
+
const input = typeof source === 'string' ? fs.createReadStream(source) : Readable.from([Buffer.from(source)]);
|
|
162
|
+
const extract = tarStream.extract();
|
|
163
|
+
const streams = gzipped ? [createGunzip()] : [];
|
|
164
|
+
// Resolves with the error instead of rejecting, so that a failure is not unhandled while entries are visited.
|
|
165
|
+
const feeding = pipeline([input, ...streams, extract]).then(() => undefined, (reason) => reason);
|
|
166
|
+
try {
|
|
167
|
+
for await (const entry of extract) {
|
|
168
|
+
const header = entry.header;
|
|
169
|
+
let kind;
|
|
170
|
+
if (header.type === 'file' || header.type === 'contiguous-file') {
|
|
171
|
+
kind = 'file';
|
|
172
|
+
}
|
|
173
|
+
else if (header.type === 'directory') {
|
|
174
|
+
kind = 'directory';
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
kind = 'unsupported';
|
|
178
|
+
}
|
|
179
|
+
let consumed = false;
|
|
180
|
+
await visit({
|
|
181
|
+
name: header.name,
|
|
182
|
+
kind,
|
|
183
|
+
mode: this.toMode(header.mode),
|
|
184
|
+
open: async () => {
|
|
185
|
+
consumed = true;
|
|
186
|
+
// Entries are not Node streams: Node's `pipeline` would wait forever for an entry that a failing archive
|
|
187
|
+
// already destroyed, while a stream created from the entry fails.
|
|
188
|
+
return Readable.from(entry);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
if (!consumed) {
|
|
192
|
+
entry.resume();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
input.destroy();
|
|
198
|
+
await feeding;
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
const feedError = await feeding;
|
|
202
|
+
if (feedError) {
|
|
203
|
+
throw feedError;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Normalizes the name of an entry to a relative path with `/` as separator.
|
|
208
|
+
* @returns `undefined` for the archive root.
|
|
209
|
+
* @throws if the name is absolute or leaves the archive root.
|
|
210
|
+
*/
|
|
211
|
+
toEntryPath(name) {
|
|
212
|
+
const normalized = name.replace(/\\/g, '/');
|
|
213
|
+
if (normalized.startsWith('/') || /^[a-zA-Z]:/.test(normalized)) {
|
|
214
|
+
throw new Error(`Archive entry has an absolute path: ${name}`);
|
|
215
|
+
}
|
|
216
|
+
const segments = normalized.split('/').filter(segment => segment && segment !== '.');
|
|
217
|
+
if (segments.includes('..')) {
|
|
218
|
+
throw new Error(`Archive entry leaves the extraction directory: ${name}`);
|
|
219
|
+
}
|
|
220
|
+
return segments.length > 0 ? segments.join('/') : undefined;
|
|
221
|
+
}
|
|
222
|
+
toMode(mode) {
|
|
223
|
+
const permissions = (mode ?? 0) & PERMISSION_BITS;
|
|
224
|
+
return permissions || undefined;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Creates a directory below the root one segment at a time and refuses to descend into an existing entry that is not
|
|
228
|
+
* a directory, so that nothing is created or written through a link that already existed in the destination.
|
|
229
|
+
*/
|
|
230
|
+
async createDirectory(root, directory, verifiedDirectories) {
|
|
231
|
+
let current = root;
|
|
232
|
+
for (const segment of path.relative(root, directory).split(path.sep)) {
|
|
233
|
+
current = path.join(current, segment);
|
|
234
|
+
if (verifiedDirectories.has(current)) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
await fs.promises.mkdir(current);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (error.code !== 'EEXIST') {
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
if (!(await fs.promises.lstat(current)).isDirectory()) {
|
|
245
|
+
throw new Error(`Archive entry leaves the extraction directory: ${path.relative(root, current)}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
verifiedDirectories.add(current);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Rejects writing a file over an existing link or special file, which could point outside of the destination.
|
|
253
|
+
*/
|
|
254
|
+
async assertNoLink(root, target) {
|
|
255
|
+
const existing = await fs.promises.lstat(target).catch((error) => {
|
|
256
|
+
if (error.code === 'ENOENT') {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
throw error;
|
|
260
|
+
});
|
|
261
|
+
if (existing && !existing.isFile()) {
|
|
262
|
+
throw new Error(`Archive entry would be written through a link or special file: ${path.relative(root, target)}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async writeFile(target, content, mode) {
|
|
266
|
+
const handle = await fs.promises.open(target, WRITE_FLAGS, mode ?? 0o666);
|
|
267
|
+
await pipeline(content, handle.createWriteStream());
|
|
268
|
+
}
|
|
269
|
+
reportSkipped(source, skipped) {
|
|
270
|
+
if (skipped.length > 0) {
|
|
271
|
+
const message = `Skipped ${skipped.length} link or special entries of archive${typeof source === 'string' ? ` ${source}` : ''}: ${skipped.join(', ')}`;
|
|
272
|
+
if (this.logger) {
|
|
273
|
+
this.logger.warn(message);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// eslint-disable-next-line @theia/named-logger-check
|
|
277
|
+
console.warn(message);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
__decorate([
|
|
283
|
+
inject(ILogger),
|
|
284
|
+
named('filesystem:ArchiveExtractorImpl')
|
|
285
|
+
], ArchiveExtractorImpl.prototype, "logger", void 0);
|
|
286
|
+
ArchiveExtractorImpl = __decorate([
|
|
287
|
+
injectable()
|
|
288
|
+
], ArchiveExtractorImpl);
|
|
289
|
+
export { ArchiveExtractorImpl };
|
|
290
|
+
//# sourceMappingURL=archive-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-extractor.js","sourceRoot":"","sources":["../../../src/node/archive/archive-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-extractor.spec.d.ts","sourceRoot":"","sources":["../../../src/node/archive/archive-extractor.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import { randomBytes } from 'crypto';
|
|
18
|
+
import * as os from 'os';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
import { expect } from 'chai';
|
|
21
|
+
import * as sinon from 'sinon';
|
|
22
|
+
import { ArchiveExtractorImpl } from './archive-extractor.js';
|
|
23
|
+
import { createTestTar, createTestZip } from './test/test-archives.js';
|
|
24
|
+
const isWindows = process.platform === 'win32';
|
|
25
|
+
describe('ArchiveExtractorImpl', () => {
|
|
26
|
+
let workspace;
|
|
27
|
+
let destination;
|
|
28
|
+
let outside;
|
|
29
|
+
let warnings;
|
|
30
|
+
class TestArchiveExtractor extends ArchiveExtractorImpl {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(...arguments);
|
|
33
|
+
this.logger = { warn: (message) => warnings.push(message) };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const extractor = new TestArchiveExtractor();
|
|
37
|
+
beforeEach(async () => {
|
|
38
|
+
workspace = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'archive-extractor-'));
|
|
39
|
+
destination = path.join(workspace, 'out');
|
|
40
|
+
outside = path.join(workspace, 'outside');
|
|
41
|
+
await fs.promises.mkdir(outside);
|
|
42
|
+
warnings = [];
|
|
43
|
+
});
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
await fs.promises.rm(workspace, { recursive: true, force: true });
|
|
46
|
+
});
|
|
47
|
+
async function expectRejection(promise, message) {
|
|
48
|
+
try {
|
|
49
|
+
await promise;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
expect(String(error)).to.match(message);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
expect.fail('Expected the promise to be rejected');
|
|
56
|
+
}
|
|
57
|
+
async function listFiles(directory) {
|
|
58
|
+
const entries = await fs.promises.readdir(directory, { recursive: true });
|
|
59
|
+
return entries.map(entry => entry.split(path.sep).join('/')).sort();
|
|
60
|
+
}
|
|
61
|
+
/** Creating a file link on Windows requires elevated rights or developer mode. */
|
|
62
|
+
async function createFileLink(target, link) {
|
|
63
|
+
try {
|
|
64
|
+
await fs.promises.symlink(target, link, 'file');
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (isWindows && error.code === 'EPERM') {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function writeArchive(name, content) {
|
|
75
|
+
const archivePath = path.join(workspace, name);
|
|
76
|
+
await fs.promises.writeFile(archivePath, content);
|
|
77
|
+
return archivePath;
|
|
78
|
+
}
|
|
79
|
+
const formats = [
|
|
80
|
+
{
|
|
81
|
+
name: 'zip',
|
|
82
|
+
create: async (entries) => createTestZip(entries.map(entry => ({
|
|
83
|
+
name: entry.type === 'directory' ? entry.name + '/' : entry.name,
|
|
84
|
+
mode: (entry.type === 'directory' ? 0o040000 : 0o100000) | (entry.mode ?? (entry.type === 'directory' ? 0o755 : 0o644)),
|
|
85
|
+
data: entry.data
|
|
86
|
+
})))
|
|
87
|
+
},
|
|
88
|
+
{ name: 'tar', create: entries => createTestTar(entries) },
|
|
89
|
+
{ name: 'tgz', create: entries => createTestTar(entries, true) }
|
|
90
|
+
];
|
|
91
|
+
for (const format of formats) {
|
|
92
|
+
describe(format.name, () => {
|
|
93
|
+
it('extracts files and directories from a path', async () => {
|
|
94
|
+
const archive = await writeArchive(`archive.${format.name}`, await format.create([
|
|
95
|
+
{ name: 'extension', type: 'directory' },
|
|
96
|
+
{ name: 'extension/package.json', data: '{}' },
|
|
97
|
+
{ name: 'extension/nested/file.txt', data: 'content' }
|
|
98
|
+
]));
|
|
99
|
+
const entries = await extractor.extract(archive, destination);
|
|
100
|
+
expect(entries.map(entry => `${entry.type}:${entry.path}`)).to.deep.equal([
|
|
101
|
+
'directory:extension',
|
|
102
|
+
'file:extension/package.json',
|
|
103
|
+
'file:extension/nested/file.txt'
|
|
104
|
+
]);
|
|
105
|
+
expect(await fs.promises.readFile(path.join(destination, 'extension', 'nested', 'file.txt'), 'utf8')).to.equal('content');
|
|
106
|
+
});
|
|
107
|
+
it('extracts from a buffer', async () => {
|
|
108
|
+
await extractor.extract(await format.create([{ name: 'file.txt', data: 'content' }]), destination);
|
|
109
|
+
expect(await fs.promises.readFile(path.join(destination, 'file.txt'), 'utf8')).to.equal('content');
|
|
110
|
+
});
|
|
111
|
+
it('reads the selected files without extracting', async () => {
|
|
112
|
+
const archive = await format.create([
|
|
113
|
+
{ name: 'extension/package.json', data: '{"name":"test"}' },
|
|
114
|
+
{ name: 'extension/README.md', data: 'readme' }
|
|
115
|
+
]);
|
|
116
|
+
const files = await extractor.readFiles(archive, { filter: entryPath => entryPath === 'extension/package.json' });
|
|
117
|
+
expect(files.map(file => [file.path, file.data.toString('utf8')])).to.deep.equal([['extension/package.json', '{"name":"test"}']]);
|
|
118
|
+
expect(fs.existsSync(destination)).to.be.false;
|
|
119
|
+
});
|
|
120
|
+
(isWindows ? it.skip : it)('keeps permission bits but strips setuid, setgid and sticky bits', async () => {
|
|
121
|
+
const entries = await extractor.extract(await format.create([
|
|
122
|
+
{ name: 'run.sh', mode: 0o755, data: '#!/bin/sh' },
|
|
123
|
+
{ name: 'setuid', mode: 0o7755, data: 'evil' }
|
|
124
|
+
]), destination);
|
|
125
|
+
expect(entries.map(entry => entry.mode)).to.deep.equal([0o755, 0o755]);
|
|
126
|
+
expect((await fs.promises.stat(path.join(destination, 'run.sh'))).mode & 0o7777).to.equal(0o755 & ~process.umask());
|
|
127
|
+
expect((await fs.promises.stat(path.join(destination, 'setuid'))).mode & 0o7000).to.equal(0);
|
|
128
|
+
});
|
|
129
|
+
it('rejects an entry that leaves the destination', async () => {
|
|
130
|
+
const archive = await format.create([{ name: '../outside/evil.txt', data: 'evil' }]);
|
|
131
|
+
await expectRejection(extractor.extract(archive, destination), /invalid relative path|leaves the extraction directory/);
|
|
132
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
133
|
+
});
|
|
134
|
+
it('rejects an entry with an absolute path', async () => {
|
|
135
|
+
const target = path.join(outside, 'evil.txt').split(path.sep).join('/');
|
|
136
|
+
await expectRejection(extractor.extract(await format.create([{ name: target, data: 'evil' }]), destination), /absolute path/);
|
|
137
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
138
|
+
});
|
|
139
|
+
it('does not write through a symlinked directory in the destination', async () => {
|
|
140
|
+
await fs.promises.mkdir(destination);
|
|
141
|
+
await fs.promises.symlink(outside, path.join(destination, 'link'), 'junction');
|
|
142
|
+
await expectRejection(extractor.extract(await format.create([{ name: 'link/evil.txt', data: 'evil' }]), destination), /leaves the extraction directory/);
|
|
143
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
144
|
+
});
|
|
145
|
+
it('does not create directories through a symlinked directory in the destination', async () => {
|
|
146
|
+
await fs.promises.mkdir(destination);
|
|
147
|
+
await fs.promises.symlink(outside, path.join(destination, 'link'), 'junction');
|
|
148
|
+
await expectRejection(extractor.extract(await format.create([{ name: 'link/new-directory/evil.txt', data: 'evil' }]), destination), /leaves the extraction directory/);
|
|
149
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
150
|
+
});
|
|
151
|
+
it('does not write through a symlinked file in the destination', async function () {
|
|
152
|
+
const target = path.join(outside, 'target.txt');
|
|
153
|
+
await fs.promises.writeFile(target, 'original');
|
|
154
|
+
await fs.promises.mkdir(destination);
|
|
155
|
+
if (!await createFileLink(target, path.join(destination, 'file.txt'))) {
|
|
156
|
+
this.skip();
|
|
157
|
+
}
|
|
158
|
+
await expectRejection(extractor.extract(await format.create([{ name: 'file.txt', data: 'evil' }]), destination), /written through a link/);
|
|
159
|
+
expect(await fs.promises.readFile(target, 'utf8')).to.equal('original');
|
|
160
|
+
});
|
|
161
|
+
it('does not write a file whose existing target cannot be inspected', async () => {
|
|
162
|
+
await fs.promises.mkdir(destination);
|
|
163
|
+
const target = path.join(await fs.promises.realpath(destination), 'file.txt');
|
|
164
|
+
await fs.promises.writeFile(target, 'original');
|
|
165
|
+
const lstat = sinon.stub(fs.promises, 'lstat').callThrough();
|
|
166
|
+
lstat.withArgs(target).rejects(Object.assign(new Error('EACCES: permission denied'), { code: 'EACCES' }));
|
|
167
|
+
try {
|
|
168
|
+
await expectRejection(extractor.extract(await format.create([{ name: 'file.txt', data: 'evil' }]), destination), /EACCES/);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
lstat.restore();
|
|
172
|
+
}
|
|
173
|
+
expect(await fs.promises.readFile(target, 'utf8')).to.equal('original');
|
|
174
|
+
});
|
|
175
|
+
it('accepts names that start with two dots', async () => {
|
|
176
|
+
await extractor.extract(await format.create([
|
|
177
|
+
{ name: '..config/settings.json', data: '{}' },
|
|
178
|
+
{ name: '..hidden', data: 'hidden' }
|
|
179
|
+
]), destination);
|
|
180
|
+
expect(await listFiles(destination)).to.deep.equal(['..config', '..config/settings.json', '..hidden']);
|
|
181
|
+
});
|
|
182
|
+
it('creates parent directories that have no entry of their own', async () => {
|
|
183
|
+
const entries = await extractor.extract(await format.create([{ name: 'a/b/c.txt', data: 'content' }]), destination);
|
|
184
|
+
expect(entries.map(entry => entry.path)).to.deep.equal(['a/b/c.txt']);
|
|
185
|
+
expect(await fs.promises.readFile(path.join(destination, 'a', 'b', 'c.txt'), 'utf8')).to.equal('content');
|
|
186
|
+
});
|
|
187
|
+
it('overwrites existing files in the destination', async () => {
|
|
188
|
+
await fs.promises.mkdir(destination);
|
|
189
|
+
await fs.promises.writeFile(path.join(destination, 'file.txt'), 'old content that is longer');
|
|
190
|
+
await extractor.extract(await format.create([{ name: 'file.txt', data: 'new' }]), destination);
|
|
191
|
+
expect(await fs.promises.readFile(path.join(destination, 'file.txt'), 'utf8')).to.equal('new');
|
|
192
|
+
});
|
|
193
|
+
it('extracts long entry names', async () => {
|
|
194
|
+
const longName = ['a'.repeat(80), 'b'.repeat(80), 'c'.repeat(80), 'file.txt'].join('/');
|
|
195
|
+
await extractor.extract(await format.create([{ name: longName, data: 'long' }]), destination);
|
|
196
|
+
expect(await fs.promises.readFile(path.join(destination, ...longName.split('/')), 'utf8')).to.equal('long');
|
|
197
|
+
});
|
|
198
|
+
it('extracts a large file', async () => {
|
|
199
|
+
const data = randomBytes(3 * 1024 * 1024).toString('base64');
|
|
200
|
+
await extractor.extract(await format.create([{ name: 'large.txt', data }]), destination);
|
|
201
|
+
expect(await fs.promises.readFile(path.join(destination, 'large.txt'), 'utf8')).to.equal(data);
|
|
202
|
+
});
|
|
203
|
+
it('rejects a truncated archive', async () => {
|
|
204
|
+
const archive = await format.create([{ name: 'file.txt', data: randomBytes(64 * 1024).toString('base64') }]);
|
|
205
|
+
await expectRejection(extractor.extract(archive.subarray(0, archive.length / 2), destination), /end of (central directory|data|file)/i);
|
|
206
|
+
});
|
|
207
|
+
it('extracts an empty archive', async () => {
|
|
208
|
+
const entries = await extractor.extract(await format.create([]), destination, { format: format.name });
|
|
209
|
+
expect(entries).to.be.empty;
|
|
210
|
+
expect(await listFiles(destination)).to.be.empty;
|
|
211
|
+
});
|
|
212
|
+
(process.platform === 'linux' ? it : it.skip)('closes the archive file after a failed extraction', async () => {
|
|
213
|
+
const archive = await writeArchive(`archive.${format.name}`, await format.create([
|
|
214
|
+
{ name: 'file.txt', data: 'content' },
|
|
215
|
+
{ name: '../outside/evil.txt', data: 'evil' }
|
|
216
|
+
]));
|
|
217
|
+
const openBefore = (await fs.promises.readdir('/proc/self/fd')).length;
|
|
218
|
+
await expectRejection(extractor.extract(archive, destination), /invalid relative path|leaves the extraction directory/);
|
|
219
|
+
expect((await fs.promises.readdir('/proc/self/fd')).length).to.equal(openBefore);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
describe('zip entries', () => {
|
|
224
|
+
(isWindows ? it.skip : it)('uses default permissions for entries without a Unix mode', async () => {
|
|
225
|
+
const entries = await extractor.extract(createTestZip([{ name: 'file.txt', mode: 0, data: 'content' }]), destination);
|
|
226
|
+
expect(entries.map(entry => entry.mode)).to.deep.equal([undefined]);
|
|
227
|
+
expect((await fs.promises.stat(path.join(destination, 'file.txt'))).mode & 0o777).to.equal(0o666 & ~process.umask());
|
|
228
|
+
});
|
|
229
|
+
it('accepts backslashes as separators', async () => {
|
|
230
|
+
await extractor.extract(createTestZip([{ name: 'dir\\file.txt', data: 'content' }]), destination);
|
|
231
|
+
expect(await listFiles(destination)).to.deep.equal(['dir', 'dir/file.txt']);
|
|
232
|
+
});
|
|
233
|
+
it('rejects an entry that leaves the destination with backslashes', async () => {
|
|
234
|
+
await expectRejection(extractor.extract(createTestZip([{ name: '..\\outside\\evil.txt', data: 'evil' }]), destination), /invalid relative path|leaves the extraction directory/);
|
|
235
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
describe('zip links', () => {
|
|
239
|
+
it('skips a symlink entry', async () => {
|
|
240
|
+
const entries = await extractor.extract(createTestZip([
|
|
241
|
+
{ name: 'link', mode: 0o120777, data: outside },
|
|
242
|
+
{ name: 'file.txt', data: 'content' }
|
|
243
|
+
]), destination);
|
|
244
|
+
expect(entries.map(entry => entry.path)).to.deep.equal(['file.txt']);
|
|
245
|
+
expect(await listFiles(destination)).to.deep.equal(['file.txt']);
|
|
246
|
+
expect(warnings.join()).to.contain('link');
|
|
247
|
+
});
|
|
248
|
+
it('keeps a file inside the destination when it follows a symlink entry of the same name', async () => {
|
|
249
|
+
await extractor.extract(createTestZip([
|
|
250
|
+
{ name: 'link', mode: 0o120777, data: outside },
|
|
251
|
+
{ name: 'link/evil.txt', data: 'evil' }
|
|
252
|
+
]), destination);
|
|
253
|
+
expect(await listFiles(destination)).to.deep.equal(['link', 'link/evil.txt']);
|
|
254
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('tar links', () => {
|
|
258
|
+
it('skips a chain of symlink entries', async () => {
|
|
259
|
+
await extractor.extract(await createTestTar([
|
|
260
|
+
{ name: 'a', type: 'symlink', linkname: '..' },
|
|
261
|
+
{ name: 'a/b', type: 'symlink', linkname: '../outside' },
|
|
262
|
+
{ name: 'a/b/evil.txt', data: 'evil' }
|
|
263
|
+
]), destination);
|
|
264
|
+
expect(await listFiles(destination)).to.deep.equal(['a', 'a/b', 'a/b/evil.txt']);
|
|
265
|
+
expect(await listFiles(outside)).to.be.empty;
|
|
266
|
+
});
|
|
267
|
+
it('skips a hardlink entry', async () => {
|
|
268
|
+
const target = path.join(outside, 'secret.txt');
|
|
269
|
+
await fs.promises.writeFile(target, 'secret');
|
|
270
|
+
const entries = await extractor.extract(await createTestTar([
|
|
271
|
+
{ name: 'secret.txt', type: 'link', linkname: target },
|
|
272
|
+
{ name: 'file.txt', data: 'content' }
|
|
273
|
+
]), destination);
|
|
274
|
+
expect(entries.map(entry => entry.path)).to.deep.equal(['file.txt']);
|
|
275
|
+
expect(await listFiles(destination)).to.deep.equal(['file.txt']);
|
|
276
|
+
expect(warnings.join()).to.contain('secret.txt');
|
|
277
|
+
});
|
|
278
|
+
it('skips special entries', async () => {
|
|
279
|
+
const entries = await extractor.extract(await createTestTar([
|
|
280
|
+
{ name: 'pipe', type: 'fifo' },
|
|
281
|
+
{ name: 'file.txt', data: 'content' }
|
|
282
|
+
]), destination);
|
|
283
|
+
expect(entries.map(entry => entry.path)).to.deep.equal(['file.txt']);
|
|
284
|
+
});
|
|
285
|
+
it('reports links that are skipped while reading files', async () => {
|
|
286
|
+
const files = await extractor.readFiles(await createTestTar([
|
|
287
|
+
{ name: 'link', type: 'symlink', linkname: '/etc/passwd' },
|
|
288
|
+
{ name: 'file.txt', data: 'content' }
|
|
289
|
+
]));
|
|
290
|
+
expect(files.map(file => file.path)).to.deep.equal(['file.txt']);
|
|
291
|
+
expect(warnings.join()).to.contain('link');
|
|
292
|
+
});
|
|
293
|
+
it('reports skipped entries on the console without a logger', async () => {
|
|
294
|
+
const warn = sinon.stub(console, 'warn');
|
|
295
|
+
try {
|
|
296
|
+
await new ArchiveExtractorImpl().extract(await createTestTar([
|
|
297
|
+
{ name: 'link', type: 'symlink', linkname: '/etc/passwd' },
|
|
298
|
+
{ name: 'file.txt', data: 'content' }
|
|
299
|
+
]), destination);
|
|
300
|
+
expect(warn.calledOnceWith('Skipped 1 link or special entries of archive: link')).to.be.true;
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
warn.restore();
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
it('rejects an unsupported format', async () => {
|
|
308
|
+
await expectRejection(extractor.extract(Buffer.from('not an archive'), destination), /Unsupported archive format/);
|
|
309
|
+
});
|
|
310
|
+
it('rejects a header that only resembles a zip signature', async () => {
|
|
311
|
+
await expectRejection(extractor.extract(Buffer.from('PK\x03\x06 not an archive', 'latin1'), destination), /Unsupported archive format/);
|
|
312
|
+
});
|
|
313
|
+
it('uses the given format instead of detecting it', async () => {
|
|
314
|
+
await expectRejection(extractor.extract(createTestZip([{ name: 'file.txt' }]), destination, { format: 'tgz' }), /incorrect header check/);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
//# sourceMappingURL=archive-extractor.spec.js.map
|