Peering fixes, 404 page, new desktop special keys.

This commit is contained in:
Ylian Saint-Hilaire 2019-08-12 14:58:06 -07:00
parent 6e4c32a162
commit 72f04563d0
11 changed files with 260 additions and 31 deletions

View File

@ -387,13 +387,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// If we did not get an indication that the agent already validated this server, send the server signature.
if (obj.useSwarmCert == true) {
// Perform the hash signature using older swarm server certificate
parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, null, function (tag, signature) {
// Send back our certificate + signature
obj2.sendBinary(common.ShortToStr(2) + common.ShortToStr(parent.swarmCertificateAsn1.length) + parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
});
} else {
// Perform the hash signature using the server agent certificate
parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) {
// Send back our certificate + signature
obj2.sendBinary(common.ShortToStr(2) + common.ShortToStr(parent.agentCertificateAsn1.length) + parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
});

View File

@ -84,6 +84,10 @@ function CreateMeshCentralServer(config, args) {
if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/public'))) { obj.webPublicPath = obj.path.join(__dirname, '../meshcentral-web/public'); } else { obj.webPublicPath = obj.path.join(__dirname, 'public'); }
}
// Look to see if data and/or file path is specified
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
// Create data and files folders if needed
try { obj.fs.mkdirSync(obj.datapath); } catch (e) { }
try { obj.fs.mkdirSync(obj.filespath); } catch (e) { }
@ -555,10 +559,6 @@ function CreateMeshCentralServer(config, args) {
}, (obj.args.memorytracking * 1000));
}
// Look to see if data and/or file path is specified
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
// Read environment variables. For a subset of arguments, we allow them to be read from environment variables.
var xenv = ['user', 'port', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
for (i in xenv) { if ((obj.args[xenv[i]] == null) && (process.env['mesh' + xenv[i]])) { obj.args[xenv[i]] = obj.common.toNumber(process.env['mesh' + xenv[i]]); } }
@ -798,6 +798,7 @@ function CreateMeshCentralServer(config, args) {
// Setup Mesh Multi-Server if needed
obj.multiServer = require('./multiserver.js').CreateMultiServer(obj, obj.args);
if (obj.multiServer != null) {
if ((obj.db.databaseType != 3) || (obj.db.changeStream != true)) { console.log("ERROR: Multi-server support requires use of MongoDB with ReplicaSet and ChangeStream enabled."); process.exit(0); return; }
obj.serverId = obj.multiServer.serverid;
for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; }
}

View File

@ -152,7 +152,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (routing != null) {
// Check if we have permission to send a message to that node
var rights = user.links[routing.meshid];
var mesh = parent.meshes[agent.dbMeshKey];
var mesh = parent.meshes[routing.meshid];
if ((rights != null) && (mesh != null) && ((rights.rights & 8) || (rights.rights & 256))) { // 8 is remote control permission
command.fromSessionid = ws.sessionId; // Set the session id, required for responses
command.rights = rights.rights; // Add user rights flags to the message

View File

@ -46,6 +46,7 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.peerServerId = null;
obj.authenticated = 0;
obj.serverCertHash = null;
obj.pendingData = [];
// Disconnect from the server and/or stop trying
obj.stop = function () {
@ -88,7 +89,7 @@ module.exports.CreateMultiServer = function (parent, args) {
if (msg.length < 2) return;
if (msg.charCodeAt(0) == 123) {
if (obj.connectionState == 15) { processServerData(msg); }
if ((obj.connectionState & 4) != 0) { processServerData(msg); } else { obj.pendingData.push(msg); }
} else {
var cmd = obj.common.ReadShort(msg, 0);
switch (cmd) {
@ -101,9 +102,9 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.servernonce = msg.substring(50);
// Perform the hash signature using the server agent certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) {
// Send back our certificate + signature
obj2.ws.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
});
break;
@ -131,14 +132,22 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.parent.parent.debug(1, 'OutPeer ' + obj.serverid + ': Verified peer connection to ' + obj.url);
// Send information about our server to the peer
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); }
if (obj.connectionState == 15) {
obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 }));
for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); } // Process any pending data
obj.pendingData = [];
}
//if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); }
break;
}
case 4: {
// Server confirmed authentication, we are allowed to send commands to the server
// Peer server confirmed authentication, we are allowed to send commands to the server
obj.connectionState |= 8;
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); }
if (obj.connectionState == 15) {
obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 }));
for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); } // Process any pending data
obj.pendingData = [];
}
//if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); }
break;
}
@ -222,6 +231,7 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.infoSent = 0;
obj.peerServerId = null;
obj.serverCertHash = null;
obj.pendingData = [];
if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }
obj.parent.parent.debug(1, 'InPeer: Connected (' + obj.remoteaddr + ')');
@ -246,13 +256,10 @@ module.exports.CreateMultiServer = function (parent, args) {
if (typeof msg != 'string') { msg = msg.toString('binary'); }
if (msg.length < 2) return;
if (obj.authenticated >= 2) { // We are authenticated
if (msg.charCodeAt(0) == 123) { processServerData(msg); }
if (msg.charCodeAt(0) == 123) {
if (msg.length < 2) return;
//var cmdid = obj.common.ReadShort(msg, 0);
// Process binary commands (if any). None right now.
}
else if (obj.authenticated < 2) { // We are not authenticated
if (obj.authenticated >= 2) { processServerData(msg); } else { obj.pendingData.push(msg); }
} else if (obj.authenticated < 2) { // We are not authenticated
var cmd = obj.common.ReadShort(msg, 0);
if (cmd == 1) {
// Peer server authentication request
@ -264,9 +271,9 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.peernonce = msg.substring(50);
// Perform the hash signature using the server agent certificate
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) {
// Send back our certificate + signature
obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
});
// Check the peer server signature if we can
@ -319,6 +326,10 @@ module.exports.CreateMultiServer = function (parent, args) {
obj.send(obj.common.ShortToStr(4));
obj.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 }));
obj.authenticated = 2;
// Process any pending data that was received before peer authentication
for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); }
obj.pendingData = null;
}
// Verify the peer server signature
@ -371,9 +382,10 @@ module.exports.CreateMultiServer = function (parent, args) {
// If we have no peering configuration, don't setup this object
if (obj.peerConfig == null) { return null; }
obj.serverid = obj.parent.config.peers.serverId;
if (obj.serverid == null) { obj.serverid = require("os").hostname().toLowerCase(); }
obj.serverid = obj.parent.config.peers.serverid;
if (obj.serverid == null) { obj.serverid = require("os").hostname().toLowerCase(); } else { obj.serverid = obj.serverid.toLowerCase(); }
if (obj.parent.config.peers.servers[obj.serverid] == null) { console.log("Error: Unable to peer with other servers, \"" + obj.serverid + "\" not present in peer servers list."); return null; }
//console.log('Server peering ID: ' + obj.serverid);
// Return the private key of a peer server
obj.getServerCookieKey = function (serverid) {

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.3.9-p",
"version": "0.3.9-r",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -86,8 +86,15 @@ module.exports.CreateRedirServer = function (parent, db, args, func) {
obj.app.post(url + "amtevents.ashx", obj.parent.webserver.handleAmtEventRequest);
obj.app.get(url + "meshsettings", obj.parent.webserver.handleMeshSettingsRequest);
obj.app.get(url + "meshagents", obj.parent.webserver.handleMeshAgentRequest);
// Server redirects
if (parent.config.domains[i].redirects) {
for (var j in parent.config.domains[i].redirects) {
if (j[0] != '_') { obj.app.get(url + j, obj.parent.webserver.handleDomainRedirect); }
}
}
}
};
}
// Setup all HTTP redirection handlers
//obj.app.set("etag", false);

File diff suppressed because one or more lines are too long

View File

@ -512,6 +512,8 @@
<option value=7>Alt-F4</option>
<option value=8>Ctrl-W</option>
<option value=9>Alt-Tab</option>
<option value=11>Win+Left</option>
<option value=12>Win+Right</option>
</select>
<input id="DeskWD" type=button value="Send" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
<input id="DeskClip" style="" type="button" value="Clipboard" onkeypress="return false" onkeydown="return false" onclick="showDeskClip()">
@ -5056,6 +5058,18 @@
}
} else if (ks == 10) { // CTRL-ALT-DEL
desktop.m.sendcad();
} else if (ks == 11) { // WIN-LEFT
if (desktop.contype == 2) {
desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release
} else {
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
}
} else if (ks == 12) { // WIN-RIGHT
if (desktop.contype == 2) {
desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release
} else {
desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
}
}
}

View File

@ -0,0 +1,56 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="format-detection" content="telephone=no" />
<title>MeshCentral - Terms of use</title>
<style type="text/css">
a {
color: #036;
text-decoration: underline;
}
#footer a {
color: #fff;
text-decoration: underline;
}
#footer a:hover {
color: #fff;
text-decoration: none;
}
</style>
</head>
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
<div id="container">
<!-- Begin Masthead -->
<div id=masthead style="background:url(logo.png) 0px 0px;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px">
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
</div>
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
</div>
<p>{{{logoutControl}}}</p>
</div>
<div id=page_content style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
<div id="column_l" style="padding-left:10px;padding-right:10px">
<div style="text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb"><b>404</b></div>
<div style="text-align:center;font-size:16px;font-family:Arial;color:#999">This page does not exist</div>
<div style="text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999"><a href="/" style="text-decoration:none"><b>Go to main site</b></a></div>
</div>
</div>
<div id=footer style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
<table cellpadding=0 cellspacing=6 style=width:100%>
<tr>
<td style=text-align:left;color:white>{{{footer}}}</td>
<td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href="/">Back</a></td>
</tr>
</table>
</div>
</div>
</body>
</html>

133
views/error404.handlebars Normal file
View File

@ -0,0 +1,133 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="format-detection" content="telephone=no" />
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
<title>MeshCentral - Terms of use</title>
</head>
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
<div id="container">
<!-- Begin Masthead -->
<div id="masthead" class=noselect style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden;">
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
<strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
</div>
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
<strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
</div>
<p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;">{{{logoutControl}}}</p>
</div>
<div id="page_leftbar">
<div style="height:16px"></div>
</div>
<div id=topbar class="noselect style3" style="height:24px;position:relative">
<div id=uiMenuButton title="User interface selection" onclick="showUserInterfaceSelectMenu()">
&diams;
<div id=uiMenu style="display:none">
<div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class="uiSelector1"></div></div>
<div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class="uiSelector2"></div></div>
<div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class="uiSelector3"></div></div>
<div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class="uiSelector4"></div></div>
</div>
</div>
</div>
<div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
<div style="text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb"><b>404</b></div>
<div style="text-align:center;font-size:20px;font-family:Arial;color:#999">This page does not exist</div>
<div style="text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999"><a href="/" style="text-decoration:none"><b>Go to main site</b></a></div>
</div>
<div id="footer">
<table cellpadding="0" cellspacing="10" style="width: 100%">
<tr>
<td style="text-align:left"></td>
<td style="text-align:right"><a href="/">Back</a></td>
</tr>
</table>
</div>
</div>
<script>
'use strict';
var uiMode = parseInt(getstore('uiMode', 1));
var webPageStackMenu = false;
var webPageFullScreen = true;
var nightMode = (getstore('_nightMode', '0') == '1');
var terms = "{{{terms}}}";
if (terms != "") { QH('column_l', decodeURIComponent(terms)); }
QV('column_l', true);
userInterfaceSelectMenu();
// Toggle user interface menu
function showUserInterfaceSelectMenu() {
Q('uiViewButton1').classList.remove('uiSelectorSel');
Q('uiViewButton2').classList.remove('uiSelectorSel');
Q('uiViewButton3').classList.remove('uiSelectorSel');
Q('uiViewButton4').classList.remove('uiSelectorSel');
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
QV('uiMenu', (QS('uiMenu').display == 'none'));
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
}
function userInterfaceSelectMenu(s) {
if (s) { uiMode = s; putstore('uiMode', uiMode); }
webPageFullScreen = (uiMode < 3);
webPageStackMenu = true;//(uiMode > 1);
toggleFullScreen(0);
toggleStackMenu(0);
QC('column_l').add('room4submenu');
}
function toggleNightMode() {
nightMode = !nightMode;
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
putstore('_nightMode', nightMode ? '1' : '0');
}
// Toggle the web page to full screen
function toggleFullScreen(toggle) {
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
var hide = 0;
//if (args.hide) { hide = parseInt(args.hide); }
if (webPageFullScreen == false) {
QC('body').remove("menu_stack");
QC('body').remove("fullscreen");
QC('body').remove("arg_hide");
//if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
//QV('UserDummyMenuSpan', false);
//QV('page_leftbar', false);
} else {
QC('body').add("fullscreen");
if (hide & 16) QC('body').add("arg_hide"); // This is replacement for QV('page_leftbar', !(hide & 16));
//QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
//QV('page_leftbar', true);
}
QV('body', true);
}
// If FullScreen, toggle menu to be horisontal or vertical
function toggleStackMenu(toggle) {
if (webPageFullScreen == true) {
if (toggle === 1) {
webPageStackMenu = !webPageStackMenu;
putstore('webPageStackMenu', webPageStackMenu);
}
if (webPageStackMenu == false) {
QC('body').remove("menu_stack");
} else {
QC('body').add("menu_stack");
//if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
}
}
}
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
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; } }
</script>
</body>
</html>

View File

@ -1733,7 +1733,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}
// Handle domain redirection
function handleDomainRedirect(req, res) {
obj.handleDomainRedirect = function(req, res) {
const domain = checkUserIpAddress(req, res);
if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; }
var urlArgs = '', urlName = null, splitUrl = req.originalUrl.split("?");
@ -3041,7 +3041,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket);
// Server redirects
if (parent.config.domains[i].redirects) { for (var j in parent.config.domains[i].redirects) { if (j[0] != '_') { obj.app.get(url + j, handleDomainRedirect); } } }
if (parent.config.domains[i].redirects) { for (var j in parent.config.domains[i].redirects) { if (j[0] != '_') { obj.app.get(url + j, obj.handleDomainRedirect); } } }
// Server picture
obj.app.get(url + 'serverpic.ashx', function (req, res) {
@ -3106,6 +3106,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Indicates to ExpressJS that the public folder should be used to serve static files.
obj.app.use(url, obj.express.static(obj.parent.webPublicPath));
// Handle 404 error
obj.app.use(function (req, res, next) {
var domain = getDomain(req);
res.status(404).render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'error404-mobile' : 'error404'), { title: domain.title, title2: domain.title2 });
})
// Start regular disconnection list flush every 2 minutes.
obj.wsagentsDisconnectionsTimer = setInterval(function () { obj.wsagentsDisconnections = {}; }, 120000);
}
@ -3373,7 +3379,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; }
if (newcount != oldcount) {
x = userid.split('/');
var u = users[userid];
var u = obj.users[userid];
if (u) {
var targets = ['*', 'server-users'];
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }
@ -3387,7 +3393,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
oldcount = obj.sessionsCount[userid];
if ((oldcount != null) && (oldcount != 0)) {
x = userid.split('/');
var u = users[userid];
var u = obj.users[userid];
if (u) {
var targets = ['*', 'server-users'];
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }
@ -3412,7 +3418,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// If the count changed, update and event
if (newcount != oldcount) {
x = userid.split('/');
var u = users[userid];
var u = obj.users[userid];
if (u) {
var targets = ['*', 'server-users'];
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }