New agents, NeDB encryption, WebApp Fixes.

This commit is contained in:
Ylian Saint-Hilaire 2019-01-24 12:08:48 -08:00
parent 35e8f9b94a
commit 110b58cd58
35 changed files with 90 additions and 7437 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@ -653,7 +653,7 @@ function UserSessions()
}
this.consoleUid = function consoleUid()
{
var checkstr = process.platform == 'darwin' ? 'console' : process.env['DISPLAY'];
var checkstr = process.platform == 'darwin' ? 'console' : ((process.env['DISPLAY'])?process.env['DISPLAY']:':0')
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });

File diff suppressed because one or more lines are too long

View File

@ -653,7 +653,7 @@ function UserSessions()
}
this.consoleUid = function consoleUid()
{
var checkstr = process.platform == 'darwin' ? 'console' : process.env['DISPLAY'];
var checkstr = process.platform == 'darwin' ? 'console' : ((process.env['DISPLAY'])?process.env['DISPLAY']:':0')
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

28
db.js
View File

@ -31,6 +31,7 @@ module.exports.CreateDB = function (parent) {
obj.path = require('path');
obj.parent = parent;
obj.identifier = null;
obj.dbKey = null;
if (obj.parent.args.mongodb) {
// Use MongoDB
@ -44,7 +45,32 @@ module.exports.CreateDB = function (parent) {
// Use NeDB (The default)
obj.databaseType = 1;
Datastore = require('nedb');
obj.file = new Datastore({ filename: obj.parent.getConfigFilePath('meshcentral.db'), autoload: true });
var datastoreOptions = { filename: obj.parent.getConfigFilePath('meshcentral.db'), autoload: true };
// If a DB encryption key is provided, perform database encryption
if (typeof obj.parent.args.dbencryptkey == 'string') {
// Hash the database password into a AES256 key and setup encryption and decryption.
obj.dbKey = obj.parent.crypto.createHash('sha384').update(obj.parent.args.dbencryptkey).digest("raw").slice(0, 32);
datastoreOptions.afterSerialization = function (plaintext) {
const iv = obj.parent.crypto.randomBytes(16);
const aes = obj.parent.crypto.createCipheriv('aes-256-cbc', obj.dbKey, iv);
var ciphertext = aes.update(plaintext);
ciphertext = Buffer.concat([iv, ciphertext, aes.final()]);
return ciphertext.toString('base64');
}
datastoreOptions.beforeDeserialization = function (ciphertext) {
const ciphertextBytes = Buffer.from(ciphertext, 'base64');
const iv = ciphertextBytes.slice(0, 16);
const data = ciphertextBytes.slice(16);
const aes = obj.parent.crypto.createDecipheriv('aes-256-cbc', obj.dbKey, iv);
var plaintextBytes = Buffer.from(aes.update(data));
plaintextBytes = Buffer.concat([plaintextBytes, aes.final()]);
return plaintextBytes.toString();
}
}
// Start NeDB
obj.file = new Datastore(datastoreOptions);
obj.file.persistence.setAutocompactionInterval(3600);
}

View File

@ -716,6 +716,12 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
});
break;
}
case 'openUrl':
{
// Sent by the agent to return the status of a open URL action.
// Nothing is done right now.
break;
}
default: {
console.log('Unknown agent action (' + obj.remoteaddrport + '): ' + command.action + '.');
break;

View File

@ -65,9 +65,13 @@ function CreateMeshCentralServer(config, args) {
if ((__dirname.endsWith('/node_modules/meshcentral')) || (__dirname.endsWith('\\node_modules\\meshcentral')) || (__dirname.endsWith('/node_modules/meshcentral/')) || (__dirname.endsWith('\\node_modules\\meshcentral\\'))) {
obj.datapath = obj.path.join(__dirname, '../../meshcentral-data');
obj.filespath = obj.path.join(__dirname, '../../meshcentral-files');
if (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web/views'))) { obj.webViewsPath = obj.path.join(__dirname, '../../meshcentral-web/views'); } else { obj.webViewsPath = obj.path.join(__dirname, 'views'); }
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'); }
} else {
obj.datapath = obj.path.join(__dirname, '../meshcentral-data');
obj.filespath = obj.path.join(__dirname, '../meshcentral-files');
if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/views'))) { obj.webViewsPath = obj.path.join(__dirname, '../meshcentral-web/views'); } else { obj.webViewsPath = obj.path.join(__dirname, 'views'); }
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'); }
}
// Create data and files folders if needed

View File

@ -96,7 +96,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
// If this is a MeshMessenger session, the ID is the two userid's and authentication must match one of them.
if (obj.id.startsWith('meshmessenger/')) {
if (obj.user == null) { try { obj.close(); } catch (e) { } return null; }
if ((obj.id.startsWith('meshmessenger/user/') == true) && (obj.user == null)) { try { obj.close(); } catch (e) { } return null; } // If user-to-user, both sides need to be authenticated.
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')) {

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.2.6-v",
"version": "0.2.6-w",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -250,8 +250,8 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
if (obj.onMessage != null) obj.onMessage(str.substring(4, cmdsize), obj);
break;
case 65: // Alert
console.error(str.substring(4));
alert(str.substring(4));
str = str.substring(4);
if (str[0] != '.') { console.log(str); alert('KVM: ' + str); } else { console.log('KVM: ' + str.substring(1)); }
break;
}
return cmdsize;

View File

@ -1,745 +0,0 @@
body {
margin: 0;
padding: 0;
border: 0;
color: black;
font-size: 13px;
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
background-color: #d3d9d6;
}
#container {
background-color: #fff;
width: 960px;
min-width: 960px;
margin: 0 auto;
border-top: 0;
border-right: 1px solid #b7b7b7;
border-bottom: 0;
border-left: 1px solid #b7b7b7;
padding: 0;
}
#masthead {
width: auto;
margin: 0;
padding: 0;
overflow: auto;
text-align: right;
background-color: #036;
width: 960px;
}
#column_l {
position: relative;
float: left;
width: 930px;
margin: 0;
padding: 0 15px;
background-color: #fff;
}
#footer {
clear: both;
overflow: auto;
width: 100%;
text-align: center;
background-color: #113962;
padding-top: 5px;
padding-bottom: 5px;
}
#masthead img {
float: left;
}
#masthead p {
font-size: 11px;
color: #fff;
margin: 10px 10px 0;
}
#footer a {
color: #fff;
text-decoration: underline;
}
#footer a:hover {
color: #fff;
text-decoration: none;
}
a {
color: #036;
text-decoration: underline;
}
.i1 {
background: url(../images/icons50.png) 0px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.i2 {
background: url(../images/icons50.png) -50px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.i3 {
background: url(../images/icons50.png) -100px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.i4 {
background: url(../images/icons50.png) -150px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.i5 {
background: url(../images/icons50.png) -200px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.i6 {
background: url(../images/icons50.png) -250px 0px;
height: 50px;
width: 50px;
cursor: pointer;
border: none;
}
.j1 {
background: url(../images/icons16.png) 0px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.j2 {
background: url(../images/icons16.png) -16px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.j3 {
background: url(../images/icons16.png) -32px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.j4 {
background: url(../images/icons16.png) -48px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.j5 {
background: url(../images/icons16.png) -64px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.j6 {
background: url(../images/icons16.png) -80px 0px;
height: 16px;
width: 16px;
cursor: pointer;
border: none;
}
.lbbutton {
width:74px;
height:74px;
border-radius:5px;
background-color:white;
margin-left:8px;
margin-top:8px;
position:relative;
cursor:pointer;
opacity:0.5;
}
.lbbutton:hover {
opacity:1;
}
.lbbuttonsel {
opacity:0.9;
}
.lbbuttonsel2 {
width:82px;
border-radius:5px 0px 0px 5px;
opacity:1;
}
.lb1 {
background: url(../images/leftbar-62.jpg) -0px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.lb2 {
background: url(../images/leftbar-62.jpg) -75px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.lb3 {
background: url(../images/leftbar-62.jpg) -150px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.lb4 {
background: url(../images/leftbar-62.jpg) -225px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.lb5 {
background: url(../images/leftbar-62.jpg) -294px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.lb6 {
background: url(../images/leftbar-62.jpg) -360px 0px;
height: 62px;
width: 62px;
cursor: pointer;
border: none;
}
.m0 { background : url(../images/images16.png) -32px 0px; height : 16px; width : 16px; border:none; float:left }
.m1 { background : url(../images/images16.png) -16px 0px; height : 16px; width : 16px; border:none; float:left }
.m2 { background : url(../images/images16.png) -96px 0px; height : 16px; width : 16px; border:none; float:left }
.m3 { background : url(../images/images16.png) -112px 0px; height : 16px; width : 16px; border:none; float:left }
.si0 { background : url(../images/icons16.png) 0px 0px; height : 16px; width : 16px; border:none; float:left }
.si1 { background : url(../images/icons16.png) -16px 0px; height : 16px; width : 16px; border:none; float:left }
.si2 { background : url(../images/icons16.png) -32px 0px; height : 16px; width : 16px; border:none; float:left }
.si3 { background : url(../images/icons16.png) -48px 0px; height : 16px; width : 16px; border:none; float:left }
.si4 { background : url(../images/icons16.png) -64px 0px; height : 16px; width : 16px; border:none; float:left }
.mi { background : url(../images/meshicon50.png) 0px 0px; height: 50px; width: 50px; cursor:pointer; border:none }
#floatframe {
position: fixed;
top: 200px;
height: 300px;
z-index: 200;
display: none;
}
.style1 {
text-align: center;
}
.style2 {
text-align: center;
background-color: #808080;
font-weight: bold;
}
.style3 {
text-align: center;
color: white;
background-color: #808080;
font-weight: bold;
}
.style3x {
text-align: center;
color: white;
background-color: #808080;
font-weight: bold;
}
.style3x:hover {
background-color: #606060;
}
.style3sel {
text-align: center;
color: white;
background-color: #003366;
font-weight: bold;
}
.style4 {
color: white;
text-decoration: none;
}
.style5 {
text-align: center;
background-color: #808080;
font-weight: normal;
}
.style6 {
text-align: center;
background-color: #D3D9D6;
}
.style7 {
font-size: large;
background-color: #FFFFFF;
}
.style10 {
background-color: #C9C9C9;
}
.style11 {
font-size: large;
background-color: #C9C9C9;
}
.style14 {
text-align: left;
background-color: #D3D9D6;
}
.auto-style1 {
text-align: right;
background-color: #D3D9D6;
}
.fileIcon1 {
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb49Y2Sj9LT2f///yH5BAEAAAMALAAAAAAQABAAAAImnI+py+1vhJwyUYAzHTL4D3qdlJWaIFJqmKod607sDKIiDUP63hQAOw==);
height: 16px;
width: 16px;
cursor: pointer;
border: none;
float: left;
margin-top: 1px;
}
.fileIcon2 {
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7);
height: 16px;
width: 16px;
cursor: pointer;
border: none;
float: left;
margin-top: 1px;
}
.fileIcon3 {
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==);
height: 16px;
width: 16px;
cursor: pointer;
border: none;
float: left;
margin-top: 1px;
}
.fileIcon4 {
background: url(../images/meshicon16.png);
height: 16px;
width: 16px;
cursor: pointer;
border: none;
float: left;
margin-top: 1px;
}
.filelist {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
cursor: default;
-khtml-user-drag: element;
background-color: white;
clear: both;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fsize {
float: right;
text-align: right;
width: 180px;
}
.g1 {
background-position: 0% 0%;
width: 14px;
height: 100%;
float: left;
/* fallback (Opera) */
/* Mozilla: */
/* Chrome, Safari:*/
background-image: linear-gradient(to right, #ffffff 0%, #c9c9c9 100%);
background-color: #c9c9c9;
background-repeat: repeat;
background-attachment: scroll;
}
.g1s {
background-image: linear-gradient(to right, #ffffff 0%, #b9b9b9 100%);
}
.g2 {
background-position: 0% 0%;
width: 14px;
height: 100%;
float: right;
/* fallback (Opera) */
/* Mozilla: */
/* Chrome, Safari:*/
background-image: linear-gradient(to right, #c9c9c9 0%, #ffffff 100%);
background-color: #c9c9c9;
background-repeat: repeat;
background-attachment: scroll;
}
.g2s {
background-image: linear-gradient(to right, #b9b9b9 0%, #ffffff 100%);
}
.h1 {
background-position: 0% 0%;
width: 14px;
height: 100%;
/* fallback (Opera) */
/* Mozilla: */
/* Chrome, Safari:*/
background-image: linear-gradient(to right, #ffffff 0%, #d3d9d6 100%);
background-color: #d3d9d6;
background-repeat: repeat;
background-attachment: scroll;
}
.h2 {
background-position: 0% 0%;
width: 14px;
height: 100%;
/* fallback (Opera) */
/* Mozilla: */
/* Chrome, Safari:*/
background-image: linear-gradient(to right, #d3d9d6 0%, #ffffff 100%);
background-color: #d3d9d6;
background-repeat: repeat;
background-attachment: scroll;
}
.e1 {
font-size: large;
margin-top: 4px;
margin-bottom: 3px;
overflow: hidden;
word-wrap: hyphenate;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 200px
}
.e2 {
float: left;
height: 100%;
}
.f1 { background-color: #c9c9c9; }
.f1s { background-color: #b9b9b9; }
.bar {
font-size: large;
background-color: #C9C9C9;
height: 24px;
float: left;
margin-bottom: 2px;
}
.bar2 {
font-size: large;
height: 24px;
float: left;
margin-bottom: 2px;
}
.bar18 {
font-size: large;
background-color: #C9C9C9;
height: 18px;
float: left;
margin-bottom: 2px;
}
.bar182 {
font-size: large;
height: 18px;
float: left;
margin-bottom: 2px;
}
.devHeaderx {
color: lightgray;
}
.DevSt {
border-bottom-style: solid;
border-bottom-width: 1px;
border-bottom-color: #DDDDDD;
}
.contextMenu {
background: #F9F9F9;
box-shadow: 0 0 12px rgba( 0, 0, 0, .3 );
border: 1px solid #ccc;
/*border-radius: 4px;*/
display: none;
position: absolute;
top: 0;
left: 0;
list-style: none;
margin: 0;
padding: 5px;
min-width: 100px;
max-width: 150px;
z-index: 500;
}
.cmtext {
color: #444;
display: inline-block;
padding-left: 8px;
padding-right: 8px;
padding-top: 5px;
padding-bottom: 5px;
text-decoration: none;
width: 85%;
cursor: default;
overflow: hidden;
position: relative;
}
.cmtext:hover {
color: #f9f9f9;
background: #444;
}
.gray {
/*filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");*/ /* Firefox 10+, Firefox on Android */
filter: gray; /* IE6-9 */
-webkit-filter: grayscale(100%) opacity(60%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.notifiyBox {
position: absolute;
z-index:1000;
top: 50px;
right: 26px;
width: 300px;
text-align: left;
background-color: #F0ECCD;
border: 4px solid #666;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 2px 2px 4px #888;
-moz-box-shadow: 2px 2px 4px #888;
box-shadow: 2px 2px 4px #888;
max-height:200px;
}
.notifiyBox:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
right: 5px;
top: -30px;
border: 15px solid;
border-color: transparent #666 #666 transparent;
}
.notifiyBox:after {
content: ' ';
position: absolute;
width: 0;
height: 0;
right: 7px;
top: -24px;
border: 12px solid;
border-color: transparent #F0ECCD #F0ECCD transparent;
}
.notification {
width:100%;
min-height:30px;
}
.notification:hover {
background-color: #EFE8B6;
}
.deskToolsBar {
padding:3px;
}
.deskToolsBar:hover {
background-color: #EFE8B6;
}
.userTableHeader {
border-bottom: 1pt solid lightgray;
padding-top: 4px;
padding-bottom: 4px;
}
.viewSelector {
width:32px;
height:32px;
background-color:#DDD;
border-radius:3px;
float:left;
margin-left:5px;
cursor: pointer;
opacity: 0.3;
}
.viewSelectorSel {
background-color:#BBB;
opacity: 0.8;
}
.viewSelector:hover {
opacity: 0.5;
background-color:#AAA;
}
.viewSelector1 {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -0px 0px;
height: 28px;
width: 28px;
}
.viewSelector2 {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -28px 0px;
height: 28px;
width: 28px;
}
.viewSelector3 {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -56px 0px;
height: 28px;
width: 28px;
}
.viewSelector4 {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -84px 0px;
height: 28px;
width: 28px;
}
.viewSelector5 {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -112px 0px;
height: 28px;
width: 28px;
}
.backButtonEx {
margin-left:2px;
margin-top:2px;
background: url(../images/views.png) -140px 0px;
height: 28px;
width: 28px;
}
.backButton {
width:32px;
height:32px;
background-color:#DDD;
border-radius:3px;
float:left;
margin-right:5px;
cursor: pointer;
opacity: 0.3;
}
.backButton:hover {
opacity: 0.5;
background-color:#AAA;
}
.hoverButton {
opacity: 0.5;
}
.hoverButton:hover {
opacity: 1;
}
.devgrid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, auto));
}
.devgrid-container > div {
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -150,7 +150,7 @@
<div id=p0message style=margin:50px;text-align:center>Server disconnected, <href onclick=reload() style=cursor:pointer><u>click to reconnect</u></href>.</div>
</div>
<div id=p1 style=display:none>
<div style="float:right" id="devListToolbarViewIcons">
<div style="float:right;display:none" id="devListToolbarViewIcons">
<div id=devViewButton1 class="viewSelector" onclick=onDeviceViewChange(1) title="Columns"><div class="viewSelector2"></div></div>
<div id=devViewButton2 class=viewSelector onclick=onDeviceViewChange(2) title="List"><div class="viewSelector1"></div></div>
<div id=devViewButton3 class=viewSelector onclick=onDeviceViewChange(3) title="Desktops"><div class="viewSelector3"></div></div>
@ -159,19 +159,19 @@
<table style=width:100%;height:24px;background-color:#d3d9d6;vertical-align:middle;border-spacing:0>
<tr>
<td class=h1></td>
<td id=devListToolbar class=style14>
<td id=devListToolbar class=style14 style=display:none>
&nbsp;&nbsp;<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Select All" />&nbsp;
<input type=button id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />&nbsp;
<input id=SearchInput type=text style=width:120px placeholder=Filter onchange=masterUpdate(5) onkeyup=masterUpdate(5) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
<input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox() /><span title="Show devices operating system name">OS Name</span>
</td>
<td id=kvmListToolbar class=style14 style=height:100%>
<td id=kvmListToolbar class=style14 style=height:100%;display:none>
&nbsp;&nbsp;<input type="button" onclick="connectAllKvmFunction()" value="Connect All" />&nbsp;
<input type="button" onclick="disconnectAllKvmFunction()" value="Disconnect All" />&nbsp;
<input type="checkbox" id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" title="Automatic connect" />Auto&nbsp;
<input type="button" onclick="showMultiDesktopSettings()" value="Settings" />&nbsp;
</td>
<td id=devMapToolbar class=style14 style=height:100%>
<td id=devMapToolbar class=style14 style=height:100%;display:none>
&nbsp;&nbsp;<input type=text id=mapSearchLocation placeholder="Search Location" onfocus=onMapSearchFocus(1) onblur=onMapSearchFocus(0) />
<input type=button value=Search title="Search for location" onclick=getSearchLocation() />
<input type=button id=refreshmap title="Reset map view" value=Reset style=margin-left:5px onclick=refreshMap(false,true) />
@ -186,7 +186,7 @@
<option id=viewselectmapoption value=4>Map</option>
</select>
</div>
<div style=float:right id=devListToolbarSort>
<div style=float:right;display:none id=devListToolbarSort>
Sort
<select id=sortselect onchange=masterUpdate(6)>
<option>Group</option>
@ -196,7 +196,7 @@
</select>
&nbsp;
</div>
<div style=float:right id=devListToolbarSize>
<div style=float:right;display:none id=devListToolbarSize>
Size
<select id=sizeselect onchange=onDeviceViewChange()>
<option value=0>Small</option>
@ -221,8 +221,8 @@
</tr>
</table>
</div>
<div id="xdevices" style="max-height:calc(100vh - 239px);overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch"></div>
<div id="xdevicesmap" style="height:calc(100vh - 239px);width:100%;overflow:hidden;position:relative">
<div id="xdevices" style="max-height:calc(100vh - 239px);overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;display:none"></div>
<div id="xdevicesmap" style="height:calc(100vh - 239px);width:100%;overflow:hidden;position:relative;display:none">
<div id=xmapSearchResultsDlg style="position:absolute;display:none;max-height:280px;left:5px;top:5px;max-width:250px;z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666">
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
<div id=xmapSearchClose style=float:right;padding:5px;cursor:pointer onclick=mapCloseSearchWindow()><b>X</b></div>
@ -1943,7 +1943,8 @@
if (view == 3) {
// Figure out and adjust the size to fill the width of the div
var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
//var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
var realw = vsize.x + 2, tw = totalDeviceViewWidth - 5, xw = Math.floor(tw / realw);
xw = realw + Math.floor((tw - (xw * realw)) / xw);
vsize.y = vsize.y * (xw / vsize.x);
vsize.x = xw;

View File

@ -402,7 +402,7 @@ function trademarks(x) { return x.replace(/\(R\)/g, '&reg;').replace(/\(TM\)/g,
}
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = parsedUri[x]; break; } case 1: { r[name] = parsedUri[x]; var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; }
function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; }
// Update user controls
function updateControls() {

View File

@ -503,24 +503,24 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if ((cookie != null) && (cookie.u != null) && (cookie.e != null)) {
var idsplit = cookie.u.split('/');
if ((idsplit.length != 2) || (idsplit[0] != domain.id)) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid domain. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid domain. <a href="' + domain.url + '">Go to login page</a>.' });
} else {
obj.db.Get('user/' + cookie.u, function (err, docs) {
if (docs.length == 0) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(cookie.u) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(cookie.u) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
} else {
var user = docs[0];
if (user.email != cookie.e) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid e-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid e-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
} else {
if (cookie.a == 1) {
// Account email verification
if (user.emailVerified == true) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" already verified. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" already verified. <a href="' + domain.url + '">Go to login page</a>.' });
} else {
obj.db.GetUserWithVerifiedEmail(domain.id, user.email, function (err, docs) {
if (docs.length > 0) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" already in use on a different account. Change the email address and try again. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" already in use on a different account. Change the email address and try again. <a href="' + domain.url + '">Go to login page</a>.' });
} else {
// Set the verified flag
obj.users[user._id].emailVerified = true;
@ -540,7 +540,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Verified email of user ' + EscapeHtml(user.name) + ' (' + EscapeHtml(userinfo.email) + ')', domain: domain.id });
// Send the confirmation page
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' });
// Send a notification
obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 });
@ -550,7 +550,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
} else if (cookie.a == 2) {
// Account reset
if (user.emailVerified != true) {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" not verified. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" not verified. <a href="' + domain.url + '">Go to login page</a>.' });
} else {
// Set a temporary password
obj.crypto.randomBytes(16, function (err, buf) {
@ -581,19 +581,19 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Password reset for user ' + EscapeHtml(user.name), domain: domain.id });
// Send the new password
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: '<div>Password for account <b>' + EscapeHtml(user.name) + '</b> has been reset to:</div><div style=padding:14px;font-size:18px><b>' + EscapeHtml(newpass) + '</b></div>Login and go to the \"My Account\" tab to update your password. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: '<div>Password for account <b>' + EscapeHtml(user.name) + '</b> has been reset to:</div><div style=padding:14px;font-size:18px><b>' + EscapeHtml(newpass) + '</b></div>Login and go to the \"My Account\" tab to update your password. <a href="' + domain.url + '">Go to login page</a>.' });
});
});
}
} else {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid account check. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid account check. <a href="' + domain.url + '">Go to login page</a>.' });
}
}
}
});
}
} else {
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid account check, verification url is only valid for 30 minutes. <a href="' + domain.url + '">Go to login page</a>.' });
res.render(obj.path.join(obj.parent.webViewsPath, 'message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid account check, verification url is only valid for 30 minutes. <a href="' + domain.url + '">Go to login page</a>.' });
}
}
}
@ -804,14 +804,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (obj.args.minify && !req.query.nominify) {
// Try to server the minified version if we can.
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: 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 });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'default-mobile-min' : '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, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
} catch (ex) {
// 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: 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 });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'default-mobile' : '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, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
}
} else {
// 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: 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 });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'default-mobile' : '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, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer });
}
} else {
// Send back the login application
@ -824,19 +824,19 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (obj.args.minify && !req.query.nominify) {
// Try to server the minified version if we can.
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: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile-min' : '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, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer });
} catch (ex) {
// 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: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : '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, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer });
}
} else {
// 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: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : '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, passRequirements: passRequirements, 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(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : 'login');
console.log('Render...');
res.render(xpath, xoptions, function (err, html) {
console.log(err, html);
@ -868,9 +868,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (req.session && req.session.userid) {
if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url); return; } // Check is the session is for the correct domain
var user = obj.users[req.session.userid];
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, terms: encodeURIComponent(data), logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'terms-mobile' : 'terms'), { title: domain.title, title2: domain.title2, terms: encodeURIComponent(data), logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
} else {
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, terms: encodeURIComponent(data) });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'terms-mobile' : 'terms'), { title: domain.title, title2: domain.title2, terms: encodeURIComponent(data) });
}
});
} else {
@ -879,9 +879,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (req.session && req.session.userid) {
if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url); return; } // Check is the session is for the correct domain
var user = obj.users[req.session.userid];
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'terms-mobile' : 'terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
} else {
res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2 });
res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'terms-mobile' : 'terms'), { title: domain.title, title2: domain.title2 });
}
}
}
@ -891,7 +891,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
var webRtcConfig = null;
if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)); }
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
res.render(obj.path.join(__dirname, 'views/messenger'), { webrtconfig: webRtcConfig });
res.render(obj.path.join(obj.parent.webViewsPath, 'messenger'), { webrtconfig: webRtcConfig });
}
// Returns the server root certificate encoded in base64
@ -924,7 +924,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if ((serverNameSplit.length == 4) && (parseInt(serverNameSplit[0]) == serverNameSplit[0]) && (parseInt(serverNameSplit[1]) == serverNameSplit[1]) && (parseInt(serverNameSplit[2]) == serverNameSplit[2]) && (parseInt(serverNameSplit[3]) == serverNameSplit[3])) {
// Server name is an IPv4 address
obj.fs.readFile(obj.parent.path.join(__dirname, 'public/scripts/cira_setup_script_ip.mescript'), 'utf8', function (err, data) {
obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_setup_script_ip.mescript'), 'utf8', function (err, data) {
if (err != null) { res.sendStatus(404); return; }
var scriptFile = JSON.parse(data);
@ -950,7 +950,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
});
} else {
// Server name is a hostname
obj.fs.readFile(obj.parent.path.join(__dirname, 'public/scripts/cira_setup_script_dns.mescript'), 'utf8', function (err, data) {
obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_setup_script_dns.mescript'), 'utf8', function (err, data) {
if (err != null) { res.sendStatus(404); return; }
var scriptFile = JSON.parse(data);
@ -978,7 +978,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
else if (req.query.type == 2) {
var filename = 'cira_cleanup.mescript';
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + filename });
obj.fs.readFile(obj.parent.path.join(__dirname, 'public/scripts/cira_cleanup.mescript'), 'utf8', function (err, data) {
obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_cleanup.mescript'), 'utf8', function (err, data) {
if (err != null) { res.sendStatus(404); return; }
res.send(Buffer.from(data));
});
@ -1003,10 +1003,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' });
try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); }
} else {
res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "<a href='" + req.path + "?download=1'>" + filename + "</a>, " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." });
res.render(obj.path.join(obj.parent.webViewsPath, 'download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "<a href='" + req.path + "?download=1'>" + filename + "</a>, " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." });
}
} else {
res.render(obj.path.join(__dirname, 'views/download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "Invalid file link, please check the URL again." });
res.render(obj.path.join(obj.parent.webViewsPath, 'download'), { rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, message: "Invalid file link, please check the URL again." });
}
}
@ -1017,10 +1017,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
res.set({ 'Cache-Control': 'max-age=86400' }); // 1 day
if ((domain != null) && domain.titlepicture) {
try { res.sendFile(obj.path.join(obj.parent.datapath, domain.titlepicture)); } catch (e) {
try { res.sendFile(obj.path.join(__dirname, 'public/images/logoback.png')); } catch (e) { res.sendStatus(404); }
try { res.sendFile(obj.path.join(obj.parent.webPublicPath, 'images/logoback.png')); } catch (e) { res.sendStatus(404); }
}
} else {
try { res.sendFile(obj.path.join(__dirname, 'public/images/logoback.png')); } catch (e) { res.sendStatus(404); }
try { res.sendFile(obj.path.join(obj.parent.webPublicPath, 'images/logoback.png')); } catch (e) { res.sendStatus(404); }
}
}
@ -1964,7 +1964,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
try { res.sendFile(p); } catch (e) { res.sendStatus(404); }
} else {
// Use the default server picture
try { res.sendFile(obj.path.join(__dirname, 'public/images/server-200.jpg')); } catch (e) { res.sendStatus(404); }
try { res.sendFile(obj.path.join(obj.parent.webPublicPath, 'images/server-200.jpg')); } catch (e) { res.sendStatus(404); }
}
});
@ -2005,7 +2005,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.app.get(url + 'stop', function (req, res) { res.send('Stopping Server, <a href="' + url + '">click here to login</a>.'); setTimeout(function () { parent.Stop(); }, 500); });
// Indicates to ExpressJS that the public folder should be used to serve static files.
obj.app.use(url, obj.express.static(obj.path.join(__dirname, 'public')));
obj.app.use(url, obj.express.static(obj.parent.webPublicPath));
// Start regular disconnection list flush every 2 minutes.
obj.wsagentsDisconnectionsTimer = setInterval(function () { obj.wsagentsDisconnections = {}; }, 120000);