const Express = require("express"); const express = Express.Router(); const crypto = require("crypto"); const fs = require("fs"); const path = require("path"); const functions = require("./functions.js"); express.use((req, res, next) => { if (req.originalUrl.toLowerCase().startsWith("/fortnite/api/cloudstorage/user/") && req.method == "PUT") { req.rawBody = ""; req.setEncoding("latin1"); let contentLength = parseInt(req.headers['content-length'] || '0'); if (contentLength > 512000) { return res.status(413).json({ "error": "Request entity too large. Maximum size is 500KB." }); } let size = 0; req.on("data", (chunk) => { size += Buffer.byteLength(chunk); if (size > 512000) { return req.destroy(); } req.rawBody += chunk; }); req.on("end", () => next()); } else return next(); }) express.get("/fortnite/api/cloudstorage/system", async (req, res) => { const memory = functions.GetVersionInfo(req); if (memory.build >= 9.40 && memory.build <= 10.40) { return res.status(404).end(); } const dir = path.join(__dirname, "..", "CloudStorage") var CloudFiles = []; fs.readdirSync(dir).forEach(name => { if (name.toLowerCase().endsWith(".ini")) { const ParsedFile = fs.readFileSync(path.join(dir, name), 'utf-8'); const ParsedStats = fs.statSync(path.join(dir, name)); CloudFiles.push({ "uniqueFilename": name, "filename": name, "hash": crypto.createHash('sha1').update(ParsedFile).digest('hex'), "hash256": crypto.createHash('sha256').update(ParsedFile).digest('hex'), "length": ParsedFile.length, "contentType": "application/octet-stream", "uploaded": ParsedStats.mtime, "storageType": "S3", "storageIds": {}, "doNotCache": true }) } }); res.json(CloudFiles) }) express.get("/fortnite/api/cloudstorage/system/:file", async (req, res) => { const requestedFile = req.params.file; if (requestedFile.includes('../') || requestedFile.includes('..\\') || requestedFile.includes('/') || requestedFile.includes('\\') || requestedFile.startsWith('.')) { return res.status(404).json({ "error": "file not found" }); } const file = path.join(__dirname, "..", "CloudStorage", requestedFile); const normalizedFilePath = path.normalize(file); const normalizedTargetDir = path.normalize(path.join(__dirname, "..", "CloudStorage")); if (!normalizedFilePath.startsWith(normalizedTargetDir)) { return res.status(404).json({ "error": "file not found" }); } if (fs.existsSync(file)) { const ParsedFile = fs.readFileSync(file); return res.status(200).send(ParsedFile).end(); } else { res.status(200); res.end(); } }) express.get("/fortnite/api/cloudstorage/user/*/:file", async (req, res) => { try { if (!fs.existsSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings"))) { fs.mkdirSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings")); } } catch (err) {} res.set("Content-Type", "application/octet-stream") const requestedFile = req.params.file.toLowerCase(); if (requestedFile !== "clientsettings.sav") { return res.status(404).json({ "error": "file not found" }); } const memory = functions.GetVersionInfo(req); var currentBuildID = memory.CL; let file; if (process.env.LOCALAPPDATA) file = path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); else file = path.join(__dirname, "..", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); if (fs.existsSync(file)) { const ParsedFile = fs.readFileSync(file); return res.status(200).send(ParsedFile).end(); } else { res.status(200); res.end(); } }) express.get("/fortnite/api/cloudstorage/user/:accountId", async (req, res) => { try { if (!fs.existsSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings"))) { fs.mkdirSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings")); } } catch (err) {} res.set("Content-Type", "application/json") const memory = functions.GetVersionInfo(req); var currentBuildID = memory.CL; let file; if (process.env.LOCALAPPDATA) file = path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); else file = path.join(__dirname, "..", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); if (fs.existsSync(file)) { const ParsedFile = fs.readFileSync(file, 'latin1'); const ParsedStats = fs.statSync(file); return res.json([{ "uniqueFilename": "ClientSettings.Sav", "filename": "ClientSettings.Sav", "hash": crypto.createHash('sha1').update(ParsedFile).digest('hex'), "hash256": crypto.createHash('sha256').update(ParsedFile).digest('hex'), "length": Buffer.byteLength(ParsedFile), "contentType": "application/octet-stream", "uploaded": ParsedStats.mtime, "storageType": "S3", "storageIds": {}, "accountId": req.params.accountId, "doNotCache": true }]); } else { return res.json([]); } }) express.put("/fortnite/api/cloudstorage/user/*/:file", async (req, res) => { try { if (!fs.existsSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings"))) { fs.mkdirSync(path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings")); } } catch (err) {} const requestedFile = req.params.file.toLowerCase(); if (requestedFile !== "clientsettings.sav") { return res.status(404).json({ "error": "file not found" }); } const memory = functions.GetVersionInfo(req); var currentBuildID = memory.CL; let file; if (process.env.LOCALAPPDATA) file = path.join(process.env.LOCALAPPDATA, "LawinServer", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); else file = path.join(__dirname, "..", "ClientSettings", `ClientSettings-${currentBuildID}.Sav`); fs.writeFileSync(file, req.rawBody, 'latin1'); res.status(204).end(); }) module.exports = express;