From 648ef00bed2e3fc7688710333aaf422e8b802811 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Tue, 24 Feb 2026 14:44:48 +0100 Subject: [PATCH] sync to upstream --- server/chat.js | 40 +++++++++++++++++++++++++++++++++------- server/helpers.js | 10 ++++++++-- server/index.js | 2 +- web/favicon.png | Bin 6048 -> 0 bytes web/favicon.svg | 24 ++++++++++++++++++++++++ web/index.ejs | 2 +- web/js/settings.js | 22 ++++++++++++++++++++++ web/login.ejs | 4 ++-- web/setup.ejs | 2 +- web/wizard.ejs | 2 +- 10 files changed, 93 insertions(+), 15 deletions(-) delete mode 100644 web/favicon.png create mode 100644 web/favicon.svg diff --git a/server/chat.js b/server/chat.js index a538adc..f46655f 100644 --- a/server/chat.js +++ b/server/chat.js @@ -3,12 +3,19 @@ const { serverConfig } = require('./server_config'); const { logChat } = require('./console'); const helpers = require('./helpers'); +function heartbeat() { // WebSocket heartbeat helper + this.isAlive = true; +} + function createChatServer(storage) { if (!serverConfig.webserver.chatEnabled) return null; const chatWss = new WebSocket.Server({ noServer: true }); chatWss.on('connection', (ws, request) => { + ws.isAlive = true; + ws.on('pong', heartbeat); + const clientIp = request.headers['x-forwarded-for'] || request.socket.remoteAddress; const userCommandHistory = {}; @@ -25,19 +32,18 @@ function createChatServer(storage) { ws.send(JSON.stringify(historyMessage)); }); - const ipMessage = { + ws.send(JSON.stringify({ type: 'clientIp', ip: clientIp, admin: request.session?.isAdminAuthenticated - }; + })); - ws.send(JSON.stringify(ipMessage)); const userCommands = {}; let lastWarn = { time: 0 }; ws.on('message', (message) => { - helpers.antispamProtection( + message = helpers.antispamProtection( message, clientIp, ws, @@ -45,9 +51,12 @@ function createChatServer(storage) { lastWarn, userCommandHistory, '5', - 'chat' + 'chat', + 512 ); + if(!message) return; + let messageData; try { @@ -57,8 +66,6 @@ function createChatServer(storage) { return; } - console.log("Chat message:", messageData); - delete messageData.admin; delete messageData.ip; delete messageData.time; @@ -90,6 +97,25 @@ function createChatServer(storage) { } }); }); + + ws.on('close', () => { + ws.isAlive = false; + }); + }); + + /** + * We will not always be receiving data, so some proxies may terminate the connection, this prevents it. + */ + const interval = setInterval(() => { + chatWss.clients.forEach((ws) => { + if (ws.isAlive === false) return ws.terminate(); + ws.isAlive = false; + ws.ping(); + }); + }, 30000); + + chatWss.on('close', () => { + clearInterval(interval); }); return chatWss; diff --git a/server/helpers.js b/server/helpers.js index 8c11b7f..681686a 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -250,12 +250,18 @@ function checkLatency(host, port = 80, timeout = 2000) { }); } -function antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, lengthCommands, endpointName) { - const command = message.toString(); +function antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, lengthCommands, endpointName, maxPayloadSize = 1024 * 1024) { + const rawCommand = message.toString(); + const command = rawCommand.replace(/[\r\n]+/g, ''); const now = Date.now(); const normalizedClientIp = clientIp?.replace(/^::ffff:/, ''); if (endpointName === 'text') consoleCmd.logDebug(`Command received from \x1b[90m${clientIp}\x1b[0m: ${command}`); + if (command.length > maxPayloadSize) { + consoleCmd.logWarn(`Command from \x1b[90m${normalizedClientIp}\x1b[0m on \x1b[90m/${endpointName}\x1b[0m exceeded maximum payload size (${parseInt(command.length / 1024)} KB / ${parseInt(maxPayloadSize / 1024)} KB).`); + return ""; + } + // Initialize user command history if not present if (!userCommandHistory[clientIp]) userCommandHistory[clientIp] = []; diff --git a/server/index.js b/server/index.js index 734c3f2..fd4a6df 100644 --- a/server/index.js +++ b/server/index.js @@ -356,7 +356,7 @@ wss.on('connection', (ws, request) => { let lastWarn = { time: 0 }; ws.on('message', (message) => { - const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text'); + const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text', 16 * 1024); if (!clientIp.includes("127.0.0.1")) { if (((command.startsWith('X') || command.startsWith('Y')) && !request.session.isAdminAuthenticated) || diff --git a/web/favicon.png b/web/favicon.png deleted file mode 100644 index 0e104c3f04ba312b251ae52d774ac448895b6c63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6048 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 PFfe$!`njxgN@xNAWP4FO diff --git a/web/favicon.svg b/web/favicon.svg new file mode 100644 index 0000000..71c67a0 --- /dev/null +++ b/web/favicon.svg @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file diff --git a/web/index.ejs b/web/index.ejs index 14d0957..4a00c2e 100644 --- a/web/index.ejs +++ b/web/index.ejs @@ -15,7 +15,7 @@ - + diff --git a/web/js/settings.js b/web/js/settings.js index c647ba9..382e522 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -75,6 +75,27 @@ function getQueryParameter(name) { return urlParams.get(name); } +function updateFavicon(color) { + function rgbToHex(rgb) { + const result = rgb.match(/\d+/g); + return "#" + result.slice(0, 3).map(x =>(+x).toString(16).padStart(2, "0")).join(""); + } + + const hex = rgbToHex(color); + + const svg = ` + + + `; + + const base64 = btoa(svg); + + $('#favicon').attr( + 'href', + `data:image/svg+xml;base64,${base64}` + ); +} + function setTheme(themeName) { const themeColors = themes[themeName]; if (themeColors) { @@ -94,6 +115,7 @@ function setTheme(themeName) { $(':root').css('--color-text', themeColors[2]); $(':root').css('--color-text-2', textColor2); $('.wrapper-outer').css('background-color', backgroundColorWithOpacity); + updateFavicon(themeColors[1]); } } diff --git a/web/login.ejs b/web/login.ejs index edccb84..2a34086 100644 --- a/web/login.ejs +++ b/web/login.ejs @@ -8,7 +8,7 @@ - + @@ -16,7 +16,7 @@
- +

You are currently not logged in as an administrator and therefore can't change the settings.

Please login below.

diff --git a/web/setup.ejs b/web/setup.ejs index 3e5ec69..8b86fe2 100644 --- a/web/setup.ejs +++ b/web/setup.ejs @@ -8,7 +8,7 @@ - + diff --git a/web/wizard.ejs b/web/wizard.ejs index 24472f4..74dcb64 100644 --- a/web/wizard.ejs +++ b/web/wizard.ejs @@ -8,7 +8,7 @@ - +