mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-07-20 14:01:11 -04:00
Merge branch 'master' into dockerrewrite
This commit is contained in:
commit
ae0aa7e9ac
15
common.js
15
common.js
@ -419,4 +419,19 @@ module.exports.uniqueArray = function (a) {
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Replace placeholders in a string with values from an object or a function
|
||||
module.exports.replacePlaceholders = function (template, values) {
|
||||
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
||||
if (typeof values === 'function') {
|
||||
return values(key);
|
||||
}
|
||||
else if (values && typeof values === 'object') {
|
||||
return values[key] !== undefined ? values[key] : match;
|
||||
}
|
||||
else {
|
||||
return values !== undefined ? values : match;
|
||||
}
|
||||
});
|
||||
}
|
@ -168,7 +168,6 @@ RUN cd meshcentral && npm install
|
||||
# Expose needed ports
|
||||
EXPOSE 80 443
|
||||
|
||||
|
||||
# These volumes will be created by default even without any declaration, this allows default persistence in Docker/Podman.
|
||||
VOLUME /opt/meshcentral/meshcentral-data
|
||||
VOLUME /opt/meshcentral/meshcentral-files
|
||||
|
21
meshmail.js
21
meshmail.js
@ -116,6 +116,27 @@ module.exports.CreateMeshMail = function (parent, domain) {
|
||||
}
|
||||
}
|
||||
|
||||
// If no email template found, use the default translated email template
|
||||
if (((htmlfile == null) || (txtfile == null)) && (lang != null) && (lang != 'en')) {
|
||||
var translationsPath = obj.parent.path.join(obj.parent.webEmailsPath, 'translations');
|
||||
var translationsPathHtml = obj.parent.path.join(obj.parent.webEmailsPath, 'translations', name + '_' + lang + '.html');
|
||||
var translationsPathTxt = obj.parent.path.join(obj.parent.webEmailsPath, 'translations', name + '_' + lang + '.txt');
|
||||
if (obj.parent.fs.existsSync(translationsPath) && obj.parent.fs.existsSync(translationsPathHtml) && obj.parent.fs.existsSync(translationsPathTxt)) {
|
||||
htmlfile = obj.parent.fs.readFileSync(translationsPathHtml).toString();
|
||||
txtfile = obj.parent.fs.readFileSync(translationsPathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// If no translated email template found, use the default email template
|
||||
if ((htmlfile == null) || (txtfile == null)) {
|
||||
var pathHtml = obj.parent.path.join(obj.parent.webEmailsPath, name + '.html');
|
||||
var pathTxt = obj.parent.path.join(obj.parent.webEmailsPath, name + '.txt');
|
||||
if (obj.parent.fs.existsSync(pathHtml) && obj.parent.fs.existsSync(pathTxt)) {
|
||||
htmlfile = obj.parent.fs.readFileSync(pathHtml).toString();
|
||||
txtfile = obj.parent.fs.readFileSync(pathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// No email templates
|
||||
if ((htmlfile == null) || (txtfile == null)) { return null; }
|
||||
|
||||
|
@ -397,6 +397,7 @@ module.exports.CreateServer = function (parent) {
|
||||
function getTemplate(templateNumber, domain, lang) {
|
||||
parent.debug('email', 'Getting SMS template #' + templateNumber + ', lang: ' + lang);
|
||||
if (Array.isArray(lang)) { lang = lang[0]; } // TODO: For now, we only use the first language given.
|
||||
if (lang != null) { lang = lang.split('-')[0]; } // Take the first part of the language, "xx-xx"
|
||||
|
||||
var r = {}, emailsPath = null;
|
||||
if ((domain != null) && (domain.webemailspath != null)) { emailsPath = domain.webemailspath; }
|
||||
@ -404,7 +405,7 @@ module.exports.CreateServer = function (parent) {
|
||||
else if (obj.parent.webEmailsPath != null) { emailsPath = obj.parent.webEmailsPath; }
|
||||
if ((emailsPath == null) || (obj.parent.fs.existsSync(emailsPath) == false)) { return null }
|
||||
|
||||
// Get the non-english email if needed
|
||||
// Get the non-english sms if needed
|
||||
var txtfile = null;
|
||||
if ((lang != null) && (lang != 'en')) {
|
||||
var translationsPath = obj.parent.path.join(emailsPath, 'translations');
|
||||
@ -414,7 +415,7 @@ module.exports.CreateServer = function (parent) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get the english email
|
||||
// Get the english sms
|
||||
if (txtfile == null) {
|
||||
var pathTxt = obj.parent.path.join(emailsPath, 'sms-messages.txt');
|
||||
if (obj.parent.fs.existsSync(pathTxt)) {
|
||||
@ -422,6 +423,23 @@ module.exports.CreateServer = function (parent) {
|
||||
}
|
||||
}
|
||||
|
||||
// If no english sms and a non-english language is requested, try to get the default translated sms
|
||||
if (txtfile == null && (lang != null) && (lang != 'en')) {
|
||||
var translationsPath = obj.parent.path.join(obj.parent.webEmailsPath, 'translations');
|
||||
var translationsPathTxt = obj.parent.path.join(obj.parent.webEmailsPath, 'translations', 'sms-messages_' + lang + '.txt');
|
||||
if (obj.parent.fs.existsSync(translationsPath) && obj.parent.fs.existsSync(translationsPathTxt)) {
|
||||
txtfile = obj.parent.fs.readFileSync(translationsPathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// If no default translated sms, try to get the default english sms
|
||||
if (txtfile == null) {
|
||||
var pathTxt = obj.parent.path.join(obj.parent.webEmailsPath, 'sms-messages.txt');
|
||||
if (obj.parent.fs.existsSync(pathTxt)) {
|
||||
txtfile = obj.parent.fs.readFileSync(pathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// No email templates
|
||||
if (txtfile == null) { return null; }
|
||||
|
||||
|
@ -162,7 +162,19 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
try {
|
||||
if ((typeof obj.parent.config.domains[''].title == 'string') && (obj.parent.config.domains[''].title.length > 0)) {
|
||||
name = obj.parent.config.domains[''].title; info = '';
|
||||
try { if ((typeof obj.parent.config.domains[''].title2 == 'string') && (obj.parent.config.domains[''].title2.length > 0)) { info = obj.parent.config.domains[''].title2; } } catch (ex) { }
|
||||
try {
|
||||
if ((typeof obj.parent.config.domains[''].title2 == 'string') && (obj.parent.config.domains[''].title2.length > 0)) {
|
||||
info = obj.common.replacePlaceholders(obj.parent.config.domains[''].title2, {
|
||||
'serverversion': obj.parent.currentVer,
|
||||
'servername': obj.getWebServerName(domain, req),
|
||||
'agentsessions': Object.keys(parent.webserver.wsagents).length,
|
||||
'connectedusers': Object.keys(parent.webserver.wssessions).length,
|
||||
'userssessions': Object.keys(parent.webserver.wssessions2).length,
|
||||
'relaysessions': parent.webserver.relaySessionCount,
|
||||
'relaycount': Object.keys(parent.webserver.wsrelays).length
|
||||
});
|
||||
}
|
||||
} catch (ex) { }
|
||||
}
|
||||
} catch (ex) { }
|
||||
try {
|
||||
|
18
meshsms.js
18
meshsms.js
@ -169,6 +169,7 @@ module.exports.CreateMeshSMS = function (parent) {
|
||||
function getTemplate(templateNumber, domain, lang) {
|
||||
parent.debug('email', 'Getting SMS template #' + templateNumber + ', lang: ' + lang);
|
||||
if (Array.isArray(lang)) { lang = lang[0]; } // TODO: For now, we only use the first language given.
|
||||
if (lang != null) { lang = lang.split('-')[0]; } // Take the first part of the language, "xx-xx"
|
||||
|
||||
var r = {}, emailsPath = null;
|
||||
if ((domain != null) && (domain.webemailspath != null)) { emailsPath = domain.webemailspath; }
|
||||
@ -194,6 +195,23 @@ module.exports.CreateMeshSMS = function (parent) {
|
||||
}
|
||||
}
|
||||
|
||||
// If no english sms and a non-english language is requested, try to get the default translated sms
|
||||
if (txtfile == null && (lang != null) && (lang != 'en')) {
|
||||
var translationsPath = obj.parent.path.join(obj.parent.webEmailsPath, 'translations');
|
||||
var translationsPathTxt = obj.parent.path.join(obj.parent.webEmailsPath, 'translations', 'sms-messages_' + lang + '.txt');
|
||||
if (obj.parent.fs.existsSync(translationsPath) && obj.parent.fs.existsSync(translationsPathTxt)) {
|
||||
txtfile = obj.parent.fs.readFileSync(translationsPathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// If no default translated sms, try to get the default english sms
|
||||
if (txtfile == null) {
|
||||
var pathTxt = obj.parent.path.join(obj.parent.webEmailsPath, 'sms-messages.txt');
|
||||
if (obj.parent.fs.existsSync(pathTxt)) {
|
||||
txtfile = obj.parent.fs.readFileSync(pathTxt).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// No email templates
|
||||
if (txtfile == null) { return null; }
|
||||
|
||||
|
50
webserver.js
50
webserver.js
@ -3217,7 +3217,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
passRequirements: passRequirements,
|
||||
customui: customui,
|
||||
webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'),
|
||||
footer: (domain.footer == null) ? '' : domain.footer,
|
||||
footer: (domain.footer == null) ? '' : obj.common.replacePlaceholders(domain.footer, {
|
||||
'serverversion': obj.parent.currentVer,
|
||||
'servername': obj.getWebServerName(domain, req),
|
||||
'agentsessions': Object.keys(parent.webserver.wsagents).length,
|
||||
'connectedusers': Object.keys(parent.webserver.wssessions).length,
|
||||
'userssessions': Object.keys(parent.webserver.wssessions2).length,
|
||||
'relaysessions': parent.webserver.relaySessionCount,
|
||||
'relaycount': Object.keys(parent.webserver.wsrelays).length
|
||||
}),
|
||||
webstate: encodeURIComponent(webstate).replace(/'/g, '%27'),
|
||||
amtscanoptions: amtscanoptions,
|
||||
pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports(),
|
||||
@ -3462,12 +3470,29 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
sessiontime: (args.sessiontime) ? args.sessiontime : 60, // Session time in minutes, 60 minutes is the default
|
||||
passRequirements: passRequirements,
|
||||
customui: customui,
|
||||
footer: (domain.loginfooter == null) ? '' : domain.loginfooter,
|
||||
footer: (domain.loginfooter == null) ? '' : obj.common.replacePlaceholders(domain.loginfooter, {
|
||||
'serverversion': obj.parent.currentVer,
|
||||
'servername': obj.getWebServerName(domain, req),
|
||||
'agentsessions': Object.keys(parent.webserver.wsagents).length,
|
||||
'connectedusers': Object.keys(parent.webserver.wssessions).length,
|
||||
'userssessions': Object.keys(parent.webserver.wssessions2).length,
|
||||
'relaysessions': parent.webserver.relaySessionCount,
|
||||
'relaycount': Object.keys(parent.webserver.wsrelays).length
|
||||
}),
|
||||
hkey: encodeURIComponent(hardwareKeyChallenge).replace(/'/g, '%27'),
|
||||
messageid: msgid,
|
||||
flashErrors: JSON.stringify(flashErrors),
|
||||
passhint: passhint,
|
||||
welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null,
|
||||
|
||||
welcometext: domain.welcometext ? encodeURIComponent(obj.common.replacePlaceholders(domain.welcometext, {
|
||||
'serverversion': obj.parent.currentVer,
|
||||
'servername': obj.getWebServerName(domain, req),
|
||||
'agentsessions': Object.keys(parent.webserver.wsagents).length,
|
||||
'connectedusers': Object.keys(parent.webserver.wssessions).length,
|
||||
'userssessions': Object.keys(parent.webserver.wssessions2).length,
|
||||
'relaysessions': parent.webserver.relaySessionCount,
|
||||
'relaycount': Object.keys(parent.webserver.wsrelays).length
|
||||
})).split('\'').join('\\\'') : null,
|
||||
welcomePictureFullScreen: ((typeof domain.welcomepicturefullscreen == 'boolean') ? domain.welcomepicturefullscreen : false),
|
||||
hwstate: hwstate,
|
||||
otpemail: otpemail,
|
||||
@ -4208,7 +4233,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
if (typeof c.pid != 'string') { res.sendStatus(404); return; }
|
||||
|
||||
// Check the expired time, expire message.
|
||||
if ((c.e != null) && (c.e <= Date.now())) { render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
if ((c.e != null) && (c.e <= Date.now())) { res.status(404); render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
|
||||
obj.db.Get('deviceshare-' + c.pid, function (err, docs) {
|
||||
if ((err != null) || (docs == null) || (docs.length != 1)) { res.sendStatus(404); return; }
|
||||
@ -4254,17 +4279,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
// Serve the guest sharing page
|
||||
function handleSharingRequestEx(req, res, domain, c) {
|
||||
// Check the expired time, expire message.
|
||||
if ((c.expire != null) && (c.expire <= Date.now())) { render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
if ((c.expire != null) && (c.expire <= Date.now())) { res.status(404); render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
|
||||
// Check the public id
|
||||
obj.db.GetAllTypeNodeFiltered([c.nid], domain.id, 'deviceshare', null, function (err, docs) {
|
||||
// Check if any sharing links are present, expire message.
|
||||
if ((err != null) || (docs.length == 0)) { render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
if ((err != null) || (docs.length == 0)) { res.status(404); render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
|
||||
// Search for the device share public identifier, expire message.
|
||||
var found = false;
|
||||
for (var i = 0; i < docs.length; i++) { if ((docs[i].publicid == c.pid) && ((docs[i].extrakey == null) || (docs[i].extrakey === c.k))) { found = true; } }
|
||||
if (found == false) { render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
if (found == false) { res.status(404); render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
|
||||
// Get information about this node
|
||||
obj.db.Get(c.nid, function (err, nodes) {
|
||||
@ -4272,7 +4297,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
var node = nodes[0];
|
||||
|
||||
// Check the start time, not yet valid message.
|
||||
if ((c.start != null) && (c.expire != null) && ((c.start > Date.now()) || (c.start > c.expire))) { render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 11, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
if ((c.start != null) && (c.expire != null) && ((c.start > Date.now()) || (c.start > c.expire))) { res.status(404); render(req, res, getRenderPage((domain.sitestyle >= 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 11, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
|
||||
|
||||
// If this is a web relay share, check if this feature is active
|
||||
if ((c.p == 8) || (c.p == 16)) {
|
||||
@ -9360,6 +9385,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
xargs.title1 = domain.title1 ? domain.title1 : '';
|
||||
xargs.title2 = (domain.title1 && domain.title2) ? domain.title2 : '';
|
||||
}
|
||||
xargs.title2 = obj.common.replacePlaceholders(xargs.title2, {
|
||||
'serverversion': obj.parent.currentVer,
|
||||
'servername': obj.getWebServerName(domain, req),
|
||||
'agentsessions': Object.keys(parent.webserver.wsagents).length,
|
||||
'connectedusers': Object.keys(parent.webserver.wssessions).length,
|
||||
'userssessions': Object.keys(parent.webserver.wssessions2).length,
|
||||
'relaysessions': parent.webserver.relaySessionCount,
|
||||
'relaycount': Object.keys(parent.webserver.wsrelays).length
|
||||
});
|
||||
xargs.extitle = encodeURIComponent(xargs.title).split('\'').join('\\\'');
|
||||
xargs.domainurl = domain.url;
|
||||
xargs.autocomplete = (domain.autocomplete === false) ? 'autocomplete=off x' : 'autocomplete'; // This option allows autocomplete to be turned off on the login page.
|
||||
|
Loading…
x
Reference in New Issue
Block a user