const smb2 = require("@awo00/smb2"); const express = require("express"); const crypto = require("crypto"); const SessionPool = require("./session_pool"); const utility = require("./utility"); require("./polyfill.js"); const host = process.argv[2]; if (!host) { console.error("Please provide a host as a command line argument."); process.exit(1); } const client = new smb2.Client(host); const app = express(); app.use(express.urlencoded({ extended: true })); /** * @typedef {import("@awo00/smb2/dist/client/Session").default} Session */ /** * @type {SessionPool} */ const sessionPool = new SessionPool(60000); app.post("/", async (req, res) => { try { const username = req.body.username; const password = req.body.password; const domain = req.body.domain; const session = await client.authenticate({ username, password, domain }); const sessionId = crypto.randomUUID(); session.trees = {} sessionPool.createSession(sessionId, session, async (session) => await session.logoff()); res.end(JSON.stringify({ "error": null, "sessionId": sessionId })); } catch (error) { res.status(500).json({ error: error.message }); res.end(); } }); // Define routes for file operations app.get("/:sessionId/:shareName/*", async (req, res) => { try { const sessionId = req.params.sessionId; const shareName = req.params.shareName; /** * @type {string} */ const filePath = "/" + req.params[0]; const session = sessionPool.getSession(sessionId); const tree = await utility.getTree(session, shareName); if (filePath.endsWith("/")) { const entries = await tree.readDirectory(filePath); res.end(JSON.stringify({ error: null, entries })); } else { const readStream = await tree.createFileReadStream(filePath); readStream.pipe(res); readStream.on("error", (error) => { res.status(500).json({ error: error.message }); res.end(); }); } } catch (error) { res.status(500).json({ error: error.message }); res.end(); } }); app.post("/:sessionId/:shareName/*", async (req, res) => { try { const sessionId = req.params.sessionId; const shareName = req.params.shareName; /** * @type {string} */ const filePath = "/" + req.params[0]; const session = sessionPool.getSession(sessionId); const tree = await utility.getTree(session, shareName); // Get the uploaded file from the request const file = req.files.file; // Check if the file already exists const fileExists = await tree.exists(filePath); // Check if the force parameter is provided in the form const force = req.body.force; if (fileExists && !force) { res.status(200).json({ error: null, exists: true }); res.end(); } else { // Create a write stream to the destination file const writeStream = await tree.createFileWriteStream(filePath); // Pipe the uploaded file to the write stream file.pipe(writeStream); // Handle events for the write stream writeStream.on("finish", () => { res.end(JSON.stringify({ error: null })); }); writeStream.on("error", (error) => { res.status(500).json({ error: error.message }); res.end(); }); } } catch (error) { res.status(500).json({ error: error.message }); res.end(); } }); app.put("/:sessionId/:shareName/*", async (req, res) => { try { const sessionId = req.params.sessionId; const shareName = req.params.shareName; /** * @type {string} */ const filePath = "/" + req.params[0]; const session = sessionPool.getSession(sessionId); const tree = await utility.getTree(session, shareName); // Check if the folder already exists const folderExists = await tree.exists(filePath); if (folderExists) { res.status(200).json({ error: null, exists: true }); res.end(); } else { // Create the folder await tree.createDirectory(filePath); res.end(JSON.stringify({ error: null })); } } catch (error) { res.status(500).json({ error: error.message }); res.end(); } }); // Start the server const port = 8082; app.listen(port, () => { console.log(`Server is running on port ${port}`); });