Added user web state filtering.
Ylian Saint-Hilaire committed
Oct 25, 2019 at 14:41 UTC
fb9350e9a3339b561b95fc66580c1ef50c3d54d5
6 files changed
+92
-9
meshuser.js
+1
@@ -2881,6 +2881,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2881
}
2882
case 'userWebState': {
2883
if (common.validateString(command.state, 1, 10000) == false) break; // Check state size, no more than 10k
2884
+ command.state = parent.filterUserWebState(command.state); // Filter the state to remove anything bad
2885
db.Set({ _id: 'ws' + user._id, state: command.state });
2886
parent.parent.DispatchEvent([user._id], obj, { action: 'userWebState', nolog: 1, domain: domain.id, state: command.state });
2887
break;
views/default-min.handlebars
+17
-2
@@ -3705,7 +3705,7 @@
3705
var x = '';
3706
if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
3707
x += '<br /><br />';
3708
- if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connect for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3708
+ if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3709
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
3710
setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
3711
p10validateSendUninstallAgentDialog();
@@ -8333,7 +8333,22 @@
8333
8334
// Generic methods
8335
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
8336
- function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
8336
+ function putstore(name, val) {
8337
+ try {
8338
+ if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return;
8339
+ if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { }
8340
+ if (name[0] != '_') {
8341
+ var s = {};
8342
+ for (var i = 0, len = localStorage.length; i < len; ++i) {
8343
+ var k = localStorage.key(i);
8344
+ if (k[0] != '_') {
8345
+ s[k] = localStorage.getItem(k);
8346
+ if ((k != 'desktopsettings') && (typeof s[k] == 'string') && (s[k].length > 64)) { delete s[k]; }
8347
+ }
8348
+ }
8349
+ meshserver.send({ action: 'userWebState', state: JSON.stringify(s) });
8350
+ }
8351
+ }
8352
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
8353
function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
8354
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
views/default.handlebars
+16
-1
@@ -9315,7 +9315,22 @@
9315
9316
// Generic methods
9317
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
9318
- function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
9318
+ function putstore(name, val) {
9319
+ try {
9320
+ if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return;
9321
+ if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { }
9322
+ if (name[0] != '_') {
9323
+ var s = {};
9324
+ for (var i = 0, len = localStorage.length; i < len; ++i) {
9325
+ var k = localStorage.key(i);
9326
+ if (k[0] != '_') {
9327
+ s[k] = localStorage.getItem(k);
9328
+ if ((k != 'desktopsettings') && (typeof s[k] == 'string') && (s[k].length > 64)) { delete s[k]; }
9329
+ }
9330
+ }
9331
+ meshserver.send({ action: 'userWebState', state: JSON.stringify(s) });
9332
+ }
9333
+ }
9334
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
9335
function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
9336
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
views/translations/default-min_fr.handlebars
+17
-2
@@ -3705,7 +3705,7 @@
3705
var x = '';
3706
if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
3707
x += '<br /><br />';
3708
- if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connect for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3708
+ if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
3709
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
3710
setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
3711
p10validateSendUninstallAgentDialog();
@@ -8333,7 +8333,22 @@
8333
8334
// Generic methods
8335
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
8336
- function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
8336
+ function putstore(name, val) {
8337
+ try {
8338
+ if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return;
8339
+ if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { }
8340
+ if (name[0] != '_') {
8341
+ var s = {};
8342
+ for (var i = 0, len = localStorage.length; i < len; ++i) {
8343
+ var k = localStorage.key(i);
8344
+ if (k[0] != '_') {
8345
+ s[k] = localStorage.getItem(k);
8346
+ if ((k != 'desktopsettings') && (typeof s[k] == 'string') && (s[k].length > 64)) { delete s[k]; }
8347
+ }
8348
+ }
8349
+ meshserver.send({ action: 'userWebState', state: JSON.stringify(s) });
8350
+ }
8351
+ }
8352
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
8353
function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
8354
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
views/translations/default_fr.handlebars
+17
-2
@@ -4685,7 +4685,7 @@
4685
var x = '';
4686
if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
4687
x += '<br /><br />';
4688
- if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connect for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
4688
+ if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
4689
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
4690
setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
4691
p10validateSendUninstallAgentDialog();
@@ -9313,7 +9313,22 @@
9313
9314
// Generic methods
9315
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
9316
- function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
9316
+ function putstore(name, val) {
9317
+ try {
9318
+ if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return;
9319
+ if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { }
9320
+ if (name[0] != '_') {
9321
+ var s = {};
9322
+ for (var i = 0, len = localStorage.length; i < len; ++i) {
9323
+ var k = localStorage.key(i);
9324
+ if (k[0] != '_') {
9325
+ s[k] = localStorage.getItem(k);
9326
+ if ((k != 'desktopsettings') && (typeof s[k] == 'string') && (s[k].length > 64)) { delete s[k]; }
9327
+ }
9328
+ }
9329
+ meshserver.send({ action: 'userWebState', state: JSON.stringify(s) });
9330
+ }
9331
+ }
9332
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
9333
function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
9334
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
webserver.js
+24
-2
@@ -1527,8 +1527,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1527
// Fetch the web state
1528
parent.debug('web', 'handleRootRequestEx: success.');
1529
obj.db.Get('ws' + user._id, function (err, states) {
1530
- var webstate = (states.length == 1) ? states[0].state : '';
1531
- render(req, res, getRenderPage('default', req), { authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, extitle: encodeURIComponent(domain.title), extitle2: encodeURIComponent(domain.title2), domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null)?'null':parent.pluginHandler.prepExports() });
1530
+ var webstate = (states.length == 1) ? obj.filterUserWebState(states[0].state) : '';
1531
+ render(req, res, getRenderPage('default', req), { authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, extitle: encodeURIComponent(domain.title), extitle2: encodeURIComponent(domain.title2), domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports() });
1532
});
1533
} else {
1534
// Send back the login application
@@ -3757,6 +3757,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3757
return r;
3758
}
3759
3760
+ // Filter the user web site and only output state that we need to keep
3761
+ const acceptableUserWebStateStrings = ['webPageStackMenu', 'notifications', 'deviceView', 'nightMode', 'webPageFullScreen', 'search', 'showRealNames', 'sort', 'deskAspectRatio', 'viewsize', 'DeskControl', 'uiMode'];
3762
+ const acceptableUserWebStateDesktopStrings = ['encoding', 'showfocus', 'showmouse', 'showcad', 'limitFrameRate', 'noMouseRotate', 'quality', 'scaling']
3763
+ obj.filterUserWebState = function (state) {
3764
+ if (typeof state == 'string') { try { state = JSON.parse(state); } catch (ex) { return null; } }
3765
+ var out = {};
3766
+ for (var i in acceptableUserWebStateStrings) {
3767
+ var n = acceptableUserWebStateStrings[i];
3768
+ if ((state[n] != null) && ((typeof state[n] == 'number') || (typeof state[n] == 'boolean') || ((typeof state[n] == 'string') && (state[n].length < 32)))) { out[n] = state[n]; }
3769
+ }
3770
+ if (typeof state.desktopsettings == 'string') { try { state.desktopsettings = JSON.parse(state.desktopsettings); } catch (ex) { delete state.desktopsettings; } }
3771
+ if (state.desktopsettings != null) {
3772
+ out.desktopsettings = {};
3773
+ for (var i in acceptableUserWebStateDesktopStrings) {
3774
+ var n = acceptableUserWebStateDesktopStrings[i];
3775
+ if ((state.desktopsettings[n] != null) && ((typeof state.desktopsettings[n] == 'number') || (typeof state.desktopsettings[n] == 'boolean') || ((typeof state.desktopsettings[n] == 'string') && (state.desktopsettings[n].length < 32)))) { out.desktopsettings[n] = state.desktopsettings[n]; }
3776
+ }
3777
+ out.desktopsettings = JSON.stringify(out.desktopsettings);
3778
+ }
3779
+ return JSON.stringify(out);
3780
+ }
3781
+
3782
// Return the correct render page given mobile, minify and override path.
3783
function getRenderPage(pagename, req) {
3784
var mobile = isMobileBrowser(req), minify = obj.args.minify && !req.query.nominify, p;