[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
97
lib/zmodemDragDrop.ts
Normal file
97
lib/zmodemDragDrop.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import type { DropEntry } from "./sftpFileUtils";
|
||||
import { getDropEntryLocalPath } from "./sftpFileUtils";
|
||||
import type { Host } from "../types";
|
||||
|
||||
const ZMODEM_RZ_MISSING_MARKER_PREFIX = "\x1b]1337;NetcattyRzMissing=";
|
||||
const ZMODEM_RZ_MISSING_MARKER_SUFFIX = "\x07";
|
||||
|
||||
/**
|
||||
* Default PTY command for drag-drop ZMODEM upload.
|
||||
* lrzsz `rz` defaults to protect mode and will not replace an existing
|
||||
* same-named file; `-y` / `--overwrite` is required (issue #2863).
|
||||
*/
|
||||
export const ZMODEM_DEFAULT_RZ_UPLOAD_COMMAND = "rz -y\r";
|
||||
|
||||
export type ZmodemDragDropFile = {
|
||||
path?: string;
|
||||
name: string;
|
||||
remoteName: string;
|
||||
data?: ArrayBuffer;
|
||||
};
|
||||
|
||||
export function supportsZmodemTerminalDragDrop(
|
||||
host: Host,
|
||||
isNetworkDevice = false,
|
||||
): boolean {
|
||||
if (host.protocol === "local" || isNetworkDevice) return false;
|
||||
if (host.moshEnabled || host.etEnabled) return true;
|
||||
return (
|
||||
host.protocol === "ssh" ||
|
||||
host.protocol === "telnet" ||
|
||||
host.protocol === "serial"
|
||||
);
|
||||
}
|
||||
|
||||
export function supportsZmodemDragDropSftpFallback(host: Host): boolean {
|
||||
return host.protocol === "ssh" || Boolean(host.moshEnabled || host.etEnabled);
|
||||
}
|
||||
|
||||
export function getZmodemRemoteName(relativePath: string, fallbackName: string): string {
|
||||
const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
||||
if (!normalized) return fallbackName;
|
||||
const segments = normalized.split("/").filter(Boolean);
|
||||
return segments[segments.length - 1] || fallbackName;
|
||||
}
|
||||
|
||||
function quotePosixShellArg(value: string): string {
|
||||
return `'${value.replace(/'/g, "'\\''")}'`;
|
||||
}
|
||||
|
||||
export function createZmodemRzMissingToken(): string {
|
||||
return `rz-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
||||
}
|
||||
|
||||
export function buildZmodemDragDropUploadCommand(rzMissingToken: string): string {
|
||||
const markerFormat = `\\033]1337;NetcattyRzMissing=${rzMissingToken}\\007`;
|
||||
const script = `if command -v rz >/dev/null 2>&1; then exec rz -y; else printf ${quotePosixShellArg(markerFormat)}; fi`;
|
||||
return `sh -lc ${quotePosixShellArg(script)}\r`;
|
||||
}
|
||||
|
||||
export function containsZmodemRzMissingMarker(chunk: string, rzMissingToken: string): boolean {
|
||||
return chunk.includes(`${ZMODEM_RZ_MISSING_MARKER_PREFIX}${rzMissingToken}${ZMODEM_RZ_MISSING_MARKER_SUFFIX}`);
|
||||
}
|
||||
|
||||
export async function buildZmodemDragDropFiles(
|
||||
dropEntries: DropEntry[],
|
||||
): Promise<ZmodemDragDropFile[]> {
|
||||
const files: ZmodemDragDropFile[] = [];
|
||||
|
||||
for (const entry of dropEntries) {
|
||||
if (entry.isDirectory) continue;
|
||||
|
||||
const fileName = entry.file?.name
|
||||
|| entry.relativePath.replace(/\\/g, "/").split("/").pop()
|
||||
|| entry.relativePath;
|
||||
const remoteName = getZmodemRemoteName(entry.relativePath, fileName);
|
||||
const localPath = getDropEntryLocalPath(entry);
|
||||
|
||||
if (localPath) {
|
||||
files.push({
|
||||
path: localPath,
|
||||
name: fileName,
|
||||
remoteName,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!entry.file) continue;
|
||||
const data = await entry.file.arrayBuffer();
|
||||
files.push({
|
||||
name: fileName,
|
||||
remoteName,
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
Reference in New Issue
Block a user