This commit is contained in:
Ylian Saint-Hilaire 2024-03-03 11:13:32 -08:00
commit c937764980
14 changed files with 3045 additions and 2476 deletions

49
SECURITY.md Normal file
View File

@ -0,0 +1,49 @@
# Security Policy
## Supported Versions
Any version of MeshCentral 1.x.x is supported.
| Version | Supported |
| ------- | ------------------ |
| 1.x.x | :white_check_mark: |
| < 1.0 | :x: |
## Reporting a Vulnerability
Please report any concerns or security issue to Ylian Saint-Hilaire (ylianst@gmail.com). If needed, use my PGP key below.
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG v1.56
mQMuBF2gC4sRCAClFNvMCCVW3ego3UHBQ6LhSenJfaZYhvn8gaGuemSQxqTI6bla
BTAv3aMtQnvqlSuadMMegb+FO6hnaQMlGvpVA1qpkSzgrPS5HrBD3H33J2Nj3i93
ZpDPpxdI0ehCj6IJPnl0GxGbpKIN8YpJUFl44wv1lMRFI1lgyb+dCoO60irYdNQB
PV85BI+DwPfOBFHunwR78nqMvpvsk9HaeHjEP7oXr952/7EazUowZsMlEfkYnw5S
+tLfpCoY3QWkektpJP40nMJSKQdV2NEuED99doA0X+7P1vsvFFFyMH69dnU2uSay
XCHpkAbntBy0BGmtF1RnTcOMv2V/LPXnlMdvAQCbmLQzNra3r163tcdRY0jSs+pZ
1L3w5tHNj2dzhfpa7wf/SIuds6QTr2LCN6miLoSVCRMMpT7d771b16GwQqWEXzN2
+h7dYqrssHPOa8FSUrPerz0+0eFcbMSm5/L/4KXWXoQthURv8aMP9E0iVoUYaaKB
7U+5vFEZbpoOZyZmTAjXQMSNZCft0azA82Q+G85euyicWtMv48yNVzUhkdh+M2ud
ohkXX2Aor1TqpBJoIeWke7j9D+Bo+lu61zPRx5ed9teUeLJCwqNEjlE+6gre5kxF
PoreAtn59QYcBIpzQEWVMbNFlDAR4jMyqIoKCGfBPiRw2V+kunbzqiGQEglIFfOt
6sTN/+CJh0ei976VDmE0Z1kMN+CNLgIjIw8fl02V9QgAnHcpqtVUxR4dbGOhVDq5
lWv+K75QQlWyXC2k+KboXcaCvH0WZEBACYzO0CfrZ5hP9BSkbj5usSUVGGHwEFAJ
t+/04KVY71fW281Ej5kGNaIKxeKsx6+hMo+UXb5ZM+6fANNNxs1cK95sTH6PjkyB
tsKxLoa3CV2v9mSE5JiKKt74R9nXVo7PXf6DizwAU2l30Lb6y6y0OdXdCCPAG8Ij
FrMgPu5MtjgsO5DnkZfUqDPWHhOgEPyOh3Ho+pvDhNYh5cm2eLQ8g5orzs2FHwbZ
DpAHwCdqrlcpBlKJ4W/MZdf1fg2PjqaTWm7ZFiGr91P0F6kltTLWbVKTjLdS0T+D
L7QnWWxpYW4gU2FpbnQtSGlsYWlyZSA8eWxpYW5zdEBnbWFpbC5jb20+iF4EExEI
AAYFAl2gC4sACgkQg7j/r4DH+kD/3gD+MRedlM53VzOtNOpS6mqDAxj1aWP90HN0
AqO6zuCTyGgBAJlunLFKH8IUetmQOhiohB8HVhdm/q4lKRDV7sHdplDyuMwEXaAL
ixACAJSU/sCV87he4oZUKzg2/IGl3QoDSbTCOd04dE1IjPjjHbi8t9M7Qau55aM8
ypFEsc7zMslL8Fc78EejrKmM3zsB/RU9XWFyrbQwRbaK6OHeEHC2E3AFaG0p09c6
d0kZloHuWyEsm5a/3PpbIM1eP9IESJXWCc+bQQt6DxLKHLmkKMwB/icWMg8uMJlx
aady8TEq7LH5oFVKsglnwuN1nIkecrf77TVkEqTjIxS6TiOup6zOnioFNKLYBAH0
WUnJEYFvx4OIXgQYEQgABgUCXaALiwAKCRCDuP+vgMf6QGFTAQCUj2gGwsFlN0eR
Wowv4eLcc3FwQ+lBElUctKg8vNFb0gD/ZWVWsWwKerNgNnf7RGD9mt8G2CKvdgGG
oZ2hPP2gU9w=
=roW4
-----END PGP PUBLIC KEY BLOCK-----
```

Binary file not shown.

View File

@ -3438,6 +3438,24 @@ function onTunnelData(data)
this.zip.on('progress', require('events').moderated(function (name, p) { this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'zippingFile', file: ((process.platform == 'win32') ? (name.split('/').join('\\')) : name), progress: p }))); }, 1000));
this.zip.pipe(out);
break;
case 'unzip':
if (this.unzip != null) return; // Unzip operating is currently running, exit now.
this.unzip = require('zip-reader').read(cmd.input);
this.unzip._dest = cmd.dest;
this.unzip.xws = this;
this.unzip.then(function (zipped) {
this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unzipping' })));
zipped.xws = this.xws;
zipped.extractAll(this._dest).then(function () { // finished extracting
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: null })));
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'refresh' })));
delete zipped.xws.unzip;
}, function (e) { // error extracting
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unziperror', error: e })));
delete zipped.xws.unzip;
});
}, function (e) { this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unziperror', error: e }))); delete this.xws.unzip });
break;
case 'cancel':
// Cancel zip operation if present
try { this.zipcancel = true; this.zip.cancel(function () { }); } catch (ex) { }
@ -4251,8 +4269,8 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
} else {
var p = args['_'].join(' ').split(',');
if (p.length != 2) { response = "Proper usage: unzip input,destination"; break; } // Display usage
var prom = require('zip-reader').read(p[0]);
prom._dest = p[1];
var prom = require('zip-reader').read(p[0].trim());
prom._dest = p[1].trim();
prom.self = this;
prom.sessionid = sessionid;
prom.then(function (zipped) {
@ -4733,8 +4751,11 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
}
case 'sysinfo': { // Return system information
getSystemInformation(function (results, err) {
if (results == null) { sendConsoleText(err, this.sessionid); } else {
if (results == null) {
sendConsoleText(err, this.sessionid);
} else {
sendConsoleText(JSON.stringify(results, null, 1), this.sessionid);
mesh.SendCommand({ action: 'sysinfo', sessionid: this.sessionid, data: results });
}
});
break;
@ -5723,9 +5744,11 @@ function cleanGetBitLockerVolumeInfo(volumes) {
for (var i in volumes) {
const v = volumes[i];
if (typeof v.size == 'string') { v.size = parseInt(v.size); }
if (typeof v.sizeremaining == 'string') { v.sizeremaining = parseInt(v.sizeremaining); }
if (v.identifier == '') { delete v.identifier; }
if (v.name == '') { delete v.name; }
if (v.removable != true) { delete v.removable; }
if (v.cdrom != true) { delete v.cdrom; }
if (v.protectionStatus == 'On') { v.protectionStatus = true; } else { delete v.protectionStatus; }
if (v.volumeStatus == 'FullyDecrypted') { delete v.volumeStatus; }
if (v.recoveryPassword == '') { delete v.recoveryPassword; }

View File

@ -390,7 +390,7 @@ function windows_volumes()
p1.child = child;
child.promise = p1;
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('Get-Volume | Select-Object -Property DriveLetter,FileSystemLabel,FileSystemType,Size,DriveType | ConvertTo-Csv -NoTypeInformation\nexit\n');
child.stdin.write('Get-Volume | Select-Object -Property DriveLetter,FileSystemLabel,FileSystemType,Size,SizeRemaining,DriveType | ConvertTo-Csv -NoTypeInformation\nexit\n');
child.on('exit', function (c)
{
var a, i, tokens, key;
@ -407,7 +407,9 @@ function windows_volumes()
name: tokens[1].split('"')[1],
type: tokens[2].split('"')[1],
size: tokens[3].split('"')[1],
removable: tokens[4].split('"')[1] == 'Removable'
sizeremaining: tokens[4].split('"')[1],
removable: tokens[5].split('"')[1] == 'Removable',
cdrom: tokens[5].split('"')[1] == 'CD-ROM'
};
}
}
@ -447,12 +449,14 @@ function windows_volumes()
var abc = lines[x].trim();
var englishidpass = (abc !== '' && abc.includes('Numerical Password:')); // English ID
var germanidpass = (abc !== '' && abc.includes('Numerisches Kennwort:')); // German ID
var frenchidpass = (abc !== '' && abc.includes('Mot de passe num')); // French ID
var englishpass = (abc !== '' && abc.includes('Password:') && !abc.includes('Numerical Password:')); // English Password
var germanpass = (abc !== '' && abc.includes('Kennwort:') && !abc.includes('Numerisches Kennwort:')); // German Password
if (englishidpass || germanidpass || englishpass || germanpass) {
var frenchpass = (abc !== '' && abc.includes('Mot de passe :') && !abc.includes('Mot de passe num')); // French Password
if (englishidpass || germanidpass || frenchidpass|| englishpass || germanpass || frenchpass) {
var nextline = lines[x + 1].trim();
if (x + 1 < lines.length && (nextline !== '' && nextline.startsWith('ID:'))) {
identifier = nextline.replace('ID:','').trim();
if (x + 1 < lines.length && (nextline !== '' && (nextline.startsWith('ID:') || nextline.startsWith('ID :')) )) {
identifier = nextline.replace('ID:','').replace('ID :', '').trim();
foundIDMarkedLine = true;
}else if (x + 1 < lines.length && nextline !== '') {
password = nextline;
@ -559,7 +563,7 @@ function windows_identifiers()
}
function macos_identifiers()
{
var ret = { identifiers: {} };
var ret = { identifiers: {}, darwin: {} };
var child;
child = require('child_process').execFile('/bin/sh', ['sh']);
@ -598,6 +602,84 @@ function macos_identifiers()
child.waitExit();
ret.identifiers.cpu_name = child.stdout.str.trim();
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('system_profiler SPMemoryDataType\nexit\n');
child.waitExit();
var lines = child.stdout.str.trim().split('\n');
if(lines.length > 0) {
const memorySlots = [];
if(lines[2].trim().includes('Memory Slots:')) { // OLD MACS WITH SLOTS
const Memory = [];
const bankMatches = child.stdout.str.trim().match(/BANK \d+\/DIMM\d+:[\s\S]*?(?=(BANK|$))/g);
bankMatches.forEach(function(match, index) {
const bankInfo = match.match(/BANK (\d+)\/DIMM(\d+):[\s\S]*?Size: (\d+ \w+)[\s\S]*?Type: (\w+)[\s\S]*?Speed: (\d+ \w+)[\s\S]*?Status: (\w+)[\s\S]*?Manufacturer: (0x[0-9A-Fa-f]+)[\s\S]*?Part Number: (0x[0-9A-Fa-f]+)[\s\S]*?Serial Number: (.+)/);
if (bankInfo) {
const bankIndex = bankInfo[1].trim();
const dimmIndex = bankInfo[2].trim();
const size = bankInfo[3].trim();
const type = bankInfo[4].trim();
const speed = bankInfo[5].trim();
const status = bankInfo[6].trim();
const manufacturer = bankInfo[7].trim();
const partNumber = bankInfo[8].trim();
const serialNumber = bankInfo[9].trim();
Memory.push({
DeviceLocator: "BANK " + bankIndex + "/DIMM" + dimmIndex,
Size: size,
Type: type,
Speed: speed,
Status: status,
Manufacturer: hexToAscii(manufacturer),
PartNumber: hexToAscii(partNumber),
SerialNumber: serialNumber,
});
}
});
memorySlots = Memory;
} else { // NEW MACS WITHOUT SLOTS
memorySlots.push({ DeviceLocator: "Onboard Memory", Size: lines[2].split(":")[1].trim(), PartNumber: lines[3].split(":")[1].trim(), Manufacturer: lines[4].split(":")[1].trim() })
}
ret.darwin.memory = memorySlots;
}
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('diskutil info -all\nexit\n');
child.waitExit();
var sections = child.stdout.str.split('**********\n');
if(sections.length > 0){
var devices = [];
for (var i = 0; i < sections.length; i++) {
var lines = sections[i].split('\n');
var deviceInfo = {};
var wholeYes = false;
var physicalYes = false;
var oldmac = false;
for (var j = 0; j < lines.length; j++) {
var keyValue = lines[j].split(':');
var key = keyValue[0].trim();
var value = keyValue[1] ? keyValue[1].trim() : '';
if (key === 'Virtual') oldmac = true;
if (key === 'Whole' && value === 'Yes') wholeYes = true;
if (key === 'Virtual' && value === 'No') physicalYes = true;
if(value && key === 'Device / Media Name'){
deviceInfo['Caption'] = value;
}
if(value && key === 'Disk Size'){
deviceInfo['Size'] = value.split(' ')[0] + ' ' + value.split(' ')[1];
}
}
if (wholeYes) {
if (oldmac) {
if (physicalYes) devices.push(deviceInfo);
} else {
devices.push(deviceInfo);
}
}
}
ret.identifiers.storage_devices = devices;
}
trimIdentifiers(ret.identifiers);
@ -606,6 +688,17 @@ function macos_identifiers()
return (ret);
}
function hexToAscii(hexString) {
hexString = hexString.startsWith('0x') ? hexString.slice(2) : hexString;
var str = '';
for (var i = 0; i < hexString.length; i += 2) {
var hexPair = hexString.substr(i, 2);
str += String.fromCharCode(parseInt(hexPair, 16));
}
str = str.replace(/[\u007F-\uFFFF]/g, ''); // Remove characters from 0x0080 to 0xFFFF
return str.trim();
}
function win_chassisType()
{
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'SystemEnclosure', 'get', 'ChassisTypes']);

View File

@ -879,6 +879,7 @@ if (args['_'].length == 0) {
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --start " + localISOTime + " --duration 30"));
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --start " + localISOTime + " --duration 30 --daily"));
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type desktop,terminal --consent prompt"));
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type http --port 80"));
console.log("\r\nRequired arguments:\r\n");
if (process.platform == 'win32') {
console.log(" --id [deviceid] - The device identifier.");
@ -888,14 +889,15 @@ if (args['_'].length == 0) {
console.log("\r\nOptional arguments:\r\n");
console.log(" --remove [shareid] - Remove a device sharing link.");
console.log(" --add [guestname] - Add a device sharing link.");
console.log(" --type [desktop,terminal,files] - Type of sharing to add, can be combined. default is desktop.");
console.log(" --type [desktop,terminal,files,http,https] - Type of sharing to add, can be combined. default is desktop.");
console.log(" --viewonly - Make desktop sharing view only.");
console.log(" --consent [notify,prompt] - Consent flags, default is notify.");
console.log(" --consent [notify,prompt,none] - Consent flags, default is notify.");
console.log(" --start [yyyy-mm-ddThh:mm:ss] - Start time, default is now.");
console.log(" --end [yyyy-mm-ddThh:mm:ss] - End time.");
console.log(" --duration [minutes] - Duration of the share, default is 60 minutes.");
console.log(" --daily - Add recurring daily device share.");
console.log(" --weekly - Add recurring weekly device share.");
console.log(" --port [portnumber] - Set alternative port for http or https, default is 80 for http and 443 for https.");
break;
}
case 'agentdownload': {
@ -1707,10 +1709,12 @@ function serverConnect() {
var p = 0;
if (args.type != null) {
var shareTypes = args.type.toLowerCase().split(',');
for (var i in shareTypes) { if ((shareTypes[i] != 'terminal') && (shareTypes[i] != 'desktop') && (shareTypes[i] != 'files')) { console.log("Unknown sharing type: " + shareTypes[i]); process.exit(1); } }
for (var i in shareTypes) { if ((shareTypes[i] != 'terminal') && (shareTypes[i] != 'desktop') && (shareTypes[i] != 'files') && (shareTypes[i] != 'http') && (shareTypes[i] != 'https')) { console.log("Unknown sharing type: " + shareTypes[i]); process.exit(1); } }
if (shareTypes.indexOf('terminal') >= 0) { p |= 1; }
if (shareTypes.indexOf('desktop') >= 0) { p |= 2; }
if (shareTypes.indexOf('files') >= 0) { p |= 4; }
if (shareTypes.indexOf('http') >= 0) { p |= 8; }
if (shareTypes.indexOf('https') >= 0) { p |= 16; }
}
if (p == 0) { p = 2; } // Desktop
@ -1745,6 +1749,19 @@ function serverConnect() {
}
}
var port = null;
// Set Port Number if http or https
if ((p & 8) || (p & 16)) {
if (typeof args.port == 'number') {
if ((args.port < 1) || (args.port > 65535)) { console.log("Port number must be between 1 and 65535."); process.exit(1); }
port = args.port;
} else if ((p & 8)) {
port = 80;
} else if ((p & 16)) {
port = 443;
}
}
// Start and end time
var start = null, end = null;
if (args.start) { start = Math.floor(Date.parse(args.start) / 1000); end = start + (60 * 60); }
@ -1761,14 +1778,14 @@ function serverConnect() {
if ((typeof args.duration != 'number') || (args.duration < 1)) { console.log("Invalid duration value."); process.exit(1); return; }
// Recurring sharing
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, expire: args.duration, recurring: recurring, viewOnly: viewOnly, responseid: 'meshctrl' }));
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, expire: args.duration, recurring: recurring, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
} else {
if ((start == null) && (end == null)) {
// Unlimited sharing
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, expire: 0, viewOnly: viewOnly, responseid: 'meshctrl' }));
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, expire: 0, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
} else {
// Time limited sharing
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, end: end, viewOnly: viewOnly, responseid: 'meshctrl' }));
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, end: end, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
}
}
} else if (args.remove) {

View File

@ -4304,7 +4304,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
}
// If we have view only remote desktop rights, force view-only on the guest share.
if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_REMOTEVIEWONLY) != 0)) { command.viewOnly = true; command.p = (command.p & 1); }
if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_REMOTEVIEWONLY) != 0)) { command.viewOnly = true; }
// Create cookie
var publicid = getRandomPassword(), startTime = null, expireTime = null, duration = null;

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "meshcentral",
"version": "1.1.20",
"version": "1.1.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "meshcentral",
"version": "1.1.20",
"version": "1.1.21",
"license": "Apache-2.0",
"dependencies": {
"@yetzt/nedb": "1.8.0",

View File

@ -1311,6 +1311,10 @@ NoMeshesPanel img {
width: 250px;
}
#d2netinfo .dialogText {
padding-right: 10px;
}
#p12warning, #p12warning2, #p11warning, #p11warning2 {
max-width: 100%;
display: none;

View File

@ -8,6 +8,7 @@
const fs = require('fs');
const path = require('path');
const os = require('os');
//const zlib = require('zlib');
var performCheck = false;
var translationTable = null;
@ -563,13 +564,13 @@ function totext(source, target, lang) {
if (splitOutputPtr == 1) {
// Save the target back
fs.writeFileSync(target + '-' + lang + '.txt', output.join('\r\n'), { flag: 'w+' });
fs.writeFileSync(target + '-' + lang + '.txt', output.join(os.EOL), { flag: 'w+' });
log('Done.');
} else {
// Save the text in 1000 string bunches
for (var i in splitOutput) {
log('Writing ' + target + '-' + lang + '-' + i + '.txt...');
fs.writeFileSync(target + '-' + lang + '-' + i + '.txt', splitOutput[i].join('\r\n'), { flag: 'w+' });
fs.writeFileSync(target + '-' + lang + '-' + i + '.txt', splitOutput[i].join(os.EOL), { flag: 'w+' });
}
log('Done.');
}
@ -585,7 +586,7 @@ function fromtext(source, target, lang) {
// Read raw text
var rawText = fs.readFileSync(target).toString('utf8');
var rawTextArray = rawText.split('\r\n');
var rawTextArray = rawText.split(/\r?\n/);
var rawTextPtr = 0;
log('Translation file: ' + sourceLangFileData.strings.length + ' string(s)');
@ -733,7 +734,7 @@ function extract(langFile, sources) {
function extractFromTxt(file) {
log("Processing TXT: " + path.basename(file));
var lines = fs.readFileSync(file).toString().split('\r\n');
var lines = fs.readFileSync(file).toString().split(/\r?\n/);
var name = path.basename(file);
for (var i in lines) {
var line = lines[i];
@ -847,7 +848,7 @@ function getStringFromJavaScript(name, script) {
function translateFromTxt(lang, file, createSubDir) {
log("Translating TXT (" + lang + "): " + path.basename(file));
var lines = fs.readFileSync(file).toString().split('\r\n'), outlines = [];
var lines = fs.readFileSync(file).toString().split(/\r?\n/), outlines = [];
for (var i in lines) {
var line = lines[i];
if ((line.length > 1) && (line[0] != '~')) {
@ -857,7 +858,7 @@ function translateFromTxt(lang, file, createSubDir) {
}
}
var outname = file, out = outlines.join('\r\n');
var outname = file, out = outlines.join(os.EOL);
if (createSubDir != null) {
var outfolder = path.join(path.dirname(file), createSubDir);
if (fs.existsSync(outfolder) == false) { fs.mkdirSync(outfolder); }

File diff suppressed because it is too large Load Diff

View File

@ -81,8 +81,8 @@
<div class="tab">
<button id="twintab64" class="tablinks" onclick="openTab(event, 'wintab64')">Windows 64bit</button>
<button id="twintab32" class="tablinks" onclick="openTab(event, 'wintab32')">Windows 32bit</button>
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux</button>
<button id="tlinuxbinarytab" class="tablinks" onclick="openTab(event, 'linuxbinarytab')">Linux Binary</button>
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux / BSD Scripts</button>
<button id="tlinuxbinarytab" class="tablinks" onclick="openTab(event, 'linuxbinarytab')">Linux / BSD / macOS Binary</button>
<button id="tmacostab" class="tablinks" onclick="openTab(event, 'macostab')">MacOS</button>
<button id="tandrotab" class="tablinks" onclick="openTab(event, 'androtab')">Android</button>
<button id="tassistab" class="tablinks" onclick="openTab(event, 'assistab')">Assistant</button>
@ -253,7 +253,7 @@
}
function linuxBinarySetup() {
var x = '<h3>Linux Binary</h3>', moreoptions = '';
var x = '<h3>' + "Linux / BSD / macOS Binary Installer" + '</h3>', moreoptions = '';
var opts = '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px>';
opts += '<option value=5 selected>' + "Linux / BSD / macOS Binary Installer" + '</option>';
opts += '</select>';
@ -261,8 +261,8 @@
var servername = window.location.hostname;
if ((servername.indexOf('.') == -1)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
var portStr = (serverPort == 443) ? '' : (':' + serverPort);
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41 ];
var binaryInstallAgents = { 5 : 'Linux x86-32', 6 : 'Linux x86-64', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)' };
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41, 16, 29 ];
var binaryInstallAgents = { 6 : 'Linux x86-64', 5 : 'Linux x86-32', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)', 16: 'Apple macOS x86-64', 29: 'Apple macOS ARM-64' };
for (var i in binaryInstallAgentsOrder) { moreoptions += '<option value=' + binaryInstallAgentsOrder[i] + '>' + binaryInstallAgents[binaryInstallAgentsOrder[i]] + '</option>' }
x += '<div id=aginsSysTypeDiv>';
x += addHtmlValue("System Type", '<select id=aginsSysType onchange=addAgentToMeshClick() style=width:236px>' + moreoptions + '</select>');

View File

@ -5917,21 +5917,6 @@
x += addDetailItem("Antivirus", y.join('<br />'));
}
// Volumes and Bitlocker
if (node.volumes){
var bitlocker = [];
for (var i in node.volumes) {
if (typeof node.volumes[i].protectionStatus !== 'undefined' && node.volumes[i].protectionStatus == 'On'){
bitlocker.push(i + ' - <span style=color:green>' + node.volumes[i].volumeStatus + '</span>');
}else if (typeof node.volumes[i].protectionStatus !== 'undefined'){
bitlocker.push(i + ' - <span style=color:red>' + node.volumes[i].volumeStatus + '</span>');
}
}
if(bitlocker.length > 0){
x += addDetailItem("BitLocker", bitlocker.join('<br />'));
}
}
if (x != '') { sections.push({ name: "Operating System", html: x, img: 'software' }); }
}
@ -6073,9 +6058,9 @@
if (tpm.SpecVersion) { x += addDetailItem("SpecVersion", parseFloat(EscapeHtml(tpm.SpecVersion)).toFixed(1), s); }
if (tpm.ManufacturerId) { x += addDetailItem("ManufacturerId", EscapeHtml(tpm.ManufacturerId), s); }
if (tpm.ManufacturerVersion) { x += addDetailItem("ManufacturerVersion", EscapeHtml(tpm.ManufacturerVersion), s); }
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", EscapeHtml(tpm.IsActivated), s); }
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", EscapeHtml(tpm.IsEnabled), s); }
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", EscapeHtml(tpm.IsOwned), s); }
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", (tpm.IsActivated ? "Yes" : "No"), s); }
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", (tpm.IsEnabled ? "Yes" : "No"), s); }
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", (tpm.IsOwned ? "Yes" : "No"), s); }
if (x != '') { sections.push({ name: "TPM", html: x, img: 'tpm'}); }
}
@ -6124,6 +6109,26 @@
}
}
if (hardware.darwin) {
if (hardware.darwin.memory && (hardware.darwin.memory.length > 0)) {
var x = '';
x += '<table style=width:100%>';
for (var i in hardware.darwin.memory) {
var m = hardware.darwin.memory[i];
if(m.Size && (m.Size == 'No Module Installed')) continue;
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
x += '<div style=margin-bottom:3px><b>' + EscapeHtml((m.DeviceLocator ? m.DeviceLocator : 'Unknown')) + '</b></div>';
if (m.Size && m.Speed) { x += addDetailItem("Capacity / Speed", format("{0}, {1}", m.Size, m.Speed), s); }
else if (m.Size) { x += addDetailItem("Capacity", format("{0}", (m.Size)), s); }
console.log(m.Manufacturer);
if (m.PartNumber) { x += addDetailItem("Part Number", EscapeHtml((m.Manufacturer && m.Manufacturer != '')?(m.Manufacturer + ', '):'') + EscapeHtml(m.PartNumber), s); }
x += '</div>';
}
x += '</table>';
if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram'}); }
}
}
// Storage
if (hardware.identifiers && ident.storage_devices) {
var x = '';
@ -6154,6 +6159,45 @@
if (x != '') { sections.push({ name: "Storage", html: x, img: 'storage' }); }
}
// Volumes and Bitlocker
if (hardware.windows && hardware.windows.volumes) {
var x = '';
for (var i in hardware.windows.volumes) {
var m = hardware.windows.volumes[i];
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
x += '<div style=margin-bottom:3px><b>' + i + ':' + (((m.name == null) || (m.name == '')) ? '' : (' - ' + EscapeHtml(m.name))) + '</b></div>';
if (m.size) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
var j = parseInt(Math.floor(Math.log(Math.abs(m.size)) / Math.log(1024)), 10);
var fsize = (j === 0 ? `${m.size} ${sizes[j]}` : `${(m.size / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
x += addDetailItem("Capacity", EscapeHtml(fsize), s);
}
if (m.sizeremaining) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
var j = parseInt(Math.floor(Math.log(Math.abs(m.sizeremaining)) / Math.log(1024)), 10);
var fsize = (j === 0 ? `${m.sizeremaining} ${sizes[j]}` : `${(m.sizeremaining / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
x += addDetailItem("Capacity Remaining", EscapeHtml(fsize), s);
}
if (m.type) {
var type = (m.removable == true ? "Removable" : (m.cdrom == true ? "CD-ROM" : ''));
x += addDetailItem("File System", (type != '' ? (type + ' / ') : '') + (m.type == 'Unknown' ? "Unknown" : EscapeHtml(m.type)), s);
}
if (m.protectionStatus || m.volumeStatus) {
var bitlockerState = [];
if (m.protectionStatus) bitlockerState.push("Enabled");
if (m.volumeStatus && m.volumeStatus == 'FullyDecrypted') bitlockerState.push("Fully Decrypted");
if (m.volumeStatus && m.volumeStatus == 'EncryptionInProgress') bitlockerState.push("Encryption In Progress");
if (m.volumeStatus && m.volumeStatus == 'FullyEncrypted') bitlockerState.push("Fully Encrypted");
bitlockerState = bitlockerState.join(' - ');
if (m.recoveryPassword) { bitlockerState += addKeyLink('', 'deviceDetailsShowBitlockerInfo(\"' + encodeURIComponentEx(i) + '\",\"' + encodeURIComponentEx(m.identifier) + '\",\"' + encodeURIComponentEx(m.recoveryPassword) + '\")'); }
x += addDetailItem("BitLocker", bitlockerState, s);
}
x += '</div>';
}
if (x != '') { sections.push({ name: "Storage Volumes", html: '<table style=width:100%>' + x + '</table>', img: 'storage'}); }
}
// Render the sections
var x = '';
for (var i in sections) {
@ -6174,6 +6218,13 @@
}
}
function deviceDetailsShowBitlockerInfo(drive, identifier, password) {
if (xxdialogMode) return false;
var x = '<div><p>' + "Identifier" + '</p><p style=user-select:text;font-weight:bold>' + (identifier ? decodeURIComponent(identifier) : "Unknown") + '</p>';
x += '<p>' + "Recovery Password" + '</p><p style=user-select:text;font-weight:bold>' + (password ? decodeURIComponent(password) : "Unknown") + '</p></div>';
setDialogMode(2, decodeURIComponent(drive) + ': ' + "BitLocker Information", 1, null, x, '');
}
//
// CONSOLE
@ -7116,6 +7167,8 @@
function addHtmlValue4(t, v) { return '<table style=width:100%><td style=width:120px>' + t + '<td style=text-align:right><b>' + v + '</b></table>'; }
function addLink(x, f) { return '<a style=cursor:pointer;text-decoration:none onclick=\'' + f + '\'>&diams; ' + x + '</a>'; }
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
function addKeyLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=' + f + ' onkeypress="if (event.key==\'Enter\') { ' + f + ' } ">' + x + ' <img class=hoverButton src=images/key16.png></span>'; }
function addKeyLinkConditional(x, f, c) { if (c) return addKeyLink(x, f); return x; }
function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
function getFileSizeStr(size) { if (typeof size != 'number') { size = 0; } if (size == 1) return "1 byte"; return format('{0} bytes', size); }
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }

View File

@ -684,6 +684,7 @@
<input id="deskActionsBtn" type=button title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() class="mR" />
<input id="deskActionsSettings" type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR" />
<input type="button" title="Change the power state of the remote machine" onkeypress="return false" onkeydown="return false" value="Power Actions..." onclick="showPowerActionDlg()" style="display:none" />
<div id="desktopCustomUpperRight" style="float:left;margin-right:6px"></div>
<div id="desktopCustomUiButtons" style="float:left"></div>
</div>
<div>
@ -868,6 +869,7 @@
<input type=button style="margin-right:2px" disabled="disabled" id=p13CopyButton value="Copy" onclick="p13copyFile(0)" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13PasteButton value="Paste" onclick="p13pasteFile()" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13ZipButton value="Zip" onclick="p13zipFiles()" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13UnzipButton value="Unzip" onclick="p13unzipFile()" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13RefreshButton value="Refresh" onclick="p13folderup(9999)" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13FindButton value="Find" onclick="p13findfile()" />
<input type=button style="margin-right:2px" disabled="disabled" id=p13GoToFolderButton value="GoTo" onclick="p13gotofolder()" />
@ -2329,7 +2331,23 @@
function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
function checkIdleSessionTimeout() {
var delta = (Date.now() - sessionActivity);
if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
if (delta > serverinfo.timeout) {
if (desktop != null) { // Disconnect remote desktop
desktop.Stop();
webRtcDesktopReset();
desktopNode = desktop = null;
if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
}
if (terminal != null) { // Disconnect terminal
terminal.Stop();
terminal = null;
}
if (files != null) { // Disconnect files
files.Stop();
files = null;
}
window.location.href = 'logout';
} else {
var ds = Math.round((serverinfo.timeout - delta) / 1000);
if (ds <= 60) {
QH('idleTimeoutNotify', '<br />' + format((ds == 1)?"1 second until disconnect":"{0} seconds until disconnect", ds));
@ -5435,8 +5453,8 @@
if (serverinfo.https == true) { portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port); } else { portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port); }
// Add Linux/macOS binary installer option
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41 ];
var binaryInstallAgents = { 5 : 'Linux x86-32', 6 : 'Linux x86-64', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)' };
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41, 16, 29 ];
var binaryInstallAgents = { 6 : 'Linux x86-64', 5 : 'Linux x86-32', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)', 16: 'Apple macOS x86-64', 29: 'Apple macOS ARM-64' };
for (var i in binaryInstallAgentsOrder) { moreoptions += '<option value=' + binaryInstallAgentsOrder[i] + '>' + binaryInstallAgents[binaryInstallAgentsOrder[i]] + '</option>' }
x += '<div id=aginsSysTypeDiv>';
x += addHtmlValue("System Type", '<select id=aginsSysType onchange=addAgentToMeshClick() style=width:236px>' + moreoptions + '</select>');
@ -7538,9 +7556,9 @@
x += '<input type=button value="' + "Log Event" + '" title="' + "Write an event for this device" + '" onclick=writeDeviceEvent("' + encodeURIComponentEx(node._id) + '") />';
if ((node.mtype == 2) && (connectivity & 1) && ((meshrights & 131072) != 0)) { x += '<input type=button cmenu=deskPreConfigScriptContextMenu value="' + "Run" + '" title="' + "Run commands on this device" + '" onclick=runDeviceCmd("' + encodeURIComponentEx(node._id) + '") />'; }
if (node.mtype != 4) {
if ((meshrights & 8) && ((connectivity & 1) || ((node.pmt == 1) && ((features2 & 2) != 0)))) { x += '<input type=button value="' + "Message" + '" title="' + "Display a text message on the remote device" + '" onclick=deviceMessageFunction() />'; }
if ((meshrights & 8) && (connectivity & 1) && ((meshrights & 16384) != 0) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Message" + '" title="' + "Display a text message on the remote device" + '" onclick=deviceMessageFunction() />'; }
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="' + "Display a text message of the remote device" + '" onclick=deviceToastFunction() />'; }
if ((meshrights & 8) && (connectivity & 1) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Chat" + '" title="' + "Open chat window to this computer" + '" onclick=deviceChat(event) />'; }
if ((meshrights & 8) && (connectivity & 1) && ((meshrights & 16384) != 0) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Chat" + '" title="' + "Open chat window to this computer" + '" onclick=deviceChat(event) />'; }
if ((serverinfo != null) && (serverinfo.altmessenging != null) && (meshrights & 8) && (connectivity & 1)) {
for (var i in serverinfo.altmessenging) {
var am = serverinfo.altmessenging[i];
@ -8110,7 +8128,7 @@
function deviceMessageFunction() {
if (xxdialogMode) return;
var x = '<div style=margin-bottom:4px>Display a message box on the remote device.</div>';
var x = '<div style=margin-bottom:4px>' + "Display a message box on the remote device" + '</div>';
x += '<textarea id=d2devMessage style=background-color:#fcf3cf;width:100%;height:80px;resize:none;overflow-y:scroll;box-sizing:border-box;margin-bottom:4px></textarea>';
x += '<select style=width:100% id=d2devTimeout>';
x += '<option value=2 selected>' + "Show for 2 Minutes (Default)" + '</option>';
@ -8255,7 +8273,7 @@
x += addHtmlValue("Start Time", '<input id=d2timeStartSelector style=float:right;width:250px class=flatpickr type="text" placeholder="' + "Select Date & Time..." + '" data-id="altinput">');
x += addHtmlValue("Duration", '<select id=d2inviteDuration style=float:right;width:250px>' + z + '</select>');
x += '</div>';
if (currentNode.agent.caps & 1) { x += '<div id=d2userConsentSelector>' + addHtmlValue("User Consent", '<select id=d2userConsent style=float:right;width:250px><option value=1>' + "Prompt for consent" + '</option><option value=0>' + "Notify Only" + '</option></select>') + '</div>'; }
if (currentNode.agent.caps & 1) { x += '<div id=d2userConsentSelector>' + addHtmlValue("User Consent", '<select id=d2userConsent style=float:right;width:250px><option value=0>' + "Notify Only" + '<option value=1>' + "Prompt for consent" + '</option><option value=2>' + "No Consent" + '</option></select>') + '</div>'; }
x += '<div id=d2httpPortSelector>' + addHtmlValue("Port", '<input id=d2httpPort style=float:right;width:250px value=80 onkeyup=showShareDeviceValidate()></input>') + '</div>';
x += '<div id=d2httpsPortSelector>' + addHtmlValue("Port", '<input id=d2httpsPort style=float:right;width:250px value=443 onkeyup=showShareDeviceValidate()></input>') + '</div>';
setDialogMode(2, "Share Device", 3, showShareDeviceEx, x);
@ -8291,14 +8309,17 @@
if (q & 1) {
consent |= 0x0002; // Terminal notify
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0010; } // Terminal prompt for user consent
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Terminal with no user consent
}
if (q & 2) {
consent |= 0x0041; // Desktop connection toolbar + Desktop notify
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0008; } // Desktop prompt for user consent
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Desktop with no user consent
}
if (q & 4) {
consent |= 0x0004; // Files notify
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0020; } // Files prompt for user consent
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Files prompt for user consent
}
if (Q('d2timeRange').value == 0) {
@ -8989,7 +9010,11 @@
var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
QE('connectbutton1', online);
QE('connectbutton1r', online || (currentNode.mtype == 3));
Q('connectbutton1r').value = 'RDP Connect' + ((currentNode.rdpport && currentNode.rdpport != 3389) ? ' ('+currentNode.rdpport + ')' : '');
if (currentNode.rdpport && currentNode.rdpport != 3389) {
QH('desktopCustomUpperRight', '<a style="cursor:pointer;line-height:22px" onclick="cmaltportaction(1,event)">' + format("RDP Port {0}", (currentNode.rdpport?currentNode.rdpport:3389)) + '</a>');
} else {
QH('desktopCustomUpperRight', '');
}
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
QE('connectbutton1h', hwonline);
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
@ -9024,9 +9049,9 @@
QV('DeskRunButton', ((rights & 131072) != 0) && online);
QV('DeskSaveImageButton', (deskState == 3) && (Q('Desk')['toBlob'] != null) && ((features2 & 0x400) == 0));
QV('DeskRecordButton', (deskState == 3) && (Q('Desk')['toBlob'] != null) && (desktop.m.StartRecording != null) && ((features2 & 0x400) == 0));
QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (currentNode.agent) && online);
QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (currentNode.agent) && online);
QV('DeskLockButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (currentNode.agent) && (deskState == 3));
QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && online);
QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && online);
QV('DeskLockButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (deskState == 3));
QV('DeskToolsButton', (currentNode.agent) && online);
QE('DeskToolsButton', inputAllowed);
QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (currentNode.agent) && online);
@ -10938,10 +10963,16 @@
setDialogMode(0); // Close the dialog box
} else if ((data.msg == 'zipping') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
// Show the dialog box message
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + "Compressing files..." + '<div>', 'fileMsgDialog');
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + "Compressing files..." + '</div>', 'fileMsgDialog');
} else if ((data.msg == 'unzipping') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
// Show the dialog box message
setDialogMode(2, "File Operation", 10, null, '<div style=margin:10px>' + "Unzipping file..." + '</div>', 'fileMsgDialog');
} else if ((data.msg == 'unziperror') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
// Show the dialog box message
setDialogMode(2, "File Operation", 10, null, '<div style=margin:10px>' + "Unzipping Error" + '</div><br />' + EscapeHtml(data.error), 'fileMsgDialog');
} else if ((data.msg == 'zippingFile') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
// Show the dialog box message
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + EscapeHtml(data.file) + '<div><br /><progress value=' + EscapeHtml(data.progress) + ' style=width:100% max=100 />', 'fileMsgDialog');
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + EscapeHtml(data.file) + '</div><br /><progress value=' + EscapeHtml(data.progress) + ' style=width:100% max=100 />', 'fileMsgDialog');
}
return;
}
@ -11181,6 +11212,7 @@
QE('p13CutButton', false);
QE('p13CopyButton', false);
QE('p13ZipButton', false);
QE('p13UnZipButton', false);
QE('p13PasteButton', false);
QE('p13GoToFolderButton', false);
QE('p13DownloadButton', false);
@ -11199,6 +11231,7 @@
QE('p13CutButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
QE('p13CopyButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
QE('p13ZipButton', advancedFeatures && (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
QE('p13UnzipButton', advancedFeatures && (cc == 1) && (sfc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)) && p13getFileSelAllowedExt('.zip'));
QE('p13PasteButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0)));
QE('p13GoToFolderButton', true);
QE('p13DownloadButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
@ -11214,12 +11247,14 @@
QV('p13CutButton', filesNode.mtype != 3);
QV('p13CopyButton', filesNode.mtype != 3);
QV('p13ZipButton', filesNode.mtype != 3);
QV('p13UnzipButton', filesNode.mtype != 3);
QV('p13PasteButton', filesNode.mtype != 3);
}
function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
function p13getFileSelAllowedExt(ext) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (!p13filetree.dir[checkboxes[i].value].n.endsWith(ext))) return false; } return true; }
function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
@ -11243,6 +11278,24 @@
}
}
function p13unzipFile() {
var dest, input, checkboxes = document.getElementsByName('fd');
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
var slash = isWindowsNode(currentNode) ? '\\' : '/';
dest = (isWindowsNode(currentNode) ? '' : '/') + p13filetreelocation.join(slash) + slash + p13filetree.dir[checkboxes[i].value].n.split('.zip')[0] + slash;
input = (isWindowsNode(currentNode) ? '' : '/') + p13filetreelocation.join(slash) + slash + p13filetree.dir[checkboxes[i].value].n;
}
}
setDialogMode(2, "Unzip To Folder", 3, p13unzipFileEx, '<input type=text id=p13unzipfolderinput maxlength=64 style=width:100% value="' + dest + '" />', { action: 'unzip', input: input });
focusTextBox('p13unzipfolderinput');
}
function p13unzipFileEx(a, tag) {
tag.dest = Q('p13unzipfolderinput').value;
files.sendText(tag);
}
function p13zipFiles() {
var inputFiles = [], checkboxes = document.getElementsByName('fd');
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { inputFiles.push(p13filetree.dir[checkboxes[i].value].n); } }
@ -11698,8 +11751,8 @@
data: {
labels: [],
datasets: [
{ label: 'CPU', backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
{ label: 'Memory', backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
{ label: "CPU", backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
{ label: "Memory", backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
] },
options: {
events: ['click'],
@ -12019,9 +12072,9 @@
if (tpm.SpecVersion) { x += addDetailItem("SpecVersion", parseFloat(EscapeHtml(tpm.SpecVersion)).toFixed(1), s); }
if (tpm.ManufacturerId) { x += addDetailItem("ManufacturerId", EscapeHtml(tpm.ManufacturerId), s); }
if (tpm.ManufacturerVersion) { x += addDetailItem("ManufacturerVersion", EscapeHtml(tpm.ManufacturerVersion), s); }
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", EscapeHtml(tpm.IsActivated), s); }
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", EscapeHtml(tpm.IsEnabled), s); }
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", EscapeHtml(tpm.IsOwned), s); }
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", (tpm.IsActivated ? "Yes" : "No"), s); }
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", (tpm.IsEnabled ? "Yes" : "No"), s); }
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", (tpm.IsOwned ? "Yes" : "No"), s); }
if (x != '') { sections.push({ name: "TPM", html: x, img: 'tpm64.png'}); }
}
@ -12070,6 +12123,25 @@
}
}
if (hardware.darwin) {
if (hardware.darwin.memory && (hardware.darwin.memory.length > 0)) {
var x = '';
x += '<table style=width:100%>';
for (var i in hardware.darwin.memory) {
var m = hardware.darwin.memory[i];
if(m.Size && (m.Size == 'No Module Installed')) continue;
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
x += '<div style=margin-bottom:3px><b>' + EscapeHtml((m.DeviceLocator ? m.DeviceLocator : 'Unknown')) + '</b></div>';
if (m.Size && m.Speed) { x += addDetailItem("Capacity / Speed", format("{0}, {1}", m.Size, m.Speed), s); }
else if (m.Size) { x += addDetailItem("Capacity", format("{0}", (m.Size)), s); }
if (m.PartNumber) { x += addDetailItem("Part Number", EscapeHtml((m.Manufacturer && m.Manufacturer != '')?(m.Manufacturer + ', '):'') + EscapeHtml(m.PartNumber), s); }
x += '</div>';
}
x += '</table>';
if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram64.png'}); }
}
}
// Storage
if (hardware.identifiers && hardware.identifiers.storage_devices) {
var x = '';
@ -12113,12 +12185,23 @@
var fsize = (j === 0 ? `${m.size} ${sizes[j]}` : `${(m.size / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
x += addDetailItem("Capacity", EscapeHtml(fsize), s);
}
if (m.type) { x += addDetailItem("File System", (m.removable == true ? ("Removable" + ' / ') : '') + EscapeHtml(m.type), s); }
if (m.sizeremaining) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
var j = parseInt(Math.floor(Math.log(Math.abs(m.sizeremaining)) / Math.log(1024)), 10);
var fsize = (j === 0 ? `${m.sizeremaining} ${sizes[j]}` : `${(m.sizeremaining / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
x += addDetailItem("Capacity Remaining", EscapeHtml(fsize), s);
}
if (m.type) {
var type = (m.removable == true ? "Removable" : (m.cdrom == true ? "CD-ROM" : ''));
x += addDetailItem("File System", (type != '' ? (type + ' / ') : '') + (m.type == 'Unknown' ? "Unknown" : EscapeHtml(m.type)), s);
}
if (m.protectionStatus || m.volumeStatus) {
var bitlockerState = [];
if (m.protectionStatus) bitlockerState.push("Enabled");
if (m.volumeStatus) bitlockerState.push(EscapeHtml(m.volumeStatus));
if (m.volumeStatus && m.volumeStatus == 'FullyDecrypted') bitlockerState.push("Fully Decrypted");
if (m.volumeStatus && m.volumeStatus == 'EncryptionInProgress') bitlockerState.push("Encryption In Progress");
if (m.volumeStatus && m.volumeStatus == 'FullyEncrypted') bitlockerState.push("Fully Encrypted");
bitlockerState = bitlockerState.join(' - ');
if (m.recoveryPassword) { bitlockerState += addKeyLink('', 'deviceDetailsShowBitlockerInfo(\"' + encodeURIComponentEx(i) + '\",\"' + encodeURIComponentEx(m.identifier) + '\",\"' + encodeURIComponentEx(m.recoveryPassword) + '\")'); }
x += addDetailItem("BitLocker", bitlockerState, s);

View File

@ -2815,7 +2815,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
obj.authenticate(req.query.user, req.query.pass, domain, function (err, userid, passhint, loginOptions) {
// 2FA is not supported in URL authentication method. If user has 2FA enabled, this login method fails.
var user = obj.users[userid];
if (checkUserOneTimePasswordRequired(domain, user, req, loginOptions) == true) {
if ((err == null) && checkUserOneTimePasswordRequired(domain, user, req, loginOptions) == true) {
handleRootRequestEx(req, res, domain, direct);
} else if ((userid != null) && (err == null)) {
// Login success