Merge branch 'Ylianst:master' into dockerrewrite

This commit is contained in:
DaanSelen 2025-05-23 10:32:17 +02:00 committed by GitHub
commit 620df54036
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 5333 additions and 5145 deletions

View File

@ -2314,11 +2314,11 @@ function terminal_end()
function terminal_consent_ask(ws) {
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['terminalConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username);
var consentMessage = currentTranslation['terminalConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgTerminal != null) { consentMessage = ws.httprequest.soptions.consentMsgTerminal.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); }
if (ws.httprequest.soptions.consentMsgTerminal != null) { consentMessage = ws.httprequest.soptions.consentMsgTerminal.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
}
if (process.platform == 'win32') {
var enhanced = false;
@ -2417,12 +2417,12 @@ function terminal_promise_connection_resolved(term)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 2))
{
// User Notifications is required
var notifyMessage = currentTranslation['terminalNotify'].replaceAll('{0}', this.ws.httprequest.realname ? this.ws.httprequest.realname : this.ws.httprequest.username);
var notifyMessage = currentTranslation['terminalNotify'].replace(/\{0\}/g, this.ws.httprequest.realname ? this.ws.httprequest.realname : this.ws.httprequest.username);
var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null)
{
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); }
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
}
@ -2431,11 +2431,19 @@ function terminal_promise_connection_resolved(term)
function terminal_promise_consent_rejected(e)
{
// DO NOT start terminal
if (this.that) {
if(this.that.httprequest){ // User Consent Denied
if ((this.that.httprequest.oldStyle === true) && (this.that.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
terminal_promise_consent_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
return;
}
} else { } // Connection was closed server side, maybe log some messages somewhere?
this.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
this.that.end();
this.that = null;
this.httprequest = null;
} else { } // no websocket, maybe log some messages somewhere?
}
function promise_init(res, rej) { this._res = res; this._rej = rej; }
function terminal_userpromise_resolved(u)
@ -2646,7 +2654,7 @@ function tunnel_kvm_end()
this.httprequest.desktop.kvm.users.splice(i, 1);
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
this.httprequest.desktop.kvm.connectionBar.close();
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replaceAll('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', this.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace(/\{0\}/g, this.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, this.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
this.httprequest.desktop.kvm.connectionBar.on('close', function ()
{
@ -2682,11 +2690,11 @@ function kvm_consent_ok(ws) {
if (ws.httprequest.consent && (ws.httprequest.consent & 1)){
// User Notifications is required
MeshServerLogEx(35, null, "Started remote desktop with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
var notifyMessage = currentTranslation['desktopNotify'].replaceAll('{0}', ws.httprequest.realname);
var notifyMessage = currentTranslation['desktopNotify'].replace(/\{0\}/g, ws.httprequest.realname);
var notifyTitle = "MeshCentral";
if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; }
if (ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = ws.httprequest.soptions.notifyMsgDesktop.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); }
if (ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = ws.httprequest.soptions.notifyMsgDesktop.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage, ws.tsid); } catch (ex) { }
} else {
@ -2699,7 +2707,7 @@ function kvm_consent_ok(ws) {
ws.httprequest.desktop.kvm.connectionBar.close();
}
try {
ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(ws.httprequest.privacybartext.replaceAll('{0}', ws.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(ws.httprequest.privacybartext.replace(/\{0\}/g, ws.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
} catch (ex) {
MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or not Supported (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
@ -2733,11 +2741,11 @@ function kvm_consent_ok(ws) {
function kvm_consent_ask(ws){
// Send a console message back using the console channel, "\n" is supported.
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['desktopConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username);
var consentMessage = currentTranslation['desktopConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgDesktop != null) { consentMessage = ws.httprequest.soptions.consentMsgDesktop.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); }
if (ws.httprequest.soptions.consentMsgDesktop != null) { consentMessage = ws.httprequest.soptions.consentMsgDesktop.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
}
var pr;
if (process.platform == 'win32') {
@ -2776,6 +2784,10 @@ function kvm_consentpromise_rejected(e)
{
if (this.ws) {
if(this.ws.httprequest){ // User Consent Denied
if ((this.ws.httprequest.oldStyle === true) && (this.ws.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
kvm_consentpromise_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
return;
}
MeshServerLogEx(34, null, "Failed to start remote desktop after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} else { } // Connection was closed server side, maybe log some messages somewhere?
this.ws._consentpromise = null;
@ -2794,12 +2806,12 @@ function kvm_consentpromise_resolved(always)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1))
{
// User Notifications is required
var notifyMessage = currentTranslation['desktopNotify'].replaceAll('{0}', this.ws.httprequest.realname);
var notifyMessage = currentTranslation['desktopNotify'].replace(/\{0\}/g, this.ws.httprequest.realname);
var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null)
{
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); }
if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (ex) { }
}
@ -2813,7 +2825,7 @@ function kvm_consentpromise_resolved(always)
}
try
{
this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replaceAll('{0}', this.ws.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', this.ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replace(/\{0\}/g, this.ws.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, this.ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} catch (ex)
{
@ -2856,11 +2868,11 @@ function files_consent_ok(ws){
if (ws.httprequest.consent && (ws.httprequest.consent & 4)) {
// User Notifications is required
MeshServerLogEx(42, null, "Started remote files with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
var notifyMessage = currentTranslation['fileNotify'].replaceAll('{0}', ws.httprequest.realname);
var notifyMessage = currentTranslation['fileNotify'].replace(/\{0\}/g, ws.httprequest.realname);
var notifyTitle = "MeshCentral";
if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; }
if (ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = ws.httprequest.soptions.notifyMsgFiles.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); }
if (ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = ws.httprequest.soptions.notifyMsgFiles.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
} else {
@ -2872,12 +2884,12 @@ function files_consent_ok(ws){
function files_consent_ask(ws){
// Send a console message back using the console channel, "\n" is supported.
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['fileConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username);
var consentMessage = currentTranslation['fileConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgFiles != null) { consentMessage = ws.httprequest.soptions.consentMsgFiles.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); }
if (ws.httprequest.soptions.consentMsgFiles != null) { consentMessage = ws.httprequest.soptions.consentMsgFiles.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
}
var pr;
if (process.platform == 'win32') {
@ -2923,12 +2935,12 @@ function files_consentpromise_resolved(always)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4))
{
// User Notifications is required
var notifyMessage = currentTranslation['fileNotify'].replaceAll('{0}', this.ws.httprequest.realname);
var notifyMessage = currentTranslation['fileNotify'].replace(/\{0\}/g, this.ws.httprequest.realname);
var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null)
{
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); }
if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
}
@ -2939,6 +2951,10 @@ function files_consentpromise_rejected(e)
{
if (this.ws) {
if(this.ws.httprequest){ // User Consent Denied
if ((this.ws.httprequest.oldStyle === true) && (this.ws.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
files_consentpromise_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
return;
}
MeshServerLogEx(41, null, "Failed to start remote files after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} else { } // Connection was closed server side, maybe log some messages somewhere?
this.ws._consentpromise = null;

View File

@ -2890,7 +2890,7 @@
"items": {
"type": "integer"
},
"description": "This is an array: 1 = Terminal, 2 = Desktop, 5 = Files, 100 = Intel AMT WSMAN, 101 = Intel AMT Redirection, 200 = Messenger"
"description": "This is an array: 1 = Terminal, 2 = Desktop, 5 = Files, 6 = Admin Powershell, 8 = User Shell, 9 = User Powershell, 100 = Intel AMT WSMAN, 101 = Intel AMT Redirection, 200 = Messenger"
}
},
"required": [

View File

@ -997,7 +997,7 @@ function CreateMeshCentralServer(config, args) {
if (err != null) { console.log("Database error: " + err); process.exit(); return; }
if ((docs == null) || (docs.length == 0)) { console.log("Unknown userid, usage: --resetaccount [userid] --domain (domain) --pass [password]."); process.exit(); return; }
const user = docs[0]; if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { user.siteadmin -= 32; } // Unlock the account.
delete user.phone; delete user.otpekey; delete user.otpsecret; delete user.otpkeys; delete user.otphkeys; delete user.otpdev; delete user.otpsms; delete user.otpmsg; // Disable 2FA
delete user.phone; delete user.otpekey; delete user.otpsecret; delete user.otpkeys; delete user.otphkeys; delete user.otpdev; delete user.otpsms; delete user.otpmsg; user.otpduo; // Disable 2FA
delete user.msghandle; // Disable users 2fa messaging too
var config = getConfig(false);
if (config.domains[user.domain].auth || config.domains[user.domain].authstrategies) {

View File

@ -42,6 +42,9 @@ const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// 1 = Terminal
// 2 = Desktop
// 5 = Files
// 6 = Admin PowerShell
// 8 = User Shell
// 9 = User PowerShell
// 10 = Web-RDP
// 11 = Web-SSH
// 12 = Web-VNC
@ -578,7 +581,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
// Log the connection
if (sessionUser != null) {
var msg = 'Started relay session', msgid = 13;
if (obj.req.query.p == 1) { msg = 'Started terminal session'; msgid = 14; }
if ([1,6,8,9].indexOf(obj.req.query.p) >= 0) { msg = 'Started terminal session'; msgid = 14; } // admin shell, admin powershell, user shell, user powershell
else if (obj.req.query.p == 2) { msg = 'Started desktop session'; msgid = 15; }
else if (obj.req.query.p == 5) { msg = 'Started file management session'; msgid = 16; }
else if (obj.req.query.p == 200) { msg = 'Started messenger session'; msgid = 162; }
@ -777,7 +780,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
// Log the disconnection
if (ws.time) {
var msg = 'Ended relay session', msgid = 9;
if (obj.req.query.p == 1) { msg = 'Ended terminal session', msgid = 10; }
if ([1,6,8,9].indexOf(obj.req.query.p) >= 0) { msg = 'Ended terminal session', msgid = 10; } // admin shell, admin powershell, user shell, user powershell
else if (obj.req.query.p == 2) { msg = 'Ended desktop session', msgid = 11; }
else if (obj.req.query.p == 5) { msg = 'Ended file management session', msgid = 12; }
else if (obj.req.query.p == 200) { msg = 'Ended messenger session', msgid = 112; }

View File

@ -1973,6 +1973,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
delete chguser.otpekey; // Email 2FA
delete chguser.phone; // SMS 2FA
delete chguser.otpdev; // Push notification 2FA
delete chguser.otpduo; // Duo 2FA
}
db.SetUser(chguser);

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "1.1.44",
"version": "1.1.45",
"keywords": [
"Remote Device Management",
"Remote Device Monitoring",

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

@ -2300,7 +2300,7 @@
if (idtype == 'devices') { go(2); }
if (idtype == 'files') {
// Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
go(5);
}
}
@ -2583,7 +2583,7 @@
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; }
// Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
// We are allowed, let's prompt to information
var x = addHtmlValue("Name", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
@ -2677,7 +2677,7 @@
function gotoMesh(meshid) {
// Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
currentMesh = meshes[meshid];
if (currentMesh == null) { goBack(); }
p20updateMesh();
@ -3681,7 +3681,7 @@
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; }
// Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
var node = getNodeFromId(nodeid);
if (node == null) { goBack(); return; }
@ -7631,7 +7631,16 @@
function printDateTime(d) { return d.toLocaleString(args.locale); }
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
function nobreak(x) { return x.split(' ').join('&nbsp;'); }
function getUserName(userid) { if (users && users[userid] != null) return users[userid].name; return userid.split('/')[2]; }
function getUserName(userid) {
var useridsplit = userid.split('/'), userid2 = useridsplit[0] + '/' + useridsplit[1] + '/' + useridsplit[2], guestname = '';
if ((useridsplit.length == 4) && (useridsplit[3].startsWith('guest:'))) { guestname = ' - ' + decode_utf8(atob(useridsplit[3].substring(6))); }
if (users && users[userid2] != null) { if (users[userid2].realname != null) return (users[userid2].realname + guestname); else return (users[userid2].name + guestname); }
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname);
}
function addDetailItem(title, value, state) { return '<table style=width:100%><td>' + nobreak(title) + '<td style=text-align:right>' + value + '</table>'; }
function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); }
function encodeURIComponentEx(txt) { return encodeURIComponent(txt).replace(/'/g, '%27'); };

View File

@ -326,7 +326,7 @@
<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 type=button id=ScrollToTopButton onclick="onDevicesScroll(true);" style="display:none;margin-right:4px" value="Scroll To Top" />
<input id=SearchInput type=input autocomplete=off placeholder=Filter onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any"/>&nbsp;
<input id=SearchInput type=input autocomplete=off placeholder=Filter onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx"/>&nbsp;
<span id=SearchInputClearButton style="display:none;position:relative"><img src="images/x16.png" type="button" onclick="clearDeviceSearch()" style="position:absolute;cursor:pointer;left:-18px;top:-8px" srcset="images/x32.png 2x"/></span>
<select id=DevFilterSelect onchange=onOnlineCheckBox(event) title="Device Filter">
<option value=0>All</option>
@ -2368,6 +2368,8 @@
if (userinfo == null) return -1;
var authFactorCount = 0;
if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor
if (userinfo.otpduo == 1) { authFactorCount++; } // Duo factor
if (userinfo.otpdev == 1) { authFactorCount++; } // Push authentication factor
if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor
if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor
if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor
@ -6324,7 +6326,7 @@
function getDevicesThatMatchFilter(x) {
var r = [];
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null;
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null, connectivitySearch = null;
if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); }
else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); }
else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); }
@ -6337,6 +6339,8 @@
else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); }
else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); }
else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); }
else if (x.startsWith("connectivity:".toLowerCase())) { connectivitySearch = x.substring("connectivity:".length); }
else if (x.startsWith("c:".toLowerCase())) { connectivitySearch = x.substring("c:".length); }
else if (x == 'wsc:ok') { wscSearch = 1; }
else if (x == 'wsc:noav') { wscSearch = 2; }
else if (x == 'wsc:noupdate') { wscSearch = 3; }
@ -6387,6 +6391,35 @@
else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); }
}
}
} else if (connectivitySearch != null) {
// Connectivity search
for (var d in nodes) {
if (nodes[d].conn) {
if ((nodes[d].conn & 1) != 0) {
if (nodes[d].mtype == 4) {
if ((nodes[d].porttype == 'PDU') && (connectivitySearch.toLowerCase() == 'switch')) {
r.push(d);
} else if (connectivitySearch.toLowerCase() == 'ipkvm') {
r.push(d);
}
} else if (connectivitySearch.toLowerCase() == 'agent') {
r.push(d);
}
}
if (((nodes[d].conn & 2) != 0) && (connectivitySearch.toLowerCase() == 'cira')) { r.push(d); }
else if (((nodes[d].conn & 4) != 0) && (connectivitySearch.toLowerCase() == 'amt')) { r.push(d); }
if (((nodes[d].conn & 8) != 0) && (connectivitySearch.toLowerCase() == 'relay')) { r.push(d); }
if (((nodes[d].conn & 16) != 0) && (connectivitySearch.toLowerCase() == 'mqtt')) { r.push(d); }
}
if (nodes[d].mtype == 3) {
var mesh = meshes[nodes[d].meshid];
if (mesh && mesh.relayid && (connectivitySearch.toLowerCase() == 'relay')) {
r.push(d);
} else if (mesh && (typeof mesh.relayid == 'undefined') && connectivitySearch.toLowerCase() == 'local') {
r.push(d);
}
}
}
} else if (x == '*') {
// Star filter
for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } }
@ -9852,7 +9885,7 @@
// If shift is pressed, enter browser full screen.
if (e.shiftKey == true) {
enterBrowserFullscreen(Q('container'));
enterBrowserFullscreen(Q('body'));
browserfullscreen = true;
}
} else {
@ -17467,6 +17500,9 @@
if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; }
if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; }
if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; }
if (rec.protocol == 6) { sessionName += ' - ' + "Admin PowerShell"; }
if (rec.protocol == 8) { sessionName += ' - ' + "User Shell"; }
if (rec.protocol == 9) { sessionName += ' - ' + "User PowerShell"; }
if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; }
@ -17497,6 +17533,9 @@
if (rec.protocol == 1) { protocolStr = "Terminal"; }
if (rec.protocol == 2) { protocolStr = "Desktop"; }
if (rec.protocol == 5) { protocolStr = "Files"; }
if (rec.protocol == 6) { protocolStr = "Admin PowerShell"; }
if (rec.protocol == 8) { protocolStr = "User Shell"; }
if (rec.protocol == 9) { protocolStr = "User PowerShell"; }
if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { protocolStr = "Messenger"; }
@ -17839,6 +17878,9 @@
if (v == 1) return "Terminal";
if (v == 2) return "Desktop";
if (v == 5) return "Files";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
@ -17940,7 +17982,17 @@
if (v == 1) return "Terminal";
if (v == 2) return "Desktop";
if (v == 5) return "Files";
return "Unknown";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
if (v == 201) return "Web-RDP";
if (v == 202) return "Web-SSH";
if (v == 203) return "Web-SFTP";
if (v == 204) return "Web-VNC";
return "Unknown" + ' (' + v + ')';
}
if (f == 'node') {
var node = getNodeFromId(v);
@ -19330,6 +19382,7 @@
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname);
}
function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; }

View File

@ -16,7 +16,6 @@
<link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
<link type="text/css" href="styles/flatpickr.min.css" media="screen" rel="stylesheet" title="CSS">
<link id="theme-stylesheet" href="styles/bootstrap{{{min}}}.css" rel="stylesheet" title="CSS">
<link href="styles/sweetalert2.min.css" rel="stylesheet" title="CSS">
<link href="styles/select2.min.css" rel="stylesheet" title="CSS">
<link href="styles/select2-bootstrap-5-theme.min.css" rel="stylesheet" title="CSS">
<link rel="apple-touch-icon" href="/favicon-303x303.png" />
@ -48,7 +47,6 @@
<script type="text/javascript" src="scripts/jquery{{{min}}}.js"></script>
<script type="text/javascript" src="scripts/bootstrap{{{min}}}.js"></script>
<script type="text/javascript" src="scripts/fontawesome/all.min.js"></script>
<script type="text/javascript" src="scripts/sweetalert2.all.min.js"></script>
<script type="text/javascript" src="scripts/select2.full.min.js"></script>
<script type="text/javascript" src="scripts/themes/theme-switcher.js"></script>
<script keeplink=1 type="text/javascript" src="scripts/u2f-api{{{min}}}.js"></script>
@ -415,7 +413,7 @@
<input type=button class="btn btn-primary me-1 btn-sm" id=SelectAllButton onclick="selectallButtonFunction();" value="Select All" />
<input type=button class="btn btn-primary me-1 btn-sm" id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />
<input type=button class="btn btn-primary me-1 btn-sm" id=ScrollToTopButton onclick="onDevicesScroll(true);" value="Scroll To Top" />
<input type="text" id=SearchInput class="form-control-sm me-1 btn-sm" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any">
<input type="text" id=SearchInput class="form-control-sm me-1 btn-sm" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx">
<span id=SearchInputClearButton style="display:none;position:relative">
<span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px">
<i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i>
@ -451,7 +449,7 @@
<input type="button" class="btn btn-primary me-1 btn-sm" onclick="onDevicesScroll(true);" value="Scroll To Top" />
<div class="form-check me-1" title="Automatic connect"><input class="form-check-input me-1" type=checkbox id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" /><label class="form-check-label" for="autoConnectDesktopCheckbox">Auto</label></div>
<input type="button" class="btn btn-primary me-1 btn-sm" onclick="showMultiDesktopSettings()" value="Settings" />
<input type="text" id=KvmSearchInput class="form-control-sm me-1" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any">
<input type="text" id=KvmSearchInput class="form-control-sm me-1" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx">
<span id=KvmSearchInputClearButton style="display:none;position:relative">
<span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px">
<i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i>
@ -2818,6 +2816,8 @@
if (userinfo == null) return -1;
var authFactorCount = 0;
if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor
if (userinfo.otpduo == 1) { authFactorCount++; } // Duo factor
if (userinfo.otpdev == 1) { authFactorCount++; } // Push authentication factor
if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor
if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor
if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor
@ -7008,7 +7008,7 @@
function getDevicesThatMatchFilter(x) {
var r = [];
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null;
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null, connectivitySearch = null;
if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); }
else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); }
else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); }
@ -7021,6 +7021,8 @@
else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); }
else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); }
else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); }
else if (x.startsWith("connectivity:".toLowerCase())) { connectivitySearch = x.substring("connectivity:".length); }
else if (x.startsWith("c:".toLowerCase())) { connectivitySearch = x.substring("c:".length); }
else if (x == 'wsc:ok') { wscSearch = 1; }
else if (x == 'wsc:noav') { wscSearch = 2; }
else if (x == 'wsc:noupdate') { wscSearch = 3; }
@ -7071,6 +7073,35 @@
else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); }
}
}
} else if (connectivitySearch != null) {
// Connectivity search
for (var d in nodes) {
if (nodes[d].conn) {
if ((nodes[d].conn & 1) != 0) {
if (nodes[d].mtype == 4) {
if ((nodes[d].porttype == 'PDU') && (connectivitySearch.toLowerCase() == 'switch')) {
r.push(d);
} else if (connectivitySearch.toLowerCase() == 'ipkvm') {
r.push(d);
}
} else if (connectivitySearch.toLowerCase() == 'agent') {
r.push(d);
}
}
if (((nodes[d].conn & 2) != 0) && (connectivitySearch.toLowerCase() == 'cira')) { r.push(d); }
else if (((nodes[d].conn & 4) != 0) && (connectivitySearch.toLowerCase() == 'amt')) { r.push(d); }
if (((nodes[d].conn & 8) != 0) && (connectivitySearch.toLowerCase() == 'relay')) { r.push(d); }
if (((nodes[d].conn & 16) != 0) && (connectivitySearch.toLowerCase() == 'mqtt')) { r.push(d); }
}
if (nodes[d].mtype == 3) {
var mesh = meshes[nodes[d].meshid];
if (mesh && mesh.relayid && (connectivitySearch.toLowerCase() == 'relay')) {
r.push(d);
} else if (mesh && (typeof mesh.relayid == 'undefined') && connectivitySearch.toLowerCase() == 'local') {
r.push(d);
}
}
}
} else if (x == '*') {
// Star filter
for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } }
@ -10619,7 +10650,7 @@
// If shift is pressed, enter browser full screen.
if (e.shiftKey == true) {
enterBrowserFullscreen(Q('container'));
enterBrowserFullscreen(Q('body'));
browserfullscreen = true;
}
} else {
@ -18733,6 +18764,9 @@
if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; }
if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; }
if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; }
if (rec.protocol == 6) { sessionName += ' - ' + "Admin PowerShell"; }
if (rec.protocol == 8) { sessionName += ' - ' + "User Shell"; }
if (rec.protocol == 9) { sessionName += ' - ' + "User PowerShell"; }
if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; }
@ -18763,6 +18797,9 @@
if (rec.protocol == 1) { protocolStr = "Terminal"; }
if (rec.protocol == 2) { protocolStr = "Desktop"; }
if (rec.protocol == 5) { protocolStr = "Files"; }
if (rec.protocol == 6) { protocolStr = "Admin PowerShell"; }
if (rec.protocol == 8) { protocolStr = "User Shell"; }
if (rec.protocol == 9) { protocolStr = "User PowerShell"; }
if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { protocolStr = "Messenger"; }
@ -19109,6 +19146,9 @@
if (v == 1) return "Terminal";
if (v == 2) return "Desktop";
if (v == 5) return "Files";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
@ -19210,7 +19250,17 @@
if (v == 1) return "Terminal";
if (v == 2) return "Desktop";
if (v == 5) return "Files";
return "Unknown";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
if (v == 201) return "Web-RDP";
if (v == 202) return "Web-SSH";
if (v == 203) return "Web-SFTP";
if (v == 204) return "Web-VNC";
return "Unknown" + ' (' + v + ')';
}
if (f == 'node') {
var node = getNodeFromId(v);
@ -20649,6 +20699,7 @@
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname);
}
function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; }

View File

@ -401,6 +401,9 @@
var p = recFileMetadata.protocol;
if (p == 1) { p = "MeshCentral Terminal"; }
else if (p == 2) { p = "MeshCentral Desktop"; }
else if (p == 6) { p = "Admin PowerShell"; }
else if (p == 8) { p = "User Shell"; }
else if (p == 9) { p = "User PowerShell"; }
else if (p == 100) { p = "Intel&reg; AMT WSMAN"; }
else if (p == 101) { p = "Intel&reg; AMT Redirection"; }
else if ((p == 102) || (p == 200 && recFileMetadata.bpp != null)) { p = "Intel&reg; AMT KVM"; }
@ -427,7 +430,7 @@
QV('TermParent', false);
QV('XTermParent', false);
QV('ConvertAsWebM', false);
if (recFileMetadata.protocol == 1) {
if ((recFileMetadata.protocol == 1) || (recFileMetadata.protocol == 6) || (recFileMetadata.protocol == 8) || (recFileMetadata.protocol == 9)) {
// MeshCentral remote terminal
recFileProtocol = 1;
x += '<br /><br /><span style=color:gray>' + "Press [space] to play/pause." + '</span>';