1
0
mirror of https://github.com/KubaPro010/fm-dx-webserver.git synced 2026-02-26 14:11:59 +01:00

security fixes, bugfixes

This commit is contained in:
Marek Farkaš
2025-01-16 21:38:54 +01:00
parent d0a8fbaf81
commit 20864c572b
10 changed files with 67 additions and 30 deletions

View File

@@ -82,7 +82,7 @@ function handleConnect(clientIp, currentUsers, ws) {
const userLocation = `${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.countryCode}`;
const userData = { ip: clientIp, location: userLocation, time: connectionTime, instance: ws };
storage.connectedUsers.push(userData);
consoleCmd.logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${locationInfo.city}, ${locationInfo.region}, ${locationInfo.country}`);
consoleCmd.logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.country}`);
}
} catch (error) {
console.log(error);
@@ -90,7 +90,7 @@ function handleConnect(clientIp, currentUsers, ws) {
}
});
}).on('error', (err) => {
consoleCmd.chunklogInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m`);
consoleCmd.logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m`);
});
}
@@ -222,7 +222,16 @@ function antispamProtection(message, clientIp, ws, userCommands, lastWarn, userC
return command; // Return command value for normal execution
}
const escapeHtml = (unsafe) => {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
};
module.exports = {
authenticateWithXdrd, parseMarkdown, handleConnect, removeMarkdown, formatUptime, resolveDataBuffer, kickClient, checkIPv6Support, antispamProtection
authenticateWithXdrd, parseMarkdown, handleConnect, removeMarkdown, formatUptime, resolveDataBuffer, kickClient, checkIPv6Support, antispamProtection, escapeHtml
}

View File

@@ -5,6 +5,7 @@ const session = require('express-session');
const bodyParser = require('body-parser');
const http = require('http');
const httpProxy = require('http-proxy');
const readline = require('readline');
const app = express();
const httpServer = http.createServer(app);
const WebSocket = require('ws');
@@ -72,6 +73,10 @@ if (plugins.length > 0) {
}, 3000); // Initial delay of 3 seconds for the first plugin
}
const terminalWidth = readline.createInterface({
input: process.stdin,
output: process.stdout
}).output.columns;
console.log(`\x1b[32m
@@ -81,8 +86,9 @@ console.log(`\x1b[32m
| _| | | | |_____| |_| / \\ \\ V V / __/ |_) \\__ \\ __/ | \\ V / __/ |
|_| |_| |_| |____/_/\\_\\ \\_/\\_/ \\___|_.__/|___/\\___|_| \\_/ \\___|_|
`);
console.log('\x1b[0mFM-DX Webserver', pjson.version);
console.log('\x1b[90m―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――');
console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org\x1b[0m');
console.log("v" + pjson.version)
console.log('\x1b[90m' + '─'.repeat(terminalWidth - 1) + '\x1b[0m');
// Start ffmpeg
require('./stream/index');
@@ -446,9 +452,9 @@ wss.on('connection', (ws, request) => {
const { isAdminAuthenticated, isTuneAuthenticated } = request.session || {};
if (serverConfig.publicTuner || (serverConfig.lockToAdmin && isAdminAuthenticated) || (!serverConfig.lockToAdmin && isTuneAuthenticated)) {
if ((serverConfig.publicTuner && !serverConfig.lockToAdmin) || isAdminAuthenticated || (!serverConfig.publicTuner && !serverConfig.lockToAdmin && isTuneAuthenticated)) {
output.write(`${command}\n`);
}
}
});
@@ -528,6 +534,11 @@ chatWss.on('connection', (ws, request) => {
return;
}
// Escape nickname and other potentially unsafe fields
if (messageData.nickname) {
messageData.nickname = helpers.escapeHtml(messageData.nickname);
}
messageData.ip = clientIp;
const currentTime = new Date();

View File

@@ -100,7 +100,7 @@ let serverConfig = {
autoShutdown: false,
enableDefaultFreq: false,
defaultFreq: "87.5",
TestTest: "tesst"
bwSwitch: false
};
// Function to add missing fields without overwriting existing values

View File

@@ -230,6 +230,19 @@ table .input-text {
clear: both;
}
.blink {
animation: blinker 1.5s infinite;
}
@keyframes blinker {
0% {
background-color: var(--color-4);
}
100% {
background-color: var(--color-2);
}
}
@media only screen and (max-width: 960px) {
.text-medium-big {
font-size: 32px;

View File

@@ -1,3 +1,12 @@
body.modal-open {
overflow: hidden;
}
.modal-panel, .modal-panel-chat {
max-height: 100vh;
overflow-y: auto;
}
.modal {
display: none;
position: fixed;
@@ -162,7 +171,7 @@
width: 100%;
}
.modal-panel-chat {
height: 500px;
height: 550px;
}
#chat-chatbox {
height: 333px !important;

View File

@@ -30,7 +30,7 @@ $(document).ready(function() {
const isAdmin = messageData.admin ? '<span style="color: #bada55">[ADMIN]</span>' : '';
if (messageData.type === 'clientIp') {
chatIdentityNickname.html(isAdmin + " " + savedNickname);
chatIdentityNickname.html(isAdmin).append(document.createTextNode(" " + savedNickname));
chatIdentityNickname.attr('title', messageData.ip);
} else {
const chatMessage = `
@@ -49,7 +49,7 @@ $(document).ready(function() {
chatMessageCount++;
chatMessagesCount.text(chatMessageCount);
chatMessagesCount.attr("aria-label", "Chat (" + chatMessageCount + " unread)");
chatButton.removeClass('bg-color-2').addClass('bg-color-4');
chatButton.removeClass('bg-color-2').addClass('blink');
}
}
}

View File

@@ -38,22 +38,14 @@ function fetchConfig() {
function populateFields(data, prefix = "") {
$.each(data, (key, value) => {
if (key === "presets" && Array.isArray(value)) {
value.forEach((item, index) => {
const presetId = `${prefix}${prefix ? "-" : ""}${key}-${index + 1}`;
const $element = $(`#${presetId}`);
if ($element.length) {
$element.val(item);
}
});
return;
if (value === null) {
value = ""; // Convert null to an empty string
}
const id = `${prefix}${prefix ? "-" : ""}${key}`;
const $element = $(`#${id}`);
if (typeof value === "object" && !Array.isArray(value)) {
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
populateFields(value, id);
return;
}
@@ -96,7 +88,7 @@ function updateConfigData(data, prefix = "") {
while (true) {
const $presetElement = $(`#${prefix}${prefix ? "-" : ""}${key}-${index}`);
if ($presetElement.length) {
data[key].push($presetElement.val());
data[key].push($presetElement.val() || null); // Allow null if necessary
index++;
} else {
break;
@@ -117,12 +109,13 @@ function updateConfigData(data, prefix = "") {
return;
}
if (typeof value === "object" && !Array.isArray(value)) {
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
return updateConfigData(value, id);
}
if ($element.length) {
data[key] = typeof value === "boolean" ? $element.is(":checked") : $element.attr("data-value") ?? $element.val();
const newValue = $element.attr("data-value") ?? $element.val() ?? null;
data[key] = typeof value === "boolean" ? $element.is(":checked") : newValue;
}
});
}

View File

@@ -1,9 +1,9 @@
var currentDate = new Date('Jan 11, 2025 21:00:00');
var currentDate = new Date('Jan 16, 2025 21:00:00');
var day = currentDate.getDate();
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
var year = currentDate.getFullYear();
var formattedDate = day + '/' + month + '/' + year;
var currentVersion = 'v1.3.3 [' + formattedDate + ']';
var currentVersion = 'v1.3.3.1 [' + formattedDate + ']';
getInitialSettings();
removeUrlParameters();

View File

@@ -10,17 +10,18 @@ $(document).ready(function() {
function openModal(panel) {
modal.css("display", "block");
panel.css("display", "block");
$("body").addClass("modal-open"); // Disable body scrolling
setTimeout(function() {
modal.css("opacity", 1);
}, 10);
}
// Function to close the modal
function closeModal() {
modal.css("opacity", 0);
setTimeout(function() {
modal.css("display", "none");
modalPanel.add(chatPanel).css("display", "none");
$("body").removeClass("modal-open"); // Enable body scrolling
}, 300);
}

View File

@@ -142,7 +142,7 @@ function toggleNav() {
if (isMobile) {
// Do nothing to .admin-wrapper on mobile (since we're overlaying)
$(".admin-wrapper").css({
'margin-left': '0',
'margin-left': '32px',
'width': '100%' // Reset content to full width on close
});
$("#navigation").css('margin-left', 'calc(64px - 100vw)');
@@ -216,6 +216,7 @@ async function loadConsoleLogs() {
const logColors = {
INFO: "lime",
DEBUG: "cyan",
CHAT: "cyan",
WARN: "yellow",
ERROR: "red"
};