dsh-remote 0.8.46 → 0.8.47
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/LICENSE +21 -21
- package/README.en.md +361 -361
- package/README.md +368 -368
- package/cordis.patch.yml +9 -9
- package/lib/binding.js +172 -172
- package/lib/client.js +3637 -3637
- package/lib/credential.js +177 -177
- package/lib/deploy-tasks.js +142 -142
- package/lib/errors.js +87 -87
- package/lib/file-reference.js +457 -457
- package/lib/forwards.js +258 -258
- package/lib/hostkey.js +108 -108
- package/lib/http-transport.js +196 -196
- package/lib/ignore.js +156 -156
- package/lib/index.js +3771 -3747
- package/lib/openssh.js +838 -838
- package/lib/paths.js +225 -225
- package/lib/pool.js +757 -757
- package/lib/registry.js +95 -95
- package/lib/remote-fs.js +148 -143
- package/lib/routes-fs.js +233 -233
- package/lib/search.js +230 -230
- package/lib/sftp-surface.js +76 -76
- package/lib/sshconfig.js +454 -454
- package/lib/sync.js +275 -275
- package/lib/tasks.js +95 -95
- package/lib/telemetry.js +213 -213
- package/lib/update.js +472 -472
- package/lib/web-attach.js +850 -850
- package/lib/web-deploy-skill.js +205 -205
- package/lib/web-deploy.js +694 -694
- package/node_modules/asn1/Jenkinsfile +65 -0
- package/node_modules/asn1/LICENSE +19 -0
- package/node_modules/asn1/README.md +50 -0
- package/node_modules/asn1/lib/ber/errors.js +13 -0
- package/node_modules/asn1/lib/ber/index.js +27 -0
- package/node_modules/asn1/lib/ber/reader.js +262 -0
- package/node_modules/asn1/lib/ber/types.js +36 -0
- package/node_modules/asn1/lib/ber/writer.js +317 -0
- package/node_modules/asn1/lib/index.js +20 -0
- package/node_modules/asn1/package.json +31 -0
- package/node_modules/bcrypt-pbkdf/CONTRIBUTING.md +13 -0
- package/node_modules/bcrypt-pbkdf/LICENSE +66 -0
- package/node_modules/bcrypt-pbkdf/README.md +45 -0
- package/node_modules/bcrypt-pbkdf/index.js +556 -0
- package/node_modules/bcrypt-pbkdf/package.json +15 -0
- package/node_modules/buildcheck/.eslintrc.js +5 -0
- package/node_modules/buildcheck/.github/workflows/ci.yml +88 -0
- package/node_modules/buildcheck/.github/workflows/lint.yml +27 -0
- package/node_modules/buildcheck/.npmignore +3 -0
- package/node_modules/buildcheck/LICENSE +19 -0
- package/node_modules/buildcheck/README.md +106 -0
- package/node_modules/buildcheck/deps/Find-VisualStudio.cs +250 -0
- package/node_modules/buildcheck/lib/findvs.js +361 -0
- package/node_modules/buildcheck/lib/index.js +738 -0
- package/node_modules/buildcheck/package.json +36 -0
- package/node_modules/buildcheck/test/test.js +8 -0
- package/node_modules/cpu-features/.eslintrc.js +5 -0
- package/node_modules/cpu-features/.github/workflows/ci.yml +74 -0
- package/node_modules/cpu-features/.github/workflows/lint.yml +27 -0
- package/node_modules/cpu-features/LICENSE +19 -0
- package/node_modules/cpu-features/README.md +59 -0
- package/node_modules/cpu-features/binding.gyp +16 -0
- package/node_modules/cpu-features/buildcheck.js +32 -0
- package/node_modules/cpu-features/deps/cpu_features/.clang-format +4 -0
- package/node_modules/cpu-features/deps/cpu_features/.dockerignore +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/Dockerfile +5 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/aarch64_linux_cmake.yml +30 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_freebsd_cmake.yml +22 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_linux_bazel.yml +26 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_linux_cmake.yml +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_macos_cmake.yml +43 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/amd64_windows_cmake.yml +25 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/arm_linux_cmake.yml +31 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/clang_format.yml +24 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/mips_linux_cmake.yml +30 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/power_linux_cmake.yml +29 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/riscv_linux_cmake.yml +28 -0
- package/node_modules/cpu-features/deps/cpu_features/.github/workflows/s390x_linux_cmake.yml +27 -0
- package/node_modules/cpu-features/deps/cpu_features/.grenrc.yml +21 -0
- package/node_modules/cpu-features/deps/cpu_features/BUILD.bazel +329 -0
- package/node_modules/cpu-features/deps/cpu_features/CMakeLists.txt +261 -0
- package/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md +23 -0
- package/node_modules/cpu-features/deps/cpu_features/LICENSE +230 -0
- package/node_modules/cpu-features/deps/cpu_features/README.md +272 -0
- package/node_modules/cpu-features/deps/cpu_features/WORKSPACE +19 -0
- package/node_modules/cpu-features/deps/cpu_features/bazel/ci/README.md +5 -0
- package/node_modules/cpu-features/deps/cpu_features/bazel/platforms.bzl +11 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in +3 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in +3 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/README.md +30 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/Makefile +252 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/README.md +40 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/docker.dot +64 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/docker.svg +312 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/doc/generate_image.sh +7 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/docker/amd64/Dockerfile +48 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/docker/toolchain/Dockerfile +34 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/sample/CMakeLists.txt +22 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/sample/main.cpp +11 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/ci/vagrant/freebsd/Vagrantfile +107 -0
- package/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in +15 -0
- package/node_modules/cpu-features/deps/cpu_features/cpu_features.gyp +105 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h +54 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h +384 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h +259 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h +121 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h +74 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h +149 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_riscv.h +72 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_s390x.h +108 -0
- package/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h +288 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h +40 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h +37 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h +39 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h +240 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h +49 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h +110 -0
- package/node_modules/cpu-features/deps/cpu_features/include/internal/windows_utils.h +70 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt +60 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md +4 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c +205 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h +320 -0
- package/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c +12 -0
- package/node_modules/cpu-features/deps/cpu_features/patches/0001-Add-Apple-Silicon-Support.patch +456 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/generate_badges.d +165 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/make_release.sh +75 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh +490 -0
- package/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh +79 -0
- package/node_modules/cpu-features/deps/cpu_features/src/copy.inl +19 -0
- package/node_modules/cpu-features/deps/cpu_features/src/define_introspection.inl +86 -0
- package/node_modules/cpu-features/deps/cpu_features/src/define_introspection_and_hwcaps.inl +26 -0
- package/node_modules/cpu-features/deps/cpu_features/src/equals.inl +22 -0
- package/node_modules/cpu-features/deps/cpu_features/src/filesystem.c +62 -0
- package/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c +169 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64__base_implementation.inl +88 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_linux_or_android.c +79 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_macos_or_iphone.c +82 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_aarch64_windows.c +138 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_arm_linux_or_android.c +212 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_mips_linux_or_android.c +93 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_ppc_linux.c +163 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_riscv_linux.c +111 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_s390x_linux.c +120 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86__base_implementation.inl +2055 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_freebsd.c +68 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_linux_or_android.c +58 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_macos.c +57 -0
- package/node_modules/cpu-features/deps/cpu_features/src/impl_x86_windows.c +58 -0
- package/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c +132 -0
- package/node_modules/cpu-features/deps/cpu_features/src/string_view.c +192 -0
- package/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c +461 -0
- package/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt +114 -0
- package/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc +53 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc +396 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc +384 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc +176 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc +131 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_riscv_test.cc +180 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_s390x_test.cc +82 -0
- package/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc +1729 -0
- package/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc +103 -0
- package/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h +61 -0
- package/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc +52 -0
- package/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h +31 -0
- package/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc +132 -0
- package/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc +202 -0
- package/node_modules/cpu-features/lib/index.js +5 -0
- package/node_modules/cpu-features/package.json +40 -0
- package/node_modules/cpu-features/src/binding.cc +151 -0
- package/node_modules/cpu-features/test/test.js +12 -0
- package/node_modules/nan/.github/workflows/ci.yml +46 -0
- package/node_modules/nan/.pre-commit-config.yaml +8 -0
- package/node_modules/nan/CHANGELOG.md +605 -0
- package/node_modules/nan/CMakeLists.txt +138 -0
- package/node_modules/nan/LICENSE.md +9 -0
- package/node_modules/nan/README.md +457 -0
- package/node_modules/nan/doc/asyncworker.md +146 -0
- package/node_modules/nan/doc/buffers.md +54 -0
- package/node_modules/nan/doc/callback.md +76 -0
- package/node_modules/nan/doc/converters.md +41 -0
- package/node_modules/nan/doc/errors.md +226 -0
- package/node_modules/nan/doc/json.md +62 -0
- package/node_modules/nan/doc/maybe_types.md +583 -0
- package/node_modules/nan/doc/methods.md +689 -0
- package/node_modules/nan/doc/new.md +147 -0
- package/node_modules/nan/doc/node_misc.md +123 -0
- package/node_modules/nan/doc/object_wrappers.md +263 -0
- package/node_modules/nan/doc/persistent.md +296 -0
- package/node_modules/nan/doc/scopes.md +73 -0
- package/node_modules/nan/doc/script.md +58 -0
- package/node_modules/nan/doc/string_bytes.md +81 -0
- package/node_modules/nan/doc/v8_internals.md +211 -0
- package/node_modules/nan/doc/v8_misc.md +85 -0
- package/node_modules/nan/include_dirs.js +1 -0
- package/node_modules/nan/nan.h +3202 -0
- package/node_modules/nan/nan_callbacks.h +141 -0
- package/node_modules/nan/nan_callbacks_12_inl.h +730 -0
- package/node_modules/nan/nan_callbacks_pre_12_inl.h +528 -0
- package/node_modules/nan/nan_converters.h +72 -0
- package/node_modules/nan/nan_converters_43_inl.h +68 -0
- package/node_modules/nan/nan_converters_pre_43_inl.h +42 -0
- package/node_modules/nan/nan_define_own_property_helper.h +29 -0
- package/node_modules/nan/nan_implementation_12_inl.h +446 -0
- package/node_modules/nan/nan_implementation_pre_12_inl.h +263 -0
- package/node_modules/nan/nan_json.h +166 -0
- package/node_modules/nan/nan_maybe_43_inl.h +360 -0
- package/node_modules/nan/nan_maybe_pre_43_inl.h +268 -0
- package/node_modules/nan/nan_new.h +340 -0
- package/node_modules/nan/nan_object_wrap.h +156 -0
- package/node_modules/nan/nan_persistent_12_inl.h +132 -0
- package/node_modules/nan/nan_persistent_pre_12_inl.h +242 -0
- package/node_modules/nan/nan_private.h +73 -0
- package/node_modules/nan/nan_scriptorigin.h +97 -0
- package/node_modules/nan/nan_string_bytes.h +305 -0
- package/node_modules/nan/nan_typedarray_contents.h +96 -0
- package/node_modules/nan/nan_weak.h +453 -0
- package/node_modules/nan/package.json +38 -0
- package/node_modules/nan/tools/1to2.js +412 -0
- package/node_modules/nan/tools/README.md +14 -0
- package/node_modules/nan/tools/package.json +19 -0
- package/node_modules/safer-buffer/LICENSE +21 -0
- package/node_modules/safer-buffer/Porting-Buffer.md +268 -0
- package/node_modules/safer-buffer/Readme.md +156 -0
- package/node_modules/safer-buffer/dangerous.js +58 -0
- package/node_modules/safer-buffer/package.json +34 -0
- package/node_modules/safer-buffer/safer.js +77 -0
- package/node_modules/safer-buffer/tests.js +406 -0
- package/node_modules/ssh2/.eslintignore +4 -0
- package/node_modules/ssh2/.eslintrc.js +5 -0
- package/node_modules/ssh2/.github/workflows/ci.yml +110 -0
- package/node_modules/ssh2/.github/workflows/lint.yml +27 -0
- package/node_modules/ssh2/LICENSE +19 -0
- package/node_modules/ssh2/README.md +1529 -0
- package/node_modules/ssh2/SFTP.md +413 -0
- package/node_modules/ssh2/examples/server-chat.js +238 -0
- package/node_modules/ssh2/examples/sftp-server-download-only.js +134 -0
- package/node_modules/ssh2/install.js +27 -0
- package/node_modules/ssh2/lib/Channel.js +295 -0
- package/node_modules/ssh2/lib/agent.js +1123 -0
- package/node_modules/ssh2/lib/client.js +2176 -0
- package/node_modules/ssh2/lib/http-agents.js +84 -0
- package/node_modules/ssh2/lib/index.js +44 -0
- package/node_modules/ssh2/lib/keygen.js +582 -0
- package/node_modules/ssh2/lib/protocol/Protocol.js +2136 -0
- package/node_modules/ssh2/lib/protocol/SFTP.js +4052 -0
- package/node_modules/ssh2/lib/protocol/constants.js +356 -0
- package/node_modules/ssh2/lib/protocol/crypto/binding.gyp +23 -0
- package/node_modules/ssh2/lib/protocol/crypto/poly1305.js +43 -0
- package/node_modules/ssh2/lib/protocol/crypto/src/binding.cc +2300 -0
- package/node_modules/ssh2/lib/protocol/crypto.js +1602 -0
- package/node_modules/ssh2/lib/protocol/handlers.js +16 -0
- package/node_modules/ssh2/lib/protocol/handlers.misc.js +1285 -0
- package/node_modules/ssh2/lib/protocol/kex.js +1908 -0
- package/node_modules/ssh2/lib/protocol/keyParser.js +1484 -0
- package/node_modules/ssh2/lib/protocol/node-fs-compat.js +115 -0
- package/node_modules/ssh2/lib/protocol/utils.js +356 -0
- package/node_modules/ssh2/lib/protocol/zlib.js +255 -0
- package/node_modules/ssh2/lib/server.js +1380 -0
- package/node_modules/ssh2/lib/utils.js +336 -0
- package/node_modules/ssh2/package.json +49 -0
- package/node_modules/ssh2/test/common.js +316 -0
- package/node_modules/ssh2/test/fixtures/bad_rsa_private_key +26 -0
- package/node_modules/ssh2/test/fixtures/https_cert.pem +33 -0
- package/node_modules/ssh2/test/fixtures/https_key.pem +52 -0
- package/node_modules/ssh2/test/fixtures/id_dsa +12 -0
- package/node_modules/ssh2/test/fixtures/id_ecdsa +5 -0
- package/node_modules/ssh2/test/fixtures/id_rsa +15 -0
- package/node_modules/ssh2/test/fixtures/id_rsa.ppk +26 -0
- package/node_modules/ssh2/test/fixtures/id_rsa_enc +30 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa +21 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc +22 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm +23 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa +9 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc +28 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm +29 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa +12 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc +15 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa +5 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc +30 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 +54 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub +1 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result +6 -0
- package/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result +6 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc +17 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa +26 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc +18 -0
- package/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub +9 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub +10 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub +11 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub +11 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub +8 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub +13 -0
- package/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result +7 -0
- package/node_modules/ssh2/test/fixtures/openssh_new_rsa +27 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_dsa_key +12 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_ecdsa_key +5 -0
- package/node_modules/ssh2/test/fixtures/ssh_host_rsa_key +15 -0
- package/node_modules/ssh2/test/test-exec.js +578 -0
- package/node_modules/ssh2/test/test-integration-openssh.js +486 -0
- package/node_modules/ssh2/test/test-keygen.js +60 -0
- package/node_modules/ssh2/test/test-misc-client-server.js +1460 -0
- package/node_modules/ssh2/test/test-openssh.js +261 -0
- package/node_modules/ssh2/test/test-protocol-crypto.js +631 -0
- package/node_modules/ssh2/test/test-protocol-keyparser.js +177 -0
- package/node_modules/ssh2/test/test-server-hostkeys.js +138 -0
- package/node_modules/ssh2/test/test-sftp.js +842 -0
- package/node_modules/ssh2/test/test-shell.js +109 -0
- package/node_modules/ssh2/test/test-userauth-agent-openssh.js +110 -0
- package/node_modules/ssh2/test/test-userauth-agent.js +171 -0
- package/node_modules/ssh2/test/test-userauth.js +611 -0
- package/node_modules/ssh2/test/test-worker-imports.js +25 -0
- package/node_modules/ssh2/test/test.js +20 -0
- package/node_modules/ssh2/util/build_pagent.bat +2 -0
- package/node_modules/ssh2/util/pagent.c +88 -0
- package/node_modules/ssh2/util/pagent.exe +0 -0
- package/node_modules/tweetnacl/.npmignore +4 -0
- package/node_modules/tweetnacl/AUTHORS.md +28 -0
- package/node_modules/tweetnacl/CHANGELOG.md +221 -0
- package/node_modules/tweetnacl/LICENSE +24 -0
- package/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md +20 -0
- package/node_modules/tweetnacl/README.md +459 -0
- package/node_modules/tweetnacl/nacl-fast.js +2388 -0
- package/node_modules/tweetnacl/nacl-fast.min.js +2 -0
- package/node_modules/tweetnacl/nacl.d.ts +98 -0
- package/node_modules/tweetnacl/nacl.js +1175 -0
- package/node_modules/tweetnacl/nacl.min.js +1 -0
- package/node_modules/tweetnacl/package.json +58 -0
- package/package.json +95 -89
package/lib/registry.js
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
// Machine-registry pure logic for dsh-remote.
|
|
2
|
-
//
|
|
3
|
-
// Issue #13: a SAVED machine is only a standby connection — it must never
|
|
4
|
-
// silently become the "active remote context" of every session. The registry
|
|
5
|
-
// therefore keeps `currentId` as an EXPLICIT user choice:
|
|
6
|
-
// • loadMachines never falls back to the first saved machine,
|
|
7
|
-
// • a stale currentId (machine deleted meanwhile) resolves to null,
|
|
8
|
-
// • add/update never auto-activate; only an explicit "set current" does,
|
|
9
|
-
// • deleting the current machine leaves NO current (no auto-promotion).
|
|
10
|
-
// Keeping this logic in one module makes the guarantee unit-testable and
|
|
11
|
-
// shared between the HTTP routes and the tools (rw_connect).
|
|
12
|
-
|
|
13
|
-
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
14
|
-
import path from 'node:path'
|
|
15
|
-
|
|
16
|
-
/** Load { list, currentId, explicitNone } from the registry file. */
|
|
17
|
-
export function loadMachines(file) {
|
|
18
|
-
try {
|
|
19
|
-
const j = JSON.parse(readFileSync(file, 'utf8'))
|
|
20
|
-
if (Array.isArray(j.list)) {
|
|
21
|
-
const list = j.list
|
|
22
|
-
// Explicit choice only — no fallback to the first machine, no activation
|
|
23
|
-
// of a stale/deleted id (issue #13).
|
|
24
|
-
const currentId = j.currentId && list.some((m) => m.id === j.currentId) ? j.currentId : null
|
|
25
|
-
// A persisted `currentId: null` is a deliberate "active remote = none"
|
|
26
|
-
// (the user cleared the current machine). It must survive restarts so a
|
|
27
|
-
// config-level default host cannot silently reactivate a context the user
|
|
28
|
-
// explicitly turned off. `explicitNone` is true when the file carries an
|
|
29
|
-
// explicit null (vs. a fresh file where currentId is simply absent).
|
|
30
|
-
const explicitNone = Object.prototype.hasOwnProperty.call(j, 'currentId') && j.currentId == null
|
|
31
|
-
return { list, currentId, explicitNone }
|
|
32
|
-
}
|
|
33
|
-
} catch {}
|
|
34
|
-
return { list: [], currentId: null, explicitNone: false }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Persist { list, currentId }. `currentId` may be null → active remote = none.
|
|
38
|
-
* Pass `keepCurrentKey: false` (add/update a machine without touching the
|
|
39
|
-
* current selection) to PRESERVE whatever `currentId` the file already holds
|
|
40
|
-
* — so merely saving a machine never flips a fresh registry into "explicit
|
|
41
|
-
* none", nor clears an explicit choice. When no previous file exists the
|
|
42
|
-
* `currentId` key is omitted entirely (fresh registry = "no choice yet"). */
|
|
43
|
-
export function saveMachines(file, list, currentId, keepCurrentKey = true) {
|
|
44
|
-
try { mkdirSync(path.dirname(file), { recursive: true }) } catch {}
|
|
45
|
-
let stored = currentId
|
|
46
|
-
let hasStored = keepCurrentKey
|
|
47
|
-
if (!keepCurrentKey) {
|
|
48
|
-
try {
|
|
49
|
-
const prev = JSON.parse(readFileSync(file, 'utf8'))
|
|
50
|
-
if (prev && Object.prototype.hasOwnProperty.call(prev, 'currentId')) {
|
|
51
|
-
stored = prev.currentId
|
|
52
|
-
hasStored = true
|
|
53
|
-
}
|
|
54
|
-
} catch { /* no previous file → omit the key */ }
|
|
55
|
-
}
|
|
56
|
-
const payload = { list }
|
|
57
|
-
if (hasStored) payload.currentId = stored
|
|
58
|
-
writeFileSync(file, JSON.stringify(payload, null, 2))
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Strip secrets before sending a machine to the client. */
|
|
62
|
-
export function sanitizeMachine(m) {
|
|
63
|
-
if (!m) return m
|
|
64
|
-
const { password, proxy, ...rest } = m
|
|
65
|
-
const out = { ...rest, passwordSet: !!(m.password && m.password.length) }
|
|
66
|
-
if (proxy) out.proxy = { ...proxy, password: proxy.password ? '' : undefined, passwordSet: !!(proxy.password && proxy.password.length) }
|
|
67
|
-
return out
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Apply a machine's fields onto the live config object (pool + tools read it). */
|
|
71
|
-
export function applyMachine(config, m) {
|
|
72
|
-
if (!m) return
|
|
73
|
-
config.host = m.host
|
|
74
|
-
config.port = Number(m.port) || 22
|
|
75
|
-
config.username = m.username || ''
|
|
76
|
-
config.password = m.password || ''
|
|
77
|
-
config.privateKeyPath = m.privateKeyPath || ''
|
|
78
|
-
config.passphrase = m.passphrase || ''
|
|
79
|
-
config.workspace = m.workspace || (config.workspace || '')
|
|
80
|
-
if (m.hostKeyMode) config.hostKeyMode = m.hostKeyMode
|
|
81
|
-
if (typeof m.useAgent === 'boolean') config.useAgent = m.useAgent
|
|
82
|
-
if (typeof m.keyboardInteractive === 'boolean') config.keyboardInteractive = m.keyboardInteractive
|
|
83
|
-
// Issue #51: the transport backend is PER MACHINE. An enterprise box that only
|
|
84
|
-
// accepts Kerberos must go through the system OpenSSH backend while every
|
|
85
|
-
// other machine can stay on the native one, so this cannot be a purely global
|
|
86
|
-
// default.
|
|
87
|
-
if (m.backend) config.backend = m.backend
|
|
88
|
-
if (typeof m.sshBinary === 'string') config.sshBinary = m.sshBinary
|
|
89
|
-
config.proxy = m.proxy && m.proxy.host ? m.proxy : undefined
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Mint a fresh machine id. */
|
|
93
|
-
export function machineId() {
|
|
94
|
-
return 'm-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 6)
|
|
95
|
-
}
|
|
1
|
+
// Machine-registry pure logic for dsh-remote.
|
|
2
|
+
//
|
|
3
|
+
// Issue #13: a SAVED machine is only a standby connection — it must never
|
|
4
|
+
// silently become the "active remote context" of every session. The registry
|
|
5
|
+
// therefore keeps `currentId` as an EXPLICIT user choice:
|
|
6
|
+
// • loadMachines never falls back to the first saved machine,
|
|
7
|
+
// • a stale currentId (machine deleted meanwhile) resolves to null,
|
|
8
|
+
// • add/update never auto-activate; only an explicit "set current" does,
|
|
9
|
+
// • deleting the current machine leaves NO current (no auto-promotion).
|
|
10
|
+
// Keeping this logic in one module makes the guarantee unit-testable and
|
|
11
|
+
// shared between the HTTP routes and the tools (rw_connect).
|
|
12
|
+
|
|
13
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
14
|
+
import path from 'node:path'
|
|
15
|
+
|
|
16
|
+
/** Load { list, currentId, explicitNone } from the registry file. */
|
|
17
|
+
export function loadMachines(file) {
|
|
18
|
+
try {
|
|
19
|
+
const j = JSON.parse(readFileSync(file, 'utf8'))
|
|
20
|
+
if (Array.isArray(j.list)) {
|
|
21
|
+
const list = j.list
|
|
22
|
+
// Explicit choice only — no fallback to the first machine, no activation
|
|
23
|
+
// of a stale/deleted id (issue #13).
|
|
24
|
+
const currentId = j.currentId && list.some((m) => m.id === j.currentId) ? j.currentId : null
|
|
25
|
+
// A persisted `currentId: null` is a deliberate "active remote = none"
|
|
26
|
+
// (the user cleared the current machine). It must survive restarts so a
|
|
27
|
+
// config-level default host cannot silently reactivate a context the user
|
|
28
|
+
// explicitly turned off. `explicitNone` is true when the file carries an
|
|
29
|
+
// explicit null (vs. a fresh file where currentId is simply absent).
|
|
30
|
+
const explicitNone = Object.prototype.hasOwnProperty.call(j, 'currentId') && j.currentId == null
|
|
31
|
+
return { list, currentId, explicitNone }
|
|
32
|
+
}
|
|
33
|
+
} catch {}
|
|
34
|
+
return { list: [], currentId: null, explicitNone: false }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Persist { list, currentId }. `currentId` may be null → active remote = none.
|
|
38
|
+
* Pass `keepCurrentKey: false` (add/update a machine without touching the
|
|
39
|
+
* current selection) to PRESERVE whatever `currentId` the file already holds
|
|
40
|
+
* — so merely saving a machine never flips a fresh registry into "explicit
|
|
41
|
+
* none", nor clears an explicit choice. When no previous file exists the
|
|
42
|
+
* `currentId` key is omitted entirely (fresh registry = "no choice yet"). */
|
|
43
|
+
export function saveMachines(file, list, currentId, keepCurrentKey = true) {
|
|
44
|
+
try { mkdirSync(path.dirname(file), { recursive: true }) } catch {}
|
|
45
|
+
let stored = currentId
|
|
46
|
+
let hasStored = keepCurrentKey
|
|
47
|
+
if (!keepCurrentKey) {
|
|
48
|
+
try {
|
|
49
|
+
const prev = JSON.parse(readFileSync(file, 'utf8'))
|
|
50
|
+
if (prev && Object.prototype.hasOwnProperty.call(prev, 'currentId')) {
|
|
51
|
+
stored = prev.currentId
|
|
52
|
+
hasStored = true
|
|
53
|
+
}
|
|
54
|
+
} catch { /* no previous file → omit the key */ }
|
|
55
|
+
}
|
|
56
|
+
const payload = { list }
|
|
57
|
+
if (hasStored) payload.currentId = stored
|
|
58
|
+
writeFileSync(file, JSON.stringify(payload, null, 2))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Strip secrets before sending a machine to the client. */
|
|
62
|
+
export function sanitizeMachine(m) {
|
|
63
|
+
if (!m) return m
|
|
64
|
+
const { password, proxy, ...rest } = m
|
|
65
|
+
const out = { ...rest, passwordSet: !!(m.password && m.password.length) }
|
|
66
|
+
if (proxy) out.proxy = { ...proxy, password: proxy.password ? '' : undefined, passwordSet: !!(proxy.password && proxy.password.length) }
|
|
67
|
+
return out
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Apply a machine's fields onto the live config object (pool + tools read it). */
|
|
71
|
+
export function applyMachine(config, m) {
|
|
72
|
+
if (!m) return
|
|
73
|
+
config.host = m.host
|
|
74
|
+
config.port = Number(m.port) || 22
|
|
75
|
+
config.username = m.username || ''
|
|
76
|
+
config.password = m.password || ''
|
|
77
|
+
config.privateKeyPath = m.privateKeyPath || ''
|
|
78
|
+
config.passphrase = m.passphrase || ''
|
|
79
|
+
config.workspace = m.workspace || (config.workspace || '')
|
|
80
|
+
if (m.hostKeyMode) config.hostKeyMode = m.hostKeyMode
|
|
81
|
+
if (typeof m.useAgent === 'boolean') config.useAgent = m.useAgent
|
|
82
|
+
if (typeof m.keyboardInteractive === 'boolean') config.keyboardInteractive = m.keyboardInteractive
|
|
83
|
+
// Issue #51: the transport backend is PER MACHINE. An enterprise box that only
|
|
84
|
+
// accepts Kerberos must go through the system OpenSSH backend while every
|
|
85
|
+
// other machine can stay on the native one, so this cannot be a purely global
|
|
86
|
+
// default.
|
|
87
|
+
if (m.backend) config.backend = m.backend
|
|
88
|
+
if (typeof m.sshBinary === 'string') config.sshBinary = m.sshBinary
|
|
89
|
+
config.proxy = m.proxy && m.proxy.host ? m.proxy : undefined
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Mint a fresh machine id. */
|
|
93
|
+
export function machineId() {
|
|
94
|
+
return 'm-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 6)
|
|
95
|
+
}
|
package/lib/remote-fs.js
CHANGED
|
@@ -1,143 +1,148 @@
|
|
|
1
|
-
// Shared remote SFTP helpers used by both rw_* tools and the sidebar HTTP routes.
|
|
2
|
-
import { joinRemotePath, normalizeRemotePath } from './paths.js'
|
|
3
|
-
|
|
4
|
-
/** Structured listing: name + type + size + mtime + mode (SFTP protocol-level). */
|
|
5
|
-
export async function listDirStructured(sftp, p) {
|
|
6
|
-
const target = normalizeRemotePath(p || '/')
|
|
7
|
-
let list
|
|
8
|
-
try {
|
|
9
|
-
list = await sftp.readdir(target)
|
|
10
|
-
} catch (err) {
|
|
11
|
-
const msg = String((err && err.message) || err)
|
|
12
|
-
if (/no such file|not found|does not exist|ENOENT/i.test(msg)) {
|
|
13
|
-
return { path: target, items: [], missing: true }
|
|
14
|
-
}
|
|
15
|
-
throw new Error('browse failed: ' + msg)
|
|
16
|
-
}
|
|
17
|
-
const items = []
|
|
18
|
-
const symIdx = []
|
|
19
|
-
for (const e of list) {
|
|
20
|
-
const name = String(e.filename)
|
|
21
|
-
if (name === '.' || name === '..' || !name) continue
|
|
22
|
-
const a = e.attrs || {}
|
|
23
|
-
let type
|
|
24
|
-
if (a.isSymbolicLink && a.isSymbolicLink()) {
|
|
25
|
-
type = 'symlink'
|
|
26
|
-
symIdx.push(items.length)
|
|
27
|
-
} else if (a.isDirectory && a.isDirectory()) {
|
|
28
|
-
type = 'dir'
|
|
29
|
-
} else {
|
|
30
|
-
type = 'file'
|
|
31
|
-
}
|
|
32
|
-
items.push({
|
|
33
|
-
type,
|
|
34
|
-
name,
|
|
35
|
-
size: typeof a.size === 'number' ? a.size : 0,
|
|
36
|
-
mtime: typeof a.mtime === 'number' ? a.mtime : 0,
|
|
37
|
-
mode: typeof a.mode === 'number' ? a.mode.toString(8) : '',
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
if (symIdx.length) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
1
|
+
// Shared remote SFTP helpers used by both rw_* tools and the sidebar HTTP routes.
|
|
2
|
+
import { joinRemotePath, normalizeRemotePath } from './paths.js'
|
|
3
|
+
|
|
4
|
+
/** Structured listing: name + type + size + mtime + mode (SFTP protocol-level). */
|
|
5
|
+
export async function listDirStructured(sftp, p) {
|
|
6
|
+
const target = normalizeRemotePath(p || '/')
|
|
7
|
+
let list
|
|
8
|
+
try {
|
|
9
|
+
list = await sftp.readdir(target)
|
|
10
|
+
} catch (err) {
|
|
11
|
+
const msg = String((err && err.message) || err)
|
|
12
|
+
if (/no such file|not found|does not exist|ENOENT/i.test(msg)) {
|
|
13
|
+
return { path: target, items: [], missing: true }
|
|
14
|
+
}
|
|
15
|
+
throw new Error('browse failed: ' + msg)
|
|
16
|
+
}
|
|
17
|
+
const items = []
|
|
18
|
+
const symIdx = []
|
|
19
|
+
for (const e of list) {
|
|
20
|
+
const name = String(e.filename)
|
|
21
|
+
if (name === '.' || name === '..' || !name) continue
|
|
22
|
+
const a = e.attrs || {}
|
|
23
|
+
let type
|
|
24
|
+
if (a.isSymbolicLink && a.isSymbolicLink()) {
|
|
25
|
+
type = 'symlink'
|
|
26
|
+
symIdx.push(items.length)
|
|
27
|
+
} else if (a.isDirectory && a.isDirectory()) {
|
|
28
|
+
type = 'dir'
|
|
29
|
+
} else {
|
|
30
|
+
type = 'file'
|
|
31
|
+
}
|
|
32
|
+
items.push({
|
|
33
|
+
type,
|
|
34
|
+
name,
|
|
35
|
+
size: typeof a.size === 'number' ? a.size : 0,
|
|
36
|
+
mtime: typeof a.mtime === 'number' ? a.mtime : 0,
|
|
37
|
+
mode: typeof a.mode === 'number' ? a.mode.toString(8) : '',
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
if (symIdx.length) {
|
|
41
|
+
// Resolve what each symlink POINTS TO. This must be stat (follows links),
|
|
42
|
+
// not lstat: lstat describes the link itself, so a symlink to a directory
|
|
43
|
+
// was misclassified as 'file' and the workspace picker refused to enter
|
|
44
|
+
// it (issue #59). A dangling link fails stat and degrades to 'file'.
|
|
45
|
+
await Promise.all(symIdx.map(async (i) => {
|
|
46
|
+
const full = joinRemotePath(target, items[i].name)
|
|
47
|
+
try {
|
|
48
|
+
const st = await sftp.stat(full)
|
|
49
|
+
items[i].type = st && st.isDirectory && st.isDirectory() ? 'dir' : 'file'
|
|
50
|
+
items[i].link = true
|
|
51
|
+
} catch { items[i].type = 'file' /* dangling link: degrade to file */ }
|
|
52
|
+
}))
|
|
53
|
+
}
|
|
54
|
+
return { path: target, items }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Windows drive letters as display-form dir entries ("This PC" root view). */
|
|
58
|
+
export async function listRemoteDrives(sshPool) {
|
|
59
|
+
let letters = []
|
|
60
|
+
try {
|
|
61
|
+
const res = await sshPool.exec('cmd /c fsutil fsinfo drives', { timeoutMs: Math.min(sshPool.config.commandTimeoutMs || 8000, 8000) })
|
|
62
|
+
letters = [...String(res.stdout || '').matchAll(/([a-zA-Z]):\\?/g)].map((mm) => mm[1].toUpperCase())
|
|
63
|
+
} catch {}
|
|
64
|
+
if (!letters.length) {
|
|
65
|
+
try {
|
|
66
|
+
const res = await sshPool.exec('ls -d /[a-z] 2>/dev/null', { timeoutMs: Math.min(sshPool.config.commandTimeoutMs || 8000, 8000) })
|
|
67
|
+
letters = String(res.stdout || '')
|
|
68
|
+
.split(/\s+/)
|
|
69
|
+
.map((s) => s.replace(/^\/+|\/+$/g, ''))
|
|
70
|
+
.filter((s) => /^[a-zA-Z]$/.test(s))
|
|
71
|
+
.map((s) => s.toUpperCase())
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
return [...new Set(letters)].sort().map((l) => ({ name: l + ':\\', path: l + ':\\', type: 'dir', drive: true, size: 0, mtime: 0 }))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Recursive remote delete (bounded): unlink files bottom-up, then rmdir. */
|
|
78
|
+
export async function removeRemoteTree(sftp, p, maxFiles = 2000) {
|
|
79
|
+
let removed = 0
|
|
80
|
+
const walk = async (dir) => {
|
|
81
|
+
if (removed >= maxFiles) return
|
|
82
|
+
let entries = []
|
|
83
|
+
try { entries = (await sftp.readdir(dir)) || [] } catch { return }
|
|
84
|
+
for (const e of entries) {
|
|
85
|
+
if (removed >= maxFiles) return
|
|
86
|
+
const name = String(e.filename)
|
|
87
|
+
if (name === '.' || name === '..') continue
|
|
88
|
+
const fp = joinRemotePath(dir, name)
|
|
89
|
+
const isDir = !!(e.attrs && e.attrs.isDirectory && e.attrs.isDirectory())
|
|
90
|
+
if (isDir) await walk(fp)
|
|
91
|
+
else {
|
|
92
|
+
try { await sftp.unlink(fp); removed++ } catch {}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
try { await sftp.rmdir(dir); removed++ } catch { /* already gone or non-empty */ }
|
|
96
|
+
}
|
|
97
|
+
await walk(p)
|
|
98
|
+
return removed
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function looksBinary(buf) {
|
|
102
|
+
const n = Math.min(buf.length, 8192)
|
|
103
|
+
for (let i = 0; i < n; i++) if (buf[i] === 0) return true
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Read a remote file for the sidebar/editor. Oversized files use a range read
|
|
109
|
+
* (`readPartial`) so we never `fastGet` the whole blob onto disk.
|
|
110
|
+
*/
|
|
111
|
+
export async function previewRemoteFile(sftp, target, opts = {}) {
|
|
112
|
+
const {
|
|
113
|
+
maxBytes = 256 * 1024,
|
|
114
|
+
encoding = 'utf-8',
|
|
115
|
+
decodeBuf = (buf) => buf.toString('utf8'),
|
|
116
|
+
} = opts
|
|
117
|
+
const cap = Math.min(Math.max(Number(maxBytes) || 256 * 1024, 1024), 2 * 1024 * 1024)
|
|
118
|
+
const st = await sftp.stat(target)
|
|
119
|
+
const mtime = st && typeof st.mtime === 'number' ? st.mtime : 0
|
|
120
|
+
const size = st && typeof st.size === 'number' ? st.size : 0
|
|
121
|
+
let buf
|
|
122
|
+
let truncated = false
|
|
123
|
+
if (size > cap) {
|
|
124
|
+
truncated = true
|
|
125
|
+
if (typeof sftp.readPartial === 'function') {
|
|
126
|
+
buf = await sftp.readPartial(target, 0, cap)
|
|
127
|
+
} else {
|
|
128
|
+
const full = await sftp.readFile(target)
|
|
129
|
+
buf = full.subarray(0, cap)
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
buf = await sftp.readFile(target)
|
|
133
|
+
}
|
|
134
|
+
if (looksBinary(buf)) {
|
|
135
|
+
return {
|
|
136
|
+
ok: true, binary: true, size, mtime,
|
|
137
|
+
head: buf.slice(0, Math.min(buf.length, 4096)).toString('base64'),
|
|
138
|
+
truncated,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
let content = decodeBuf(buf, encoding).replace(/\r\n/g, '\n')
|
|
142
|
+
if (!truncated && content.length > cap) {
|
|
143
|
+
truncated = true
|
|
144
|
+
content = content.slice(0, cap)
|
|
145
|
+
}
|
|
146
|
+
if (truncated) content += `\n…[truncated: ${Math.max(0, size - cap)} more bytes]`
|
|
147
|
+
return { ok: true, binary: false, content, truncated, size, mtime }
|
|
148
|
+
}
|