You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-26 22:13:53 +01:00
security fixes, bugfixes
This commit is contained in:
@@ -82,7 +82,7 @@ function handleConnect(clientIp, currentUsers, ws) {
|
|||||||
const userLocation = `${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.countryCode}`;
|
const userLocation = `${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.countryCode}`;
|
||||||
const userData = { ip: clientIp, location: userLocation, time: connectionTime, instance: ws };
|
const userData = { ip: clientIp, location: userLocation, time: connectionTime, instance: ws };
|
||||||
storage.connectedUsers.push(userData);
|
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) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -90,7 +90,7 @@ function handleConnect(clientIp, currentUsers, ws) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).on('error', (err) => {
|
}).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
|
return command; // Return command value for normal execution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const escapeHtml = (unsafe) => {
|
||||||
|
return unsafe
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
authenticateWithXdrd, parseMarkdown, handleConnect, removeMarkdown, formatUptime, resolveDataBuffer, kickClient, checkIPv6Support, antispamProtection
|
authenticateWithXdrd, parseMarkdown, handleConnect, removeMarkdown, formatUptime, resolveDataBuffer, kickClient, checkIPv6Support, antispamProtection, escapeHtml
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ const session = require('express-session');
|
|||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const httpProxy = require('http-proxy');
|
const httpProxy = require('http-proxy');
|
||||||
|
const readline = require('readline');
|
||||||
const app = express();
|
const app = express();
|
||||||
const httpServer = http.createServer(app);
|
const httpServer = http.createServer(app);
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
@@ -72,6 +73,10 @@ if (plugins.length > 0) {
|
|||||||
}, 3000); // Initial delay of 3 seconds for the first plugin
|
}, 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
|
console.log(`\x1b[32m
|
||||||
@@ -81,8 +86,9 @@ console.log(`\x1b[32m
|
|||||||
| _| | | | |_____| |_| / \\ \\ V V / __/ |_) \\__ \\ __/ | \\ V / __/ |
|
| _| | | | |_____| |_| / \\ \\ V V / __/ |_) \\__ \\ __/ | \\ V / __/ |
|
||||||
|_| |_| |_| |____/_/\\_\\ \\_/\\_/ \\___|_.__/|___/\\___|_| \\_/ \\___|_|
|
|_| |_| |_| |____/_/\\_\\ \\_/\\_/ \\___|_.__/|___/\\___|_| \\_/ \\___|_|
|
||||||
`);
|
`);
|
||||||
console.log('\x1b[0mFM-DX Webserver', pjson.version);
|
console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org\x1b[0m');
|
||||||
console.log('\x1b[90m―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――');
|
console.log("v" + pjson.version)
|
||||||
|
console.log('\x1b[90m' + '─'.repeat(terminalWidth - 1) + '\x1b[0m');
|
||||||
|
|
||||||
// Start ffmpeg
|
// Start ffmpeg
|
||||||
require('./stream/index');
|
require('./stream/index');
|
||||||
@@ -446,9 +452,9 @@ wss.on('connection', (ws, request) => {
|
|||||||
|
|
||||||
const { isAdminAuthenticated, isTuneAuthenticated } = request.session || {};
|
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`);
|
output.write(`${command}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -528,6 +534,11 @@ chatWss.on('connection', (ws, request) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Escape nickname and other potentially unsafe fields
|
||||||
|
if (messageData.nickname) {
|
||||||
|
messageData.nickname = helpers.escapeHtml(messageData.nickname);
|
||||||
|
}
|
||||||
|
|
||||||
messageData.ip = clientIp;
|
messageData.ip = clientIp;
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ let serverConfig = {
|
|||||||
autoShutdown: false,
|
autoShutdown: false,
|
||||||
enableDefaultFreq: false,
|
enableDefaultFreq: false,
|
||||||
defaultFreq: "87.5",
|
defaultFreq: "87.5",
|
||||||
TestTest: "tesst"
|
bwSwitch: false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to add missing fields without overwriting existing values
|
// Function to add missing fields without overwriting existing values
|
||||||
|
|||||||
@@ -230,6 +230,19 @@ table .input-text {
|
|||||||
clear: both;
|
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) {
|
@media only screen and (max-width: 960px) {
|
||||||
.text-medium-big {
|
.text-medium-big {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
body.modal-open {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-panel, .modal-panel-chat {
|
||||||
|
max-height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -162,7 +171,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.modal-panel-chat {
|
.modal-panel-chat {
|
||||||
height: 500px;
|
height: 550px;
|
||||||
}
|
}
|
||||||
#chat-chatbox {
|
#chat-chatbox {
|
||||||
height: 333px !important;
|
height: 333px !important;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ $(document).ready(function() {
|
|||||||
const isAdmin = messageData.admin ? '<span style="color: #bada55">[ADMIN]</span>' : '';
|
const isAdmin = messageData.admin ? '<span style="color: #bada55">[ADMIN]</span>' : '';
|
||||||
|
|
||||||
if (messageData.type === 'clientIp') {
|
if (messageData.type === 'clientIp') {
|
||||||
chatIdentityNickname.html(isAdmin + " " + savedNickname);
|
chatIdentityNickname.html(isAdmin).append(document.createTextNode(" " + savedNickname));
|
||||||
chatIdentityNickname.attr('title', messageData.ip);
|
chatIdentityNickname.attr('title', messageData.ip);
|
||||||
} else {
|
} else {
|
||||||
const chatMessage = `
|
const chatMessage = `
|
||||||
@@ -49,7 +49,7 @@ $(document).ready(function() {
|
|||||||
chatMessageCount++;
|
chatMessageCount++;
|
||||||
chatMessagesCount.text(chatMessageCount);
|
chatMessagesCount.text(chatMessageCount);
|
||||||
chatMessagesCount.attr("aria-label", "Chat (" + chatMessageCount + " unread)");
|
chatMessagesCount.attr("aria-label", "Chat (" + chatMessageCount + " unread)");
|
||||||
chatButton.removeClass('bg-color-2').addClass('bg-color-4');
|
chatButton.removeClass('bg-color-2').addClass('blink');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,22 +38,14 @@ function fetchConfig() {
|
|||||||
|
|
||||||
function populateFields(data, prefix = "") {
|
function populateFields(data, prefix = "") {
|
||||||
$.each(data, (key, value) => {
|
$.each(data, (key, value) => {
|
||||||
if (key === "presets" && Array.isArray(value)) {
|
if (value === null) {
|
||||||
value.forEach((item, index) => {
|
value = ""; // Convert null to an empty string
|
||||||
const presetId = `${prefix}${prefix ? "-" : ""}${key}-${index + 1}`;
|
|
||||||
const $element = $(`#${presetId}`);
|
|
||||||
|
|
||||||
if ($element.length) {
|
|
||||||
$element.val(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = `${prefix}${prefix ? "-" : ""}${key}`;
|
const id = `${prefix}${prefix ? "-" : ""}${key}`;
|
||||||
const $element = $(`#${id}`);
|
const $element = $(`#${id}`);
|
||||||
|
|
||||||
if (typeof value === "object" && !Array.isArray(value)) {
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
||||||
populateFields(value, id);
|
populateFields(value, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,7 +88,7 @@ function updateConfigData(data, prefix = "") {
|
|||||||
while (true) {
|
while (true) {
|
||||||
const $presetElement = $(`#${prefix}${prefix ? "-" : ""}${key}-${index}`);
|
const $presetElement = $(`#${prefix}${prefix ? "-" : ""}${key}-${index}`);
|
||||||
if ($presetElement.length) {
|
if ($presetElement.length) {
|
||||||
data[key].push($presetElement.val());
|
data[key].push($presetElement.val() || null); // Allow null if necessary
|
||||||
index++;
|
index++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -117,12 +109,13 @@ function updateConfigData(data, prefix = "") {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === "object" && !Array.isArray(value)) {
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
||||||
return updateConfigData(value, id);
|
return updateConfigData(value, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($element.length) {
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 day = currentDate.getDate();
|
||||||
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
|
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
|
||||||
var year = currentDate.getFullYear();
|
var year = currentDate.getFullYear();
|
||||||
var formattedDate = day + '/' + month + '/' + year;
|
var formattedDate = day + '/' + month + '/' + year;
|
||||||
var currentVersion = 'v1.3.3 [' + formattedDate + ']';
|
var currentVersion = 'v1.3.3.1 [' + formattedDate + ']';
|
||||||
|
|
||||||
getInitialSettings();
|
getInitialSettings();
|
||||||
removeUrlParameters();
|
removeUrlParameters();
|
||||||
|
|||||||
@@ -10,17 +10,18 @@ $(document).ready(function() {
|
|||||||
function openModal(panel) {
|
function openModal(panel) {
|
||||||
modal.css("display", "block");
|
modal.css("display", "block");
|
||||||
panel.css("display", "block");
|
panel.css("display", "block");
|
||||||
|
$("body").addClass("modal-open"); // Disable body scrolling
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
modal.css("opacity", 1);
|
modal.css("opacity", 1);
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to close the modal
|
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
modal.css("opacity", 0);
|
modal.css("opacity", 0);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
modal.css("display", "none");
|
modal.css("display", "none");
|
||||||
modalPanel.add(chatPanel).css("display", "none");
|
modalPanel.add(chatPanel).css("display", "none");
|
||||||
|
$("body").removeClass("modal-open"); // Enable body scrolling
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ function toggleNav() {
|
|||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
// Do nothing to .admin-wrapper on mobile (since we're overlaying)
|
// Do nothing to .admin-wrapper on mobile (since we're overlaying)
|
||||||
$(".admin-wrapper").css({
|
$(".admin-wrapper").css({
|
||||||
'margin-left': '0',
|
'margin-left': '32px',
|
||||||
'width': '100%' // Reset content to full width on close
|
'width': '100%' // Reset content to full width on close
|
||||||
});
|
});
|
||||||
$("#navigation").css('margin-left', 'calc(64px - 100vw)');
|
$("#navigation").css('margin-left', 'calc(64px - 100vw)');
|
||||||
@@ -216,6 +216,7 @@ async function loadConsoleLogs() {
|
|||||||
const logColors = {
|
const logColors = {
|
||||||
INFO: "lime",
|
INFO: "lime",
|
||||||
DEBUG: "cyan",
|
DEBUG: "cyan",
|
||||||
|
CHAT: "cyan",
|
||||||
WARN: "yellow",
|
WARN: "yellow",
|
||||||
ERROR: "red"
|
ERROR: "red"
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user