Added chat to device support, more fixes.

This commit is contained in:
Ylian Saint-Hilaire 2018-12-07 16:36:27 -08:00
parent 788a181d09
commit e236fae42e
16 changed files with 157 additions and 68 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -436,14 +436,23 @@ function createMeshCore(agent) {
break; break;
} }
case 'ps': { case 'ps': {
// Return the list of running processes
if (data.sessionid) { if (data.sessionid) {
processManager.getProcesses(function (plist) { mesh.SendCommand({ "action": "msg", "type": "ps", "value": JSON.stringify(plist), "sessionid": data.sessionid }); }); processManager.getProcesses(function (plist) { mesh.SendCommand({ "action": "msg", "type": "ps", "value": JSON.stringify(plist), "sessionid": data.sessionid }); });
} }
break; break;
} }
case 'pskill': { case 'pskill': {
//sendConsoleText(JSON.stringify(data)); // Kill a process
if (data.value) {
try { process.kill(data.value); } catch (e) { sendConsoleText(JSON.stringify(e)); } try { process.kill(data.value); } catch (e) { sendConsoleText(JSON.stringify(e)); }
}
break;
}
case 'openUrl': {
// Open a local web browser and return success/fail
sendConsoleText('OpenURL: ' + data.url);
if (data.url) { mesh.SendCommand({ "action": "msg", "type":"openUrl", "url": data.url, "sessionid": data.sessionid, "success": (openUserDesktopUrl(data.url) != null) }); }
break; break;
} }
} }
@ -477,6 +486,12 @@ function createMeshCore(agent) {
if (data.title && data.msg) { require('toaster').Toast(data.title, data.msg); } if (data.title && data.msg) { require('toaster').Toast(data.title, data.msg); }
break; break;
} }
case 'openUrl': {
// Open a local web browser and return success/fail
sendConsoleText('OpenURL: ' + data.url);
if (data.url) { mesh.SendCommand({ "action": "openUrl", "url": data.url, "sessionid": data.sessionid, "success": (openUserDesktopUrl(data.url) != null) }); }
break;
}
} }
} }
} }
@ -964,13 +979,32 @@ function createMeshCore(agent) {
response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; } response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; }
}; };
// Open a web browser to a specified URL on current user's desktop
function openUserDesktopUrl(url) {
var child = null;
try {
switch (process.platform) {
case 'win32':
child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ["/c", "start", url], { type: childProcess.SpawnTypes.USER });
break;
case 'linux':
child = require('child_process').execFile('/usr/bin/xdg-open', ['xdg-open', url], { type: require('child_process').SpawnTypes.DETACHED, uid: require('user-sessions').consoleUid() });
break;
case 'darwin':
child = require('child_process').execFile('/usr/bin/open', ['open', url], { uid: require('user-sessions').consoleUid() });
break;
}
} catch (ex) { }
return child;
}
// Process a mesh agent console command // Process a mesh agent console command
function processConsoleCommand(cmd, args, rights, sessionid) { function processConsoleCommand(cmd, args, rights, sessionid) {
try { try {
var response = null; var response = null;
switch (cmd) { switch (cmd) {
case 'help': { // Displays available commands case 'help': { // Displays available commands
response = 'Available commands: help, info, osinfo, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios, toast, lock, users, sendcaps.'; response = 'Available commands: help, info, osinfo,args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios, toast, lock, users, sendcaps, openurl.';
break; break;
} }
/* /*
@ -992,6 +1026,11 @@ function createMeshCore(agent) {
} }
break; break;
*/ */
case 'openurl': {
if (args['_'].length != 1) { response = 'Proper usage: openurl (url)'; } // Display usage
else { if (openUserDesktopUrl(args['_'][0]) == null) { response = 'Failed.'; } else { response = 'Success.'; } }
break;
}
case 'users': { case 'users': {
if (meshCoreObj.users == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + meshCoreObj.users.join(', ') + '.'; } if (meshCoreObj.users == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + meshCoreObj.users.join(', ') + '.'; }
break; break;
@ -1520,7 +1559,7 @@ function createMeshCore(agent) {
//amtLms.on('bind', function (map) { }); //amtLms.on('bind', function (map) { });
amtLms.on('notify', function (data, options, str, code) { amtLms.on('notify', function (data, options, str, code) {
if (code == 'iAMT0052-3') { if (code == 'iAMT0052-3') {
kvmGetData(); obj.kvmGetData();
} else { } else {
//if (str != null) { sendConsoleText('Intel AMT LMS: ' + str); } //if (str != null) { sendConsoleText('Intel AMT LMS: ' + str); }
handleAmtNotification(data); handleAmtNotification(data);

View File

@ -88,8 +88,10 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
obj.digest.http = require('http'); obj.digest.http = require('http');
} }
var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port, rejectUnauthorized: false, checkServerIdentity: function (cert) { console.log('checkServerIdentity', JSON.stringify(cert)); } }; var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port, rejectUnauthorized: false, checkServerIdentity: function (cert) { console.log('checkServerIdentity', JSON.stringify(cert)); } };
var req = obj.digest.request(request); var req = obj.digest.request(request);
//console.log('Request ' + (obj.RequestCount++)); //console.log('Request ' + (obj.RequestCount++));
req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); }); req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
req.on('response', function (response) { req.on('response', function (response) {
//console.log('Response: ' + response.statusCode); //console.log('Response: ' + response.statusCode);
@ -105,6 +107,7 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
// Send POST body, this work with binary. // Send POST body, this work with binary.
req.end(postdata); req.end(postdata);
obj.ActiveAjaxCount++; obj.ActiveAjaxCount++;
return req; return req;
} }

View File

@ -98,7 +98,14 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
if (obj.id.startsWith('meshmessenger/')) { if (obj.id.startsWith('meshmessenger/')) {
if (obj.user == null) { try { obj.close(); } catch (e) { } return null; } if (obj.user == null) { try { obj.close(); } catch (e) { } return null; }
var x = obj.id.split('/'), user1 = x[1] + '/' + x[2] + '/' + x[3], user2 = x[4] + '/' + x[5] + '/' + x[6]; var x = obj.id.split('/'), user1 = x[1] + '/' + x[2] + '/' + x[3], user2 = x[4] + '/' + x[5] + '/' + x[6];
if ((x[1] != 'user') && (x[4] != 'user')) { try { obj.close(); } catch (e) { } return null; } // MeshMessenger session must have at least one authenticated user
if ((x[1] == 'user') && (x[4] == 'user')) {
// If this is a user-to-user session, you must be authenticated to join.
if ((obj.user._id != user1) && (obj.user._id != user2)) { try { obj.close(); } catch (e) { } return null; } if ((obj.user._id != user1) && (obj.user._id != user2)) { try { obj.close(); } catch (e) { } return null; }
} else {
// If only one side of the session is a user
// !!!!! TODO: Need to make sure that one of the two sides is the correct user. !!!!!
}
} }
// Validate that the id is valid, we only need to do this on non-authenticated sessions. // Validate that the id is valid, we only need to do this on non-authenticated sessions.

View File

@ -76,6 +76,40 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
ds.on('close', function () { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); }); ds.on('close', function () { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); });
} }
// Route a command to a target node
function routeCommandToNode(command) {
if (obj.common.validateString(command.nodeid, 8, 128) == false) return false;
var splitnodeid = command.nodeid.split('/');
// Check that we are in the same domain and the user has rights over this node.
if ((splitnodeid[0] == 'node') && (splitnodeid[1] == domain.id)) {
// See if the node is connected
var agent = obj.parent.wsagents[command.nodeid];
if (agent != null) {
// Check if we have permission to send a message to that node
var rights = user.links[agent.dbMeshKey];
if ((rights != null) && ((rights.rights & 8) || (rights.rights & 256))) { // 8 is remote control permission, 256 is desktop read only
command.sessionid = ws.sessionId; // Set the session id, required for responses.
command.rights = rights.rights; // Add user rights flags to the message
delete command.nodeid; // Remove the nodeid since it's implyed.
try { agent.send(JSON.stringify(command)); } catch (ex) { }
}
} else {
// Check if a peer server is connected to this agent
var routing = obj.parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
if (routing != null) {
// Check if we have permission to send a message to that node
var rights = user.links[routing.meshid];
if ((rights != 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
obj.parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
}
}
}
}
return true;
}
try { try {
// Check if the user is logged in // Check if the user is logged in
if (user == null) { try { obj.ws.close(); } catch (e) { } return; } if (user == null) { try { obj.ws.close(); } catch (e) { } return; }
@ -303,37 +337,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
} }
case 'msg': case 'msg':
{ {
// Route a message. // Route this command to a target node
// This this command has a nodeid, that is the target. routeCommandToNode(command);
if (obj.common.validateString(command.nodeid, 8, 128) == false) return;
var splitnodeid = command.nodeid.split('/');
// Check that we are in the same domain and the user has rights over this node.
if ((splitnodeid[0] == 'node') && (splitnodeid[1] == domain.id)) {
// See if the node is connected
var agent = obj.parent.wsagents[command.nodeid];
if (agent != null) {
// Check if we have permission to send a message to that node
var rights = user.links[agent.dbMeshKey];
if ((rights != null) && ((rights.rights & 8) || (rights.rights & 256))) { // 8 is remote control permission, 256 is desktop read only
command.sessionid = ws.sessionId; // Set the session id, required for responses.
command.rights = rights.rights; // Add user rights flags to the message
delete command.nodeid; // Remove the nodeid since it's implyed.
try { agent.send(JSON.stringify(command)); } catch (ex) { }
}
} else {
// Check if a peer server is connected to this agent
var routing = obj.parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
if (routing != null) {
// Check if we have permission to send a message to that node
var rights = user.links[routing.meshid];
if ((rights != 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
obj.parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
}
}
}
}
break; break;
} }
case 'events': case 'events':
@ -601,11 +606,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
{ {
// Send a notification message to a user // Send a notification message to a user
if ((user.siteadmin & 2) == 0) break; if ((user.siteadmin & 2) == 0) break;
if (obj.common.validateString(command.userid, 1, 2048) == false) break;
// Setup a user-to-user session
if (obj.common.validateString(command.userid, 1, 2048)) {
// Create the notification message // Create the notification message
var notification = { var notification = {
"action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: Chat Request, Click here to accept.", "userid": user._id, "username": user.name, "tag": 'meshmessenger/' + encodeURIComponent(command.userid) + '/' + encodeURIComponent(user._id) }; "action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: Chat Request, Click here to accept.", "userid": user._id, "username": user.name, "tag": 'meshmessenger/' + encodeURIComponent(command.userid) + '/' + encodeURIComponent(user._id)
};
// Get the list of sessions for this user // Get the list of sessions for this user
var sessions = obj.parent.wssessions[command.userid]; var sessions = obj.parent.wssessions[command.userid];
@ -614,6 +622,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (obj.parent.parent.multiServer != null) { if (obj.parent.parent.multiServer != null) {
// TODO: Add multi-server support // TODO: Add multi-server support
} }
}
// Setup a user-to-node session
if (obj.common.validateString(command.nodeid, 1, 2048)) {
if (obj.args.lanonly == true) { return; } // User-to-device chat is not support in LAN-only mode yet. We need the agent to replace the IP address of the server??
// Create the server url
var httpsPort = ((obj.parent.args.aliasport == null) ? obj.parent.args.port : obj.parent.args.aliasport); // Use HTTPS alias port is specified
var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/";
var url = "http" + (obj.args.notls ? '' : 's') + "://" + obj.parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger.htm?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name);
// Create the notification message
routeCommandToNode({ "action": "openUrl", "nodeid": command.nodeid, "userid": user._id, "username": user.name, "url": url });
}
break; break;
} }
case 'serverversion': case 'serverversion':

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.2.4-b", "version": "0.2.4-e",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

BIN
public/images/icon-url.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

BIN
public/images/icon-url2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

View File

@ -447,8 +447,11 @@
<td style=padding-top:2px;padding-bottom:2px;background:#C0C0C0> <td style=padding-top:2px;padding-bottom:2px;background:#C0C0C0>
<div style=float:right;text-align:right> <div style=float:right;text-align:right>
<select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp; <select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp;
<input id=DeskToastButton type=button value=Toast title="Display a notification message on the remote computer" onkeypress="return false" onkeydown="return false" onclick="deviceToastFunction()">&nbsp; <!--<input id=DeskToastButton type=button value=Toast title="Display a notification message on the remote computer" onkeypress="return false" onkeydown="return false" onclick="deviceToastFunction()">&nbsp;-->
<input id=DeskToolsButton type=button value=Tools title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp; <input id=DeskToolsButton type=button value=Tools title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;
<span style="float:right;margin-top:1px;margin-right:4px;cursor:pointer" title="Open chat window to this computer"><a onclick=deviceChat()><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>
<span style="float:right;margin-top:1px;margin-right:4px;cursor:pointer" title="Display a notification on the remote computer"><a onclick=deviceToastFunction()><img src='images/icon-notify.png' height=16 width=16 style=padding-top:2px /></a></span>
<span style="float:right;margin-top:1px;margin-right:4px;cursor:pointer" title="Open a web address on remote computer"><a onclick=deviceUrlFunction()><img src='images/icon-url2.png' height=16 width=16 style=padding-top:2px /></a></span>
</div> </div>
<div> <div>
<select style="margin-left:6px" id="deskkeys"> <select style="margin-left:6px" id="deskkeys">
@ -3229,7 +3232,6 @@
if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a style=cursor:pointer onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a>&nbsp;'; if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a style=cursor:pointer onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a>&nbsp;';
// RDP link, show this link only of the remote machine is Windows. // RDP link, show this link only of the remote machine is Windows.
console.log(((connectivity & 1) != 0), (clickOnce == true), (mesh.mtype == 2), ((meshrights & 8) != 0));
if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) { if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","RDP2",3389) title="Requires Microsoft ClickOnce support in your browser.">RDP</a>&nbsp;'; } if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","RDP2",3389) title="Requires Microsoft ClickOnce support in your browser.">RDP</a>&nbsp;'; }
if (node.agent.id > 4) { if (node.agent.id > 4) {
@ -3312,9 +3314,24 @@
function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); } function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
function deviceChat() {
if (xxdialogMode) return;
window.open('/messenger.htm?id=meshmessenger/' + encodeURIComponent(currentNode._id) + '/' + encodeURIComponent(userinfo._id) + '&title=' + currentNode.name, 'meshmessenger:' + currentNode._id);
meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) });
}
function deviceUrlFunction() {
if (xxdialogMode) return;
setDialogMode(2, "Open Page on Device", 3, deviceUrlFunctionEx, '<input id=d2devurl placeholder="http://server.com" style=width:100%;overflow-y:scroll></input>');
}
function deviceUrlFunctionEx() {
meshserver.send({ action: 'msg', type: 'openUrl', nodeid: currentNode._id, url: Q('d2devurl').value });
}
function deviceToastFunction() { function deviceToastFunction() {
if (xxdialogMode) return; if (xxdialogMode) return;
setDialogMode(2, "Device Toast", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>'); setDialogMode(2, "Device Notification", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
} }
function deviceToastFunctionEx() { function deviceToastFunctionEx() {
@ -5727,11 +5744,10 @@
if (sessions != null) { if (sessions != null) {
gray = ''; gray = '';
if (self) { if (self) {
msg2 = "<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Chat><a onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>"; msg2 = "<span style=float:right;margin-top:1px;margin-right:4px title=Chat><a onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>";
msg += "<a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; msg2 += "<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Notify><a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")><img src='images/icon-notify.png' height=16 width=16 style=padding-top:2px /></a></span>";
} }
if (sessions == 1) { msg += '1 active session'; } else { msg += sessions + ' active sessions'; } if (sessions == 1) { msg += '1 active session'; } else { msg += sessions + ' active sessions'; }
if (self) { msg += "</a>"; }
} else { } else {
if (user.login) { msg += '<span title="Last login: ' + new Date(user.login).toLocaleString() + '">' + new Date(user.login).toLocaleDateString() + '</span>'; } if (user.login) { msg += '<span title="Last login: ' + new Date(user.login).toLocaleString() + '">' + new Date(user.login).toLocaleDateString() + '</span>'; }
} }

View File

@ -755,14 +755,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (obj.args.minify && !req.query.nominify) { if (obj.args.minify && !req.query.nominify) {
// Try to server the minified version if we can. // Try to server the minified version if we can.
try { try {
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile-min' : 'views/default-min'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile-min' : 'views/default-min'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: 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, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
} catch (ex) { } catch (ex) {
// In case of an exception, serve the non-minified version. // In case of an exception, serve the non-minified version.
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: 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, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
} }
} else { } else {
// Serve non-minified version of web pages. // Serve non-minified version of web pages.
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: 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, webcerthash: new Buffer(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
} }
} else { } else {
// Send back the login application // Send back the login application
@ -775,18 +775,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (obj.args.minify && !req.query.nominify) { if (obj.args.minify && !req.query.nominify) {
// Try to server the minified version if we can. // Try to server the minified version if we can.
try { try {
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile-min' : 'views/login-min'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile-min' : 'views/login-min'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer });
} catch (ex) { } catch (ex) {
// In case of an exception, serve the non-minified version. // In case of an exception, serve the non-minified version.
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer });
} }
} else { } else {
// Serve non-minified version of web pages. // Serve non-minified version of web pages.
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer }); res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, footer: (domain.footer == null) ? '' : domain.footer });
} }
/* /*
var xoptions = { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer }; var xoptions = { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer };
var xpath = obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'); var xpath = obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login');
console.log('Render...'); console.log('Render...');
res.render(xpath, xoptions, function (err, html) { res.render(xpath, xoptions, function (err, html) {
@ -1272,8 +1272,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
ws.on('error', function (err) { console.log('WEBSERVER WSERR2: ' + err); }); ws.on('error', function (err) { console.log('WEBSERVER WSERR2: ' + err); });
// If the web socket is closed, close the associated TCP connection. // If the web socket is closed, close the associated TCP connection.
ws.on('close', function (req) { ws.on('close', function () {
Debug(1, 'Closing relay web socket connection to ' + ws.upgradeReq.query.host + '.'); Debug(1, 'Closing relay web socket connection to ' + req.query.host + '.');
if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } } if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } }
}); });
@ -1550,7 +1550,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
var xdomain = (domain.dns == null) ? domain.id : ''; var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/"; if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n"; var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; } if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + obj.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; } if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; } if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; }
@ -1612,7 +1612,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}; };
if (user != null) { meshaction.username = user.name; } if (user != null) { meshaction.username = user.name; }
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' }); res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' });
res.send(JSON.stringify(meshaction, null, ' ')); res.send(JSON.stringify(meshaction, null, ' '));
}); });
@ -1627,7 +1627,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}; };
if (user != null) { meshaction.username = user.name; } if (user != null) { meshaction.username = user.name; }
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' }); res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' });
res.send(JSON.stringify(meshaction, null, ' ')); res.send(JSON.stringify(meshaction, null, ' '));
} else { } else {
@ -1650,7 +1650,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
}; };
// Get the web server hostname. This may change if using a domain with a DNS name. // Get the web server hostname. This may change if using a domain with a DNS name.
function getWebServerName(domain) { obj.getWebServerName = function(domain) {
if (domain.dns != null) return domain.dns; if (domain.dns != null) return domain.dns;
return obj.certificates.CommonName; return obj.certificates.CommonName;
} }
@ -1688,7 +1688,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
var xdomain = (domain.dns == null) ? domain.id : ''; var xdomain = (domain.dns == null) ? domain.id : '';
if (xdomain != '') xdomain += "/"; if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n"; var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; } if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + obj.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; } if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; } if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; }
@ -1769,7 +1769,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (xdomain != '') xdomain += "/"; if (xdomain != '') xdomain += "/";
var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n"; var meshsettings = "MeshName=" + mesh.name + "\r\nMeshType=" + mesh.mtype + "\r\nMeshID=0x" + meshidhex + "\r\nServerID=" + serveridhex + "\r\n";
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; } if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + obj.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; }
if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; } if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; }
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; } if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; }