Updated agents, shift-device click will now open a new browser tab.

This commit is contained in:
Ylian Saint-Hilaire 2019-01-29 14:08:29 -08:00
parent 50fa7d760a
commit b0394da585
27 changed files with 206 additions and 57 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

@ -92,6 +92,11 @@ function UserSessions()
{
}
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
this._advapi.CreateMethod('AllocateAndInitializeSid');
this._advapi.CreateMethod('CheckTokenMembership');
this._advapi.CreateMethod('FreeSid');
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
this._user32.CreateMethod('UnregisterPowerSettingNotification');
@ -150,6 +155,26 @@ function UserSessions()
'WTSIsRemoteSession': 29
};
this.isRoot = function isRoot()
{
var NTAuthority = this._marshal.CreateVariable(6);
NTAuthority.toBuffer().writeInt8(5, 5);
var AdministratorsGroup = this._marshal.CreatePointer();
var admin = false;
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
{
var member = this._marshal.CreateInteger();
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
{
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
}
this._advapi.FreeSid(AdministratorsGroup.Deref());
}
return admin;
}
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
{
var buffer = this._marshal.CreatePointer();

File diff suppressed because one or more lines are too long

View File

@ -92,6 +92,11 @@ function UserSessions()
{
}
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
this._advapi.CreateMethod('AllocateAndInitializeSid');
this._advapi.CreateMethod('CheckTokenMembership');
this._advapi.CreateMethod('FreeSid');
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
this._user32.CreateMethod('UnregisterPowerSettingNotification');
@ -150,6 +155,26 @@ function UserSessions()
'WTSIsRemoteSession': 29
};
this.isRoot = function isRoot()
{
var NTAuthority = this._marshal.CreateVariable(6);
NTAuthority.toBuffer().writeInt8(5, 5);
var AdministratorsGroup = this._marshal.CreatePointer();
var admin = false;
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
{
var member = this._marshal.CreateInteger();
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
{
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
}
this._advapi.FreeSid(AdministratorsGroup.Deref());
}
return admin;
}
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
{
var buffer = this._marshal.CreatePointer();

View File

@ -1,5 +1,5 @@
/*
Copyright 2018-2019 Intel Corporation
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@ limitations under the License.
*/
var KEY_QUERY_VALUE = 0x0001;
var KEY_ENUMERATE_SUB_KEYS = 0x0008;
var KEY_WRITE = 0x20006;
var KEY_DATA_TYPES =
@ -39,7 +40,10 @@ function windows_registry()
this._marshal = require('_GenericMarshal');
this._AdvApi = this._marshal.CreateNativeProxy('Advapi32.dll');
this._AdvApi.CreateMethod('RegCreateKeyExA');
this._AdvApi.CreateMethod('RegEnumKeyExA');
this._AdvApi.CreateMethod('RegEnumValueA');
this._AdvApi.CreateMethod('RegOpenKeyExA');
this._AdvApi.CreateMethod('RegQueryInfoKeyA');
this._AdvApi.CreateMethod('RegQueryValueExA');
this._AdvApi.CreateMethod('RegCloseKey');
this._AdvApi.CreateMethod('RegDeleteKeyA');
@ -49,16 +53,63 @@ function windows_registry()
this.QueryKey = function QueryKey(hkey, path, key)
{
var err;
var h = this._marshal.CreatePointer();
var len = this._marshal.CreateVariable(4);
var valType = this._marshal.CreateVariable(4);
key = this._marshal.CreateVariable(key);
var HK = this._marshal.CreatePointer(hkey);
var retVal = null;
if (key) { key = this._marshal.CreateVariable(key); }
if (!path) { path = ''; }
if (this._AdvApi.RegOpenKeyExA(HK, this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE, h).Val != 0)
if ((err = this._AdvApi.RegOpenKeyExA(HK, this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, h).Val) != 0)
{
throw ('Error Opening Registry Key: ' + path);
throw ('Opening Registry Key: ' + path + ' => Returned Error: ' + err);
}
if ((path == '' && !key) || !key)
{
var result = { subkeys: [], values: [] };
// Enumerate keys
var achClass = this._marshal.CreateVariable(1024);
var achKey = this._marshal.CreateVariable(1024);
var achValue = this._marshal.CreateVariable(32768);
var achValueSize = this._marshal.CreateVariable(4);
var nameSize = this._marshal.CreateVariable(4);
var achClassSize = this._marshal.CreateVariable(4); achClassSize.toBuffer().writeUInt32LE(1024);
var numSubKeys = this._marshal.CreateVariable(4);
var numValues = this._marshal.CreateVariable(4);
var longestSubkeySize = this._marshal.CreateVariable(4);
var longestClassString = this._marshal.CreateVariable(4);
var longestValueName = this._marshal.CreateVariable(4);
var longestValueData = this._marshal.CreateVariable(4);
var securityDescriptor = this._marshal.CreateVariable(4);
var lastWriteTime = this._marshal.CreateVariable(8);
retVal = this._AdvApi.RegQueryInfoKeyA(h.Deref(), achClass, achClassSize, 0,
numSubKeys, longestSubkeySize, longestClassString, numValues,
longestValueName, longestValueData, securityDescriptor, lastWriteTime);
if (retVal.Val != 0) { throw ('RegQueryInfoKeyA() returned error: ' + retVal.Val); }
for(var i = 0; i < numSubKeys.toBuffer().readUInt32LE(); ++i)
{
nameSize.toBuffer().writeUInt32LE(1024);
retVal = this._AdvApi.RegEnumKeyExA(h.Deref(), i, achKey, nameSize, 0, 0, 0, lastWriteTime);
if(retVal.Val == 0)
{
result.subkeys.push(achKey.String);
}
}
for (var i = 0; i < numValues.toBuffer().readUInt32LE() ; ++i)
{
achValueSize.toBuffer().writeUInt32LE(32768);
if(this._AdvApi.RegEnumValueA(h.Deref(), i, achValue, achValueSize, 0, 0, 0, 0).Val == 0)
{
result.values.push(achValue.String);
}
}
return (result);
}
if(this._AdvApi.RegQueryValueExA(h.Deref(), key, 0, 0, 0, len).Val == 0)

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
var KEY_QUERY_VALUE=1;var KEY_WRITE=131078;var KEY_DATA_TYPES={REG_NONE:0,REG_SZ:1,REG_EXPAND_SZ:2,REG_BINARY:3,REG_DWORD:4,REG_DWORD_BIG_ENDIAN:5,REG_LINK:6,REG_MULTI_SZ:7,REG_RESOURCE_LIST:8,REG_FULL_RESOURCE_DESCRIPTOR:9,REG_RESOURCE_REQUIREMENTS_LIST:10,REG_QWORD:11};function windows_registry(){this._ObjectId="win-registry";this._marshal=require("_GenericMarshal");this._AdvApi=this._marshal.CreateNativeProxy("Advapi32.dll");this._AdvApi.CreateMethod("RegCreateKeyExA");this._AdvApi.CreateMethod("RegOpenKeyExA");this._AdvApi.CreateMethod("RegQueryValueExA");this._AdvApi.CreateMethod("RegCloseKey");this._AdvApi.CreateMethod("RegDeleteKeyA");this._AdvApi.CreateMethod("RegDeleteValueA");this._AdvApi.CreateMethod("RegSetValueExA");this.HKEY={Root:Buffer.from("80000000","hex").swap32(),CurrentUser:Buffer.from("80000001","hex").swap32(),LocalMachine:Buffer.from("80000002","hex").swap32(),Users:Buffer.from("80000003","hex").swap32()};this.QueryKey=function b(g,k,i){var e=this._marshal.CreatePointer();var j=this._marshal.CreateVariable(4);var m=this._marshal.CreateVariable(4);i=this._marshal.CreateVariable(i);var f=this._marshal.CreatePointer(g);var l=null;if(this._AdvApi.RegOpenKeyExA(f,this._marshal.CreateVariable(k),0,KEY_QUERY_VALUE,e).Val!=0){throw ("Error Opening Registry Key: "+k)}if(this._AdvApi.RegQueryValueExA(e.Deref(),i,0,0,0,j).Val==0){var d=this._marshal.CreateVariable(j.toBuffer().readUInt32LE());if(this._AdvApi.RegQueryValueExA(e.Deref(),i,0,m,d,j).Val==0){switch(m.toBuffer().readUInt32LE()){case KEY_DATA_TYPES.REG_DWORD:l=d.toBuffer().readUInt32LE();break;case KEY_DATA_TYPES.REG_DWORD_BIG_ENDIAN:l=d.toBuffer().readUInt32BE();break;case KEY_DATA_TYPES.REG_SZ:l=d.String;break;case KEY_DATA_TYPES.REG_BINARY:default:l=d.toBuffer();l._data=d;break}}}else{this._AdvApi.RegCloseKey(e.Deref());throw ("Not Found")}this._AdvApi.RegCloseKey(e.Deref());return(l)};this.WriteKey=function c(g,j,i,l){var k;var f=this._marshal.CreatePointer();if(this._AdvApi.RegCreateKeyExA(this._marshal.CreatePointer(g),this._marshal.CreateVariable(j),0,0,0,KEY_WRITE,0,f,0).Val!=0){throw ("Error Opening Registry Key: "+j)}var d;var e;switch(typeof(l)){case"boolean":e=KEY_DATA_TYPES.REG_DWORD;d=this._marshal.CreateVariable(4);d.toBuffer().writeUInt32LE(l?1:0);break;case"number":e=KEY_DATA_TYPES.REG_DWORD;d=this._marshal.CreateVariable(4);d.toBuffer().writeUInt32LE(l);break;case"string":e=KEY_DATA_TYPES.REG_SZ;d=this._marshal.CreateVariable(l);break;default:e=KEY_DATA_TYPES.REG_BINARY;d=this._marshal.CreateVariable(l.length);l.copy(d.toBuffer());break}if(this._AdvApi.RegSetValueExA(f.Deref(),this._marshal.CreateVariable(i),0,e,d,d._size).Val!=0){this._AdvApi.RegCloseKey(f.Deref());throw ("Error writing reg key: "+i)}this._AdvApi.RegCloseKey(f.Deref())};this.DeleteKey=function a(e,g,f){if(!f){if(this._AdvApi.RegDeleteKeyA(this._marshal.CreatePointer(e),this._marshal.CreateVariable(g)).Val!=0){throw ("Error Deleting Key: "+g)}}else{var d=this._marshal.CreatePointer();var i;if(this._AdvApi.RegOpenKeyExA(this._marshal.CreatePointer(e),this._marshal.CreateVariable(g),0,KEY_QUERY_VALUE|KEY_WRITE,d).Val!=0){throw ("Error Opening Registry Key: "+g)}if((i=this._AdvApi.RegDeleteValueA(d.Deref(),this._marshal.CreateVariable(f)).Val)!=0){this._AdvApi.RegCloseKey(d.Deref());throw ("Error["+i+"] Deleting Key: "+g+"."+f)}this._AdvApi.RegCloseKey(d.Deref())}}}module.exports=new windows_registry();
var KEY_QUERY_VALUE=1;var KEY_ENUMERATE_SUB_KEYS=8;var KEY_WRITE=131078;var KEY_DATA_TYPES={REG_NONE:0,REG_SZ:1,REG_EXPAND_SZ:2,REG_BINARY:3,REG_DWORD:4,REG_DWORD_BIG_ENDIAN:5,REG_LINK:6,REG_MULTI_SZ:7,REG_RESOURCE_LIST:8,REG_FULL_RESOURCE_DESCRIPTOR:9,REG_RESOURCE_REQUIREMENTS_LIST:10,REG_QWORD:11};function windows_registry(){this._ObjectId="win-registry";this._marshal=require("_GenericMarshal");this._AdvApi=this._marshal.CreateNativeProxy("Advapi32.dll");this._AdvApi.CreateMethod("RegCreateKeyExA");this._AdvApi.CreateMethod("RegEnumKeyExA");this._AdvApi.CreateMethod("RegEnumValueA");this._AdvApi.CreateMethod("RegOpenKeyExA");this._AdvApi.CreateMethod("RegQueryInfoKeyA");this._AdvApi.CreateMethod("RegQueryValueExA");this._AdvApi.CreateMethod("RegCloseKey");this._AdvApi.CreateMethod("RegDeleteKeyA");this._AdvApi.CreateMethod("RegDeleteValueA");this._AdvApi.CreateMethod("RegSetValueExA");this.HKEY={Root:Buffer.from("80000000","hex").swap32(),CurrentUser:Buffer.from("80000001","hex").swap32(),LocalMachine:Buffer.from("80000002","hex").swap32(),Users:Buffer.from("80000003","hex").swap32()};this.QueryKey=function b(o,A,q){var l;var m=this._marshal.CreatePointer();var s=this._marshal.CreateVariable(4);var E=this._marshal.CreateVariable(4);var n=this._marshal.CreatePointer(o);var C=null;if(q){q=this._marshal.CreateVariable(q)}if(!A){A=""}if((l=this._AdvApi.RegOpenKeyExA(n,this._marshal.CreateVariable(A),0,KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,m).Val)!=0){throw ("Opening Registry Key: "+A+" => Returned Error: "+l)}if((A==""&&!q)||!q){var B={subkeys:[],values:[]};var d=this._marshal.CreateVariable(1024);var f=this._marshal.CreateVariable(1024);var g=this._marshal.CreateVariable(32768);var j=this._marshal.CreateVariable(4);var x=this._marshal.CreateVariable(4);var e=this._marshal.CreateVariable(4);e.toBuffer().writeUInt32LE(1024);var y=this._marshal.CreateVariable(4);var z=this._marshal.CreateVariable(4);var u=this._marshal.CreateVariable(4);var t=this._marshal.CreateVariable(4);var w=this._marshal.CreateVariable(4);var v=this._marshal.CreateVariable(4);var D=this._marshal.CreateVariable(4);var r=this._marshal.CreateVariable(8);C=this._AdvApi.RegQueryInfoKeyA(m.Deref(),d,e,0,y,u,t,z,w,v,D,r);if(C.Val!=0){throw ("RegQueryInfoKeyA() returned error: "+C.Val)}for(var p=0;p<y.toBuffer().readUInt32LE();++p){x.toBuffer().writeUInt32LE(1024);C=this._AdvApi.RegEnumKeyExA(m.Deref(),p,f,x,0,0,0,r);if(C.Val==0){B.subkeys.push(f.String)}}for(var p=0;p<z.toBuffer().readUInt32LE();++p){j.toBuffer().writeUInt32LE(32768);if(this._AdvApi.RegEnumValueA(m.Deref(),p,g,j,0,0,0,0).Val==0){B.values.push(g.String)}}return(B)}if(this._AdvApi.RegQueryValueExA(m.Deref(),q,0,0,0,s).Val==0){var k=this._marshal.CreateVariable(s.toBuffer().readUInt32LE());if(this._AdvApi.RegQueryValueExA(m.Deref(),q,0,E,k,s).Val==0){switch(E.toBuffer().readUInt32LE()){case KEY_DATA_TYPES.REG_DWORD:C=k.toBuffer().readUInt32LE();break;case KEY_DATA_TYPES.REG_DWORD_BIG_ENDIAN:C=k.toBuffer().readUInt32BE();break;case KEY_DATA_TYPES.REG_SZ:C=k.String;break;case KEY_DATA_TYPES.REG_BINARY:default:C=k.toBuffer();C._data=k;break}}}else{this._AdvApi.RegCloseKey(m.Deref());throw ("Not Found")}this._AdvApi.RegCloseKey(m.Deref());return(C)};this.WriteKey=function c(g,j,i,l){var k;var f=this._marshal.CreatePointer();if(this._AdvApi.RegCreateKeyExA(this._marshal.CreatePointer(g),this._marshal.CreateVariable(j),0,0,0,KEY_WRITE,0,f,0).Val!=0){throw ("Error Opening Registry Key: "+j)}var d;var e;switch(typeof(l)){case"boolean":e=KEY_DATA_TYPES.REG_DWORD;d=this._marshal.CreateVariable(4);d.toBuffer().writeUInt32LE(l?1:0);break;case"number":e=KEY_DATA_TYPES.REG_DWORD;d=this._marshal.CreateVariable(4);d.toBuffer().writeUInt32LE(l);break;case"string":e=KEY_DATA_TYPES.REG_SZ;d=this._marshal.CreateVariable(l);break;default:e=KEY_DATA_TYPES.REG_BINARY;d=this._marshal.CreateVariable(l.length);l.copy(d.toBuffer());break}if(this._AdvApi.RegSetValueExA(f.Deref(),this._marshal.CreateVariable(i),0,e,d,d._size).Val!=0){this._AdvApi.RegCloseKey(f.Deref());throw ("Error writing reg key: "+i)}this._AdvApi.RegCloseKey(f.Deref())};this.DeleteKey=function a(e,g,f){if(!f){if(this._AdvApi.RegDeleteKeyA(this._marshal.CreatePointer(e),this._marshal.CreateVariable(g)).Val!=0){throw ("Error Deleting Key: "+g)}}else{var d=this._marshal.CreatePointer();var i;if(this._AdvApi.RegOpenKeyExA(this._marshal.CreatePointer(e),this._marshal.CreateVariable(g),0,KEY_QUERY_VALUE|KEY_WRITE,d).Val!=0){throw ("Error Opening Registry Key: "+g)}if((i=this._AdvApi.RegDeleteValueA(d.Deref(),this._marshal.CreateVariable(f)).Val)!=0){this._AdvApi.RegCloseKey(d.Deref());throw ("Error["+i+"] Deleting Key: "+g+"."+f)}this._AdvApi.RegCloseKey(d.Deref())}}}module.exports=new windows_registry();

2
db.js
View File

@ -151,7 +151,7 @@ module.exports.CreateDB = function (parent) {
obj.Get = function (id, func) { obj.file.find({ _id: id }, func); };
obj.GetAll = function (func) { obj.file.find({}, func); };
obj.GetAllTypeNoTypeField = function (type, domain, func) { obj.file.find({ type: type, domain: domain }, { type: 0 }, func); };
obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, func) { obj.file.find({ type: type, domain: domain, meshid: { $in: meshes } }, { type: 0 }, func); };
obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, id, func) { var x = { type: type, domain: domain, meshid: { $in: meshes } }; if (id) { x._id = id; } obj.file.find(x, { type: 0 }, func); };
obj.GetAllType = function (type, func) { obj.file.find({ type: type }, func); };
obj.GetAllIdsOfType = function (ids, domain, type, func) { obj.file.find({ type: type, domain: domain, _id: { $in: ids } }, func); };
obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }, { type: 0 }, func); };

View File

@ -230,6 +230,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
switch (command.action) {
case 'ping': { try { ws.send(JSON.stringify({ action: 'pong' })); } catch (ex) { } break; }
case 'authcookie':
{
// Renew the authentication cookie
try { ws.send(JSON.stringify({ action: 'authcookie', cookie: obj.parent.parent.encodeCookie({ userid: user._id, domainid: domain.id }, obj.parent.loginCookieEncryptionKey) })); } catch (ex) { }
break;
}
case 'serverstats':
{
if ((user.siteadmin) != 0) {
@ -267,7 +273,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
}
// Request a list of all nodes
obj.db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', function (err, docs) {
obj.db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', command.id, function (err, docs) {
var r = {};
for (i in docs) {
// Add the connection state

View File

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

View File

@ -33,21 +33,21 @@
</head>
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" oncontextmenu="handleContextMenu(event)" style="display:none">
<!-- right click menu -->
<div id="contextMenu" class="contextMenu" style="display:none">
<div id="cxinfo" class="cmtext" onclick="cmaction(1)"><b>Information</b></div>
<div id="cxdesktop" class="cmtext" onclick="cmaction(3)">Desktop</div>
<div id="cxterminal" class="cmtext" onclick="cmaction(2)">Terminal</div>
<div id="cxfiles" class="cmtext" onclick="cmaction(4)">Files</div>
<div id="cxevents" class="cmtext" onclick="cmaction(5)">Events</div>
<div id="cxconsole" class="cmtext" onclick="cmaction(6)">Console</div>
<div id="contextMenu" class="contextMenu noselect" style="display:none">
<div id="cxinfo" class="cmtext" onclick="cmaction(1,event)"><b>Information</b></div>
<div id="cxdesktop" class="cmtext" onclick="cmaction(3,event)">Desktop</div>
<div id="cxterminal" class="cmtext" onclick="cmaction(2,event)">Terminal</div>
<div id="cxfiles" class="cmtext" onclick="cmaction(4,event)">Files</div>
<div id="cxevents" class="cmtext" onclick="cmaction(5,event)">Events</div>
<div id="cxconsole" class="cmtext" onclick="cmaction(6,event)">Console</div>
<hr id="cxmgroupsplit" />
<div id="cxmdesktop" class="cmtext" onclick="cmaction(7)" style=display:none>Multi-Desktop</div>
<div id="cxmdesktop" class="cmtext" onclick="cmaction(7,event)" style=display:none>Multi-Desktop</div>
</div>
<div id="meshContextMenu" class="contextMenu" style="display: none; min-width: 0px">
<div id="cxselectall" class="cmtext" onclick="cmmeshaction(1)">Select All</div>
<div id="cxselectnone" class="cmtext" onclick="cmmeshaction(2)">Select None</div>
<div id="meshContextMenu" class="contextMenu,noselect" style="display: none; min-width: 0px">
<div id="cxselectall" class="cmtext" onclick="cmmeshaction(1,event)">Select All</div>
<div id="cxselectnone" class="cmtext" onclick="cmmeshaction(2,event)">Select None</div>
<hr id="cxmgroupsplit2" style=display:none />
<div id="cxmmdesktop" class="cmtext" style=display:none onclick="cmmeshaction(3)">Multi-Desktop</div>
<div id="cxmmdesktop" class="cmtext" style=display:none onclick="cmmeshaction(3,event)">Multi-Desktop</div>
</div>
<!-- main page -->
<div id=container style=max-height:100vh;position:relative>
@ -156,7 +156,7 @@
<div id=devViewButton3 class=viewSelector onclick=onDeviceViewChange(3) title="Desktops"><div class="viewSelector3"></div></div>
<div id=devViewButton4 class=viewSelector onclick=onDeviceViewChange(4) title="Map"><div class="viewSelector4"></div></div>
</div><div><h1>My Devices</h1></div>
<table style=width:100%;height:24px;background-color:#d3d9d6;vertical-align:middle;border-spacing:0>
<table class="noselect" style=width:100%;height:24px;background-color:#d3d9d6;vertical-align:middle;border-spacing:0>
<tr>
<td class=h1></td>
<td id=devListToolbar class=style14 style=display:none>
@ -221,7 +221,7 @@
</tr>
</table>
</div>
<div id="xdevices" style="max-height:calc(100vh - 239px);overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;display:none"></div>
<div id="xdevices" class="noselect" 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">
@ -371,7 +371,7 @@
<tr>
<td style=width:auto valign=top>
<div id=p10title>
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p10BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>General - <span id=p10deviceName></span></h1>
</div>
<div id=p10html></div>
@ -389,7 +389,7 @@
<div id=p11 class=noselect style=display:none>
<div id="p11title">
<div id=p11deviceNameHeader>
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p11BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div style="float:right" id="devListToolbarViewIcons"><div class="viewSelector" onclick=deskToggleFull(event) title="Full Screen. Hold shift to browser full screen."><div class="viewSelector5"></div></div></div>
<h1>Desktop - <span id=p11deviceName></span></h1>
</div>
@ -475,7 +475,7 @@
</div>
<div id=p12 style="display:none">
<div id="p12title">
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p12BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>Terminal - <span id=p12deviceName></span></h1>
</div>
<div id="p12warning" style='max-width:100%;display:none;cursor:pointer;margin-bottom:5px' onclick=showFeaturesDlg()>
@ -536,7 +536,7 @@
</div>
<div id=p13 style=display:none>
<div id="p13title">
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p13BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>Files - <span id=p13deviceName></span></h1>
</div>
<table id="p13toolbar" style="width: 100%" cellpadding="0" cellspacing="0">
@ -596,14 +596,14 @@
</div>
<div id=p14 style=display:none>
<div id="p14title">
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p14BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>Intel&reg; AMT - <span id=p14deviceName></span></h1>
</div>
<iframe id=p14iframe style="width:100%;height:calc(100vh - 242px);border:0;overflow:hidden" src="/commander.htm"></iframe>
</div>
<div id=p15 style=display:none>
<div id="p15title">
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p15BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>Console - <span id=p15deviceName></span></h1>
</div>
<table cellpadding=0 cellspacing=0 style="width:100%;padding:0px;padding:0px;margin-top:0px">
@ -643,7 +643,7 @@
</div>
<div id=p16 style=display:none>
<div id="p16title">
<div style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<div id="p16BackButton" style="float:left"><div class="backButton" onclick=goBack() title="Back"><div class="backButtonEx"></div></div></div>
<h1>Events - <span id=p16deviceName></span></h1>
</div>
<div style=width:100%;height:24px;background-color:#d3d9d6;margin-bottom:4px>
@ -849,7 +849,7 @@
var meshserver = null;
var meshes = {};
var meshcount = 0;
var nodes = [];
var nodes = null;
var filetree = {};
var userinfo = null;
var serverinfo = null;
@ -868,6 +868,7 @@
var domain = "{{{domain}}}";
var domainUrl = "{{{domainurl}}}";
var authCookie = "{{{authCookie}}}";
var authCookieRenewTimer = null;
var multiDesktop = {};
var multiDesktopFilter = null;
var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}";
@ -889,8 +890,6 @@
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
}
toggleFullScreen();
// Check if we are in debug mode
args = parseUriArgs();
debugmode = args.debug;
@ -899,12 +898,13 @@
QV('autoconnectbutton2', debugmode); // Terminal
QV('autoconnectbutton1', debugmode); // Desktop
toggleFullScreen();
// Setup page visuals
if (args.hide) {
var hide = parseInt(args.hide);
QV('masthead', !(hide & 1));
QV('topbarmaster', !(hide & 2));
QV('page_leftbar', !(hide & 2));
QV('footer', !(hide & 4));
QV('p10title', !(hide & 8));
QV('p11title', !(hide & 8));
@ -913,6 +913,21 @@
QV('p14title', !(hide & 8));
QV('p15title', !(hide & 8));
QV('p16title', !(hide & 8));
if (hide & 16) {
QV('page_leftbar', false);
QS('page_content').left = '0px';
}
}
// We are looking at a single device, remove all the back buttons
if ('{{currentNode}}' != '') {
QV('p10BackButton', false);
QV('p11BackButton', false);
QV('p12BackButton', false);
QV('p13BackButton', false);
QV('p14BackButton', false);
QV('p15BackButton', false);
QV('p16BackButton', false);
}
p1updateInfo();
@ -980,6 +995,8 @@
// 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) {
QS('container').width = '960px';
QS('container')['border-right'] = '1px solid #b7b7b7';
@ -1007,7 +1024,7 @@
QS('container')['overflow'] = 'hidden';
QS('page_content').position = 'absolute';
QS('page_content').top = '66px';
QS('page_content').left = '90px';
QS('page_content').left = (hide & 16)?'0px':'90px';
QS('page_content').right = '0px';
QS('page_content').bottom = '0px';
QS('column_l').height = 'calc(100vh - 135px)';
@ -1016,14 +1033,14 @@
QS('column_l')["max-height"] = 'calc(100vh - 135px)';
QV('MainMenuSpan', false);
QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
QV('page_leftbar', true);
QV('page_leftbar', !(hide & 16));
}
//center();
masterUpdate(512);
QV('body', true);
}
function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
function reload() { window.location.href = window.location.href; }
function onStateChanged(server, state, prevState, errorCode) {
@ -1043,12 +1060,14 @@
QV('logoutControl', false);
if (errorCode == 'noauth') { QH('p0span', 'Unable to perform authentication'); return; }
if (prevState == 2) { setTimeout(serverPoll, 5000); } else { QH('p0span', 'Unable to connect web socket'); }
if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
} else if (state == 2) {
// Fetch list of meshes, nodes, files
meshserver.send({ action: 'meshes' });
meshserver.send({ action: 'nodes' });
meshserver.send({ action: 'files' });
meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }
go(1);
authCookieRenewTimer = setInterval(function () { meshserver.send({ action: 'authcookie' }); }, 1800000); // Request a cookie refresh every 30 minutes.
}
}
@ -1140,6 +1159,11 @@
updateServerStats(message);
break;
}
case 'authcookie': {
// Got an authentication cookie refresh
authCookie = message.cookie;
break;
}
case 'serverinfo': {
serverinfo = message.serverinfo;
break;
@ -1221,7 +1245,7 @@
// Check if this is a message from a node
if (message.nodeid != null) {
var index = -1;
for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } }
if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
if (index != -1) {
// Node was found, dispatch the message
if (message.type == 'console') { p15consoleReceive(nodes[index], message.value); } // This is a console message.
@ -1444,7 +1468,7 @@
// Delete all nodes in that mesh
var newnodes = [];
for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } }
if (nodes != null) { for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } }
nodes = newnodes;
masterUpdate(4);
@ -1464,6 +1488,7 @@
node.state = 0;
if (!node.icon) node.icon = 1;
node.ident = ++nodeShortIdent;
if (nodes == null) { }
nodes.push(node);
// Web page update
@ -1753,6 +1778,7 @@
var deviceHeaders = {};
var oldviewmode = 0;
function updateDevices() {
if (nodes == null) { return; }
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
QV('xdevices', view < 4);
QV('xdevicesmap', view == 4);
@ -1842,19 +1868,19 @@
var nodestate = NodeStateStr(nodes[i]);
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
if (view == 1) {
r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div>';
r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div>';
} else if (view == 2) {
r += '<tr><td><div id=devs class=bar18 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium>';
r += '<div style=width:22px;float:left;background-color:white><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div>';
r += '<div style=float:left;height:18px;width:18px;background-color:white onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class=j' + icon + ' style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
r += '<div style=float:left;height:18px;width:18px;background-color:white onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><div class=j' + icon + ' style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + nodes[i]._id + '\')><span style=float:right>' + nodestate + '</span><span style=width:300px>' + name + '</span></div></div></td></tr>';
r += '<div style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)><span style=float:right>' + nodestate + '</span><span style=width:300px>' + name + '</span></div></div></td></tr>';
} else if ((view == 3) && (nodes[i].conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((nodes[i].agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
if ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodes[i]._id) >= 0)) {
r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\',11)>';
r += '<div id=devs style=display:inline-block;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\',11,null,event)>';
//r += '<input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox style=float:left>';
r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
r += '<span onclick=gotoDevice(\'' + nodes[i]._id + '\')></span><div id=xkvmid_' + nodes[i]._id.split('/')[2] + '><div id=skvmid_' + nodes[i]._id.split('/')[2] + ' style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + nodes[i]._id + '\')>Disconnected</div></div>';
r += '<span onclick=gotoDevice(\'' + nodes[i]._id + '\',null,null,event)></span><div id=xkvmid_' + nodes[i]._id.split('/')[2] + '><div id=skvmid_' + nodes[i]._id.split('/')[2] + ' style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + nodes[i]._id + '\')>Disconnected</div></div>';
r += '</div>';
kvmDivs.push(nodes[i]._id);
}
@ -2479,7 +2505,7 @@
// Get the node and set the menu options
var nodeid = contextelement.children[1].attributes.onclick.value;
var node = getNodeFromId(nodeid.substring(12, nodeid.length - 2));
var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
var mesh = meshes[node.meshid];
var meshlinks = mesh.links['user/' + domain + '/' + userinfo.name.toLowerCase()];
var meshrights = meshlinks.rights;
@ -2493,16 +2519,20 @@
return haltEvent(event);
}
function cmaction(action) {
function cmaction(action,event) {
var nodeid = contextelement.children[1].attributes.onclick.value;
nodeid = nodeid.substring(12, nodeid.length - 2);
if (action == 1) gotoDevice(nodeid, 10); // General
if (action == 2) gotoDevice(nodeid, 12); // Desktop
if (action == 3) gotoDevice(nodeid, 11); // Terminal
if (action == 4) gotoDevice(nodeid, 13); // Files
if (action == 5) gotoDevice(nodeid, 16); // Events
if (action == 6) gotoDevice(nodeid, 15); // Console
nodeid = nodeid.substring(12, nodeid.length - 18);
if (action == 7) { Q('viewselect').value = 3; Q('viewselect').onchange(); Q('autoConnectDesktopCheckbox').checked = true; Q('autoConnectDesktopCheckbox').onclick(); } // Multi-Desktop
if ((action > 0) && (action < 7)) {
var panel = [0, 10, 12, 11, 13, 16, 15][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console
if (event && (event.shiftKey == true)) {
// Open the device in a different tab
window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid);
} else {
// Go to the right panel
gotoDevice(nodeid, panel);
}
}
}
function cmmeshaction(action) {
@ -3145,7 +3175,13 @@
var powerTimelineUpdate = null;
var powerTimeline = null;
function getCurrentNode() { return currentNode; };
function gotoDevice(nodeid, panel, refresh) {
function gotoDevice(nodeid, panel, refresh, event) {
if (event && (event.shiftKey == true)) {
// Open the device in a different tab
window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid);
return;
}
//disconnectAllKvmFunction();
var node = getNodeFromId(nodeid);
var mesh = meshes[node.meshid];
@ -3355,6 +3391,9 @@
// Ask for device events
refreshDeviceEvents();
// Update the web page title
if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) { document.title = 'MeshCentral - ' + currentNode.name; } else { document.title = 'MeshCentral'; }
}
setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
if (!panel) panel = 10;
@ -6605,6 +6644,9 @@
}
if (x == 1) masterUpdate(4);
// Update the web page title
if ((currentNode) && (x >= 10) && (x < 20)) { document.title = 'MeshCentral - ' + currentNode.name; } else { document.title = 'MeshCentral'; }
}
// Generic methods