wasm-rdp/filegateway/index.js

158 lines
4.7 KiB
JavaScript

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<Session>}
*/
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}`);
});