Improved MeshCmd, added audit log support.

This commit is contained in:
Ylian Saint-Hilaire 2018-03-20 17:48:03 -07:00
parent b831f097b8
commit 2f3a02d1fd
10 changed files with 107 additions and 78 deletions

Binary file not shown.

Binary file not shown.

View File

@ -91,7 +91,7 @@ function run(argv) {
//console.log('addedModules = ' + JSON.stringify(addedModules)); //console.log('addedModules = ' + JSON.stringify(addedModules));
var actionpath = 'meshaction.txt'; var actionpath = 'meshaction.txt';
if (args.actionfile != null) { actionpath = args.actionfile; } if (args.actionfile != null) { actionpath = args.actionfile; }
var actions = ['HELP', 'ROUTE', 'AMTLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER']; var actions = ['HELP', 'ROUTE', 'AMTLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG'];
// Load the action file // Load the action file
var actionfile = null; var actionfile = null;
@ -142,6 +142,7 @@ function run(argv) {
console.log('\r\nValid local or remote actions:'); console.log('\r\nValid local or remote actions:');
console.log(' MeshCommander - Launch a local MeshCommander web server.'); console.log(' MeshCommander - Launch a local MeshCommander web server.');
console.log(' AmtUUID - Show Intel AMT unique identifier.'); console.log(' AmtUUID - Show Intel AMT unique identifier.');
console.log(' AmtAuditLog - Show the Intel AMT audit log.');
console.log(' AmtLoadWebApp - Load MeshCommander in Intel AMT 11.6+ firmware.'); console.log(' AmtLoadWebApp - Load MeshCommander in Intel AMT 11.6+ firmware.');
console.log(' AmtClearWebApp - Clear everything from Intel AMT web storage.'); console.log(' AmtClearWebApp - Clear everything from Intel AMT web storage.');
console.log(' AmtStorageState - Show contents of the Intel AMT web storage.'); console.log(' AmtStorageState - Show contents of the Intel AMT web storage.');
@ -230,6 +231,14 @@ function run(argv) {
console.log('This action launched a local web server that hosts MeshCommander, a Intel AMT management console.'); console.log('This action launched a local web server that hosts MeshCommander, a Intel AMT management console.');
console.log('\r\nPossible arguments:\r\n'); console.log('\r\nPossible arguments:\r\n');
console.log(' --localport [port] Local port used for the web server, 3000 is default.'); console.log(' --localport [port] Local port used for the web server, 3000 is default.');
} else if (action == 'amtauditlog') {
console.log('AmtAuditLog action will fetch the local or remote audit log. If used localy, no username/password is required. Example usage:\r\n\r\n meshcmd amtauditlog --host 1.2.3.4 --user admin --pass mypassword --tls --output audit.json');
console.log('\r\nPossible arguments:\r\n');
console.log(' --output [filename] The output file for the Intel AMT state in JSON format.');
console.log(' --host [hostname] The IP address or DNS name of Intel AMT, 127.0.0.1 is default.');
console.log(' --user [username] The Intel AMT login username, admin is default.');
console.log(' --pass [password] The Intel AMT login password.');
console.log(' --tls Specifies that TLS must be used.');
} else { } else {
actions.shift(); actions.shift();
console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.'); console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.');
@ -373,15 +382,61 @@ function run(argv) {
// Deactivate CCM // Deactivate CCM
debug(1, "Settings: " + JSON.stringify(settings)); debug(1, "Settings: " + JSON.stringify(settings));
deactivateCCM(); deactivateCCM();
} else if (settings.action == 'meshcommander') { } else if (settings.action == 'meshcommander') { // Start MeshCommander
// Start MeshCommander
startMeshCommander(); startMeshCommander();
} else if (settings.action == 'amtauditlog') { // Read the Intel AMT audit log
if (settings.hostname != null) {
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
} else { settings.hostname = '127.0.0.1'; }
readAmtAuditLog();
} else { } else {
console.log('Invalid \"action\" specified.'); exit(1); return; console.log('Invalid \"action\" specified.'); exit(1); return;
} }
} }
//
// Intel AMT Audit Log
//
function readAmtAuditLog() {
// See if MicroLMS needs to be started
if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) {
settings.noconsole = true; startLms(readAmtAuditLogEx);
} else {
readAmtAuditLogEx(9999);
}
}
function readAmtAuditLogEx(x) {
if (x == 9999) {
var transport = require('amt-wsman-duk');
var wsman = require('amt-wsman');
var amt = require('amt');
wsstack = new wsman(transport, settings.hostname, settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
amtstack = new amt(wsstack);
amtstack.GetAuditLog(readAmtAuditLogEx2);
} else {
osamtstack.GetAuditLog(readAmtAuditLogEx2);
}
}
function readAmtAuditLogEx2(stack, response, status) {
if (status != 200) {
console.log('Unable to get audit log, status = ' + status + '.');
} else {
var out = '';
for (var i in response) {
var name = ((response[i].Initiator != '')?(response[i].Initiator + ': '):'')
out += (response[i].Time + ' - ' + name + response[i].Event + '\r\n');
}
if (settings.output == null) { console.log(out); } else { var file = fs.openSync(settings.output, 'w'); fs.writeSync(file, new Buffer(out, 'utf8')); fs.closeSync(file); }
}
exit(1);
}
// //
// MeshCommander local web server // MeshCommander local web server
// //
@ -397,27 +452,18 @@ function startMeshCommander() {
var http = require('http'); var http = require('http');
webServer = http.createServer(); webServer = http.createServer();
webServer.listen(settings.localport); webServer.listen(settings.localport);
webServer.wsList = {};
webServer.wsListIndex = 0;
webServer.on('upgrade', function (req, socket, head) { webServer.on('upgrade', function (req, socket, head) {
//console.log("WebSocket for " + req.url.split('?')[0]); //console.log("WebSocket for " + req.url.split('?')[0]);
switch (req.url.split('?')[0]) { switch (req.url.split('?')[0]) {
case '/webrelay.ashx': // MeshCommander relay channel case '/webrelay.ashx': // MeshCommander relay channel
var ws = socket.upgradeWebSocket(); var ws = socket.upgradeWebSocket();
socket.ws = ws; socket.ws = ws;
ws.wsIndex = ++webServer.wsListIndex;
webServer.wsList[ws.wsIndex] = ws;
ws.pause(); ws.pause();
// When data is received from the web socket, forward the data into the associated TCP connection.
// If the TCP connection is pending, buffer up the data until it connects.
ws.on('data', function (data) {
//console.log('Data relay --> ' + data.length + ': ' + data.toString() + '\r\n');
ws.forwardclient.write(data); // Forward data to the associated TCP connection.
});
// If the web socket is closed, close the associated TCP connection.
ws.on('close', function (req) {
//console.log('Closed websocket.');
if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } }
});
// We got a new web socket connection, initiate a TCP connection to the target Intel AMT host/port. // We got a new web socket connection, initiate a TCP connection to the target Intel AMT host/port.
var webargs = parseUrlArguments(req.url); var webargs = parseUrlArguments(req.url);
if (webargs.p) { webargs.p = parseInt(webargs.p); } if (webargs.p) { webargs.p = parseInt(webargs.p); }
@ -429,36 +475,16 @@ function startMeshCommander() {
// If this is TCP (without TLS) set a normal TCP socket // If this is TCP (without TLS) set a normal TCP socket
var net = require('net'); var net = require('net');
ws.forwardclient = net.connect({ host: webargs.host, port: webargs.port }) ws.forwardclient = net.connect({ host: webargs.host, port: webargs.port })
ws.forwardclient.on('connect', function () { this.pipe(this.ws); this.ws.pipe(this); });
ws.forwardclient.ws = ws; ws.forwardclient.ws = ws;
ws.forwardclient.on('connect', function () { this.ws.resume(); });
} else { } else {
// If TLS is going to be used, setup a TLS socket // If TLS is going to be used, setup a TLS socket
var tls = require('tls'); var tls = require('tls');
var tlsoptions = { host: webargs.host, port: webargs.port, secureProtocol: ((webargs.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), rejectUnauthorized: false }; var tlsoptions = { host: webargs.host, port: webargs.port, secureProtocol: ((webargs.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), rejectUnauthorized: false };
ws.forwardclient = tls.connect(tlsoptions, function () { this.ws.resume(); }); ws.forwardclient = tls.connect(tlsoptions, function () { this.pipe(this.ws); this.ws.pipe(this); });
ws.forwardclient.ws = ws; ws.forwardclient.ws = ws;
} }
// When we receive data on the TCP connection, forward it back into the web socket connection.
ws.forwardclient.on('data', function (data) {
//console.log('Data relay <-- ' + data.length + ': ' + data.toString() + '\r\n');
try { this.ws.write(data); } catch (e) { }
});
// If the TCP connection closes, disconnect the associated web socket.
ws.forwardclient.on('close', function () {
//console.log('TCP/TLS disconnected.');
try { this.ws.end(); } catch (e) { }
try { this.end(); } catch (e) { }
});
// If the TCP connection causes an error, disconnect the associated web socket.
ws.forwardclient.on('error', function (err) {
//console.log('TCP/TLS disconnected with error', err);
try { this.ws.end(); } catch (e) { }
try { this.end(); } catch (e) { }
});
break; break;
default: default:
socket.end(); socket.end();
@ -1129,5 +1155,11 @@ function parseUrlArguments(url) {
return r; return r;
} }
// Remove a element from a array
function removeItemFromArray(array, element) {
const index = array.indexOf(element);
if (index !== -1) { array.splice(index, 1); }
}
// Run MeshCmd // Run MeshCmd
try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); }

View File

@ -75,10 +75,10 @@ function createMeshCore(agent) {
// Try to load up the MEI module // Try to load up the MEI module
try { try {
var amtMeiLib = require('amt-mei'); var amtMeiLib = require('amt-mei');
amtMeiConnected = 1;
amtMei = new amtMeiLib(); amtMei = new amtMeiLib();
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); }); amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); });
amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); }); amtMeiConnected = 2;
//amtMei.on('connect', function () { amtMeiConnected = 2; sendPeriodicServerUpdate(); });
} catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; } } catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
// Try to load up the WIFI scanner // Try to load up the WIFI scanner
@ -869,11 +869,11 @@ function createMeshCore(agent) {
break; break;
} }
case 'selfinfo': { // Return self information block case 'selfinfo': { // Return self information block
buildSelfInfo(function (info) { sendConsoleText(objToString(info, 0, ' '), sessionid); }); buildSelfInfo(function (info) { sendConsoleText(objToString(info, 0, ' ', true), sessionid); });
break; break;
} }
case 'args': { // Displays parsed command arguments case 'args': { // Displays parsed command arguments
response = 'args ' + objToString(args, 0, ' '); response = 'args ' + objToString(args, 0, ' ', true);
break; break;
} }
case 'print': { // Print a message on the mesh agent console, does nothing when running in the background case 'print': { // Print a message on the mesh agent console, does nothing when running in the background
@ -1045,7 +1045,7 @@ function createMeshCore(agent) {
case 'amt': { // Show Intel AMT status case 'amt': { // Show Intel AMT status
getAmtInfo(function (state) { getAmtInfo(function (state) {
var resp = 'Intel AMT not detected.'; var resp = 'Intel AMT not detected.';
if (state != null) { resp = objToString(state, 0, ' '); } if (state != null) { resp = objToString(state, 0, ' ', true); }
sendConsoleText(resp, sessionid); sendConsoleText(resp, sessionid);
}); });
break; break;
@ -1053,7 +1053,11 @@ function createMeshCore(agent) {
case 'netinfo': { // Show network interface information case 'netinfo': { // Show network interface information
//response = objToString(mesh.NetInfo, 0, ' '); //response = objToString(mesh.NetInfo, 0, ' ');
var interfaces = require('os').networkInterfaces(); var interfaces = require('os').networkInterfaces();
response = objToString(interfaces, 0, ' '); response = objToString(interfaces, 0, ' ', true);
break;
}
case 'netinfo2': { // Show network interface information
response = objToString(mesh.NetInfo, 0, ' ', true);
break; break;
} }
case 'wakeonlan': { // Send wake-on-lan case 'wakeonlan': { // Send wake-on-lan
@ -1215,7 +1219,7 @@ function createMeshCore(agent) {
amtMei.getVersion(function (val) { amtMeiTmpState.Versions = {}; for (var version in val.Versions) { amtMeiTmpState.Versions[val.Versions[version].Description] = val.Versions[version].Version; } }); amtMei.getVersion(function (val) { amtMeiTmpState.Versions = {}; for (var version in val.Versions) { amtMeiTmpState.Versions[val.Versions[version].Description] = val.Versions[version].Version; } });
amtMei.getProvisioningMode(function (result) { amtMeiTmpState.ProvisioningMode = result.mode; }); amtMei.getProvisioningMode(function (result) { amtMeiTmpState.ProvisioningMode = result.mode; });
amtMei.getProvisioningState(function (result) { amtMeiTmpState.ProvisioningState = result.state; }); amtMei.getProvisioningState(function (result) { amtMeiTmpState.ProvisioningState = result.state; });
amtMei.getEHBCState(function (result) { if (result.EHBC == true) { amtMeiTmpState.Flags += 1; } }); amtMei.getEHBCState(function (result) { if ((result != null) && (result.EHBC == true)) { amtMeiTmpState.Flags += 1; } });
amtMei.getControlMode(function (result) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } }); amtMei.getControlMode(function (result) { if (result.controlMode == 1) { amtMeiTmpState.Flags += 2; } if (result.controlMode == 2) { amtMeiTmpState.Flags += 4; } });
//amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; }); //amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; });
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } }); amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } if (func != null) { func(amtMeiTmpState); } });

View File

@ -18,7 +18,6 @@ var Q = require('queue');
function amt_heci() { function amt_heci() {
var emitterUtils = require('events').inherits(this); var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error'); emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci'); var heci = require('heci');

View File

@ -633,7 +633,7 @@ function AmtStackCreateService(wsmanStack) {
2003: 'Security Audit Log Enabled', 2003: 'Security Audit Log Enabled',
2004: 'Security Audit Log Exported', 2004: 'Security Audit Log Exported',
2005: 'Security Audit Log Recovered', 2005: 'Security Audit Log Recovered',
2100: 'Intel&reg; ME Time Set', 2100: 'Intel(R) ME Time Set',
2200: 'TCPIP Parameters Set', 2200: 'TCPIP Parameters Set',
2201: 'Host Name Set', 2201: 'Host Name Set',
2202: 'Domain Name Set', 2202: 'Domain Name Set',
@ -742,12 +742,12 @@ function AmtStackCreateService(wsmanStack) {
} }
if (x['InitiatorType'] == 2) { if (x['InitiatorType'] == 2) {
// Local // Local
x['Initiator'] = '<i>Local</i>'; x['Initiator'] = 'Local';
ptr = 5; ptr = 5;
} }
if (x['InitiatorType'] == 3) { if (x['InitiatorType'] == 3) {
// KVM Default Port // KVM Default Port
x['Initiator'] = '<i>KVM Default Port</i>'; x['Initiator'] = 'KVM Default Port';
ptr = 5; ptr = 5;
} }

View File

@ -290,11 +290,8 @@ function lme_heci(options) {
var notify = null; var notify = null;
try { notify = xmlParser.ParseWsman(httpData); } catch (e) { } try { notify = xmlParser.ParseWsman(httpData); } catch (e) { }
// Translate the event
var notifyString = _lmsNotifyToString(notify);
// Event the http data // Event the http data
if (notify != null) { this.LMS.emit('notify', notify, channel.options, notifyString); } if (notify != null) { this.LMS.emit('notify', notify, channel.options, _lmsNotifyToString(notify), _lmsNotifyToCode(notify)); }
// Send channel close // Send channel close
var buffer = Buffer.alloc(5); var buffer = Buffer.alloc(5);
@ -437,6 +434,13 @@ function parseHttp(httpData) {
return null; return null;
} }
function _lmsNotifyToCode(notify) {
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
var msgid = notify.Body.MessageID;
try { msgid += '-' + notify.Body.MessageArguments[0]; } catch (e) { }
return msgid;
}
function _lmsNotifyToString(notify) { function _lmsNotifyToString(notify) {
if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null; if ((notify == null) || (notify.Body == null) || (notify.Body.MessageID == null)) return null;
var msgid = notify.Body.MessageID; var msgid = notify.Body.MessageID;
@ -520,7 +524,7 @@ var lmsEvents = {
"iAMT0055-0": "User Notification Alert - Provisioning state change notification - Pre-configuration.", "iAMT0055-0": "User Notification Alert - Provisioning state change notification - Pre-configuration.",
"iAMT0055-1": "User Notification Alert - Provisioning state change notification - In configuration.", "iAMT0055-1": "User Notification Alert - Provisioning state change notification - In configuration.",
"iAMT0055-2": "User Notification Alert - Provisioning state change notification - Post-configuration.", "iAMT0055-2": "User Notification Alert - Provisioning state change notification - Post-configuration.",
"iAMT0055-3": "User Notification Alert - Provisioning state change notification - unprovision process has started.", "iAMT0055-3": "User Notification Alert - Provisioning state change notification - Unprovision process has started.",
"iAMT0056": "User Notification Alert - System Defense change notification.", "iAMT0056": "User Notification Alert - System Defense change notification.",
"iAMT0057": "User Notification Alert - Network State change notification.", "iAMT0057": "User Notification Alert - Network State change notification.",
"iAMT0058": "User Notification Alert - Remote Access change notification.", "iAMT0058": "User Notification Alert - Remote Access change notification.",

View File

@ -18,24 +18,20 @@ var Q = require('queue');
function amt_heci() { function amt_heci() {
var emitterUtils = require('events').inherits(this); var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error'); emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci'); var heci = require('heci');
this._ObjectID = "pthi"; this._ObjectID = "pthi";
this._rq = new Q(); this._rq = new Q();
this._setupPTHI = function _setupPTHI() this._setupPTHI = function _setupPTHI() {
{
this._amt = heci.create(); this._amt = heci.create();
this._amt.BiosVersionLen = 65; this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20; this._amt.UnicodeStringLen = 20;
this._amt.Parent = this; this._amt.Parent = this;
this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); }); this._amt.on('error', function _amtOnError(e) { this.Parent.emit('error', e); });
this._amt.on('connect', function _amtOnConnect() this._amt.on('connect', function _amtOnConnect() {
{ this.on('data', function _amtOnData(chunk) {
this.on('data', function _amtOnData(chunk)
{
//console.log("Received: " + chunk.length + " bytes"); //console.log("Received: " + chunk.length + " bytes");
var header = this.Parent.getCommand(chunk); var header = this.Parent.getCommand(chunk);
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse); //console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
@ -47,14 +43,12 @@ function amt_heci() {
params.unshift(header); params.unshift(header);
callback.apply(this.Parent, params); callback.apply(this.Parent, params);
if(this.Parent._rq.isEmpty()) if (this.Parent._rq.isEmpty()) {
{
// No More Requests, we can close PTHI // No More Requests, we can close PTHI
this.Parent._amt.disconnect(); this.Parent._amt.disconnect();
this.Parent._amt = null; this.Parent._amt = null;
} }
else else {
{
// Send the next request // Send the next request
this.write(this.Parent._rq.peekQueue().send); this.write(this.Parent._rq.peekQueue().send);
} }
@ -81,8 +75,7 @@ function amt_heci() {
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8); header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args, send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]])) }); this._rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args, send: (arguments[1] == null ? header : Buffer.concat([header, arguments[1]])) });
if(!this._amt) if (!this._amt) {
{
this._setupPTHI(); this._setupPTHI();
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 }); this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
} }

View File

@ -563,15 +563,7 @@
<div id="d7meshkvm"> <div id="d7meshkvm">
<h4 style="width:100%;border-bottom:1px solid gray">Mesh Agent Remote Desktop</h4> <h4 style="width:100%;border-bottom:1px solid gray">Mesh Agent Remote Desktop</h4>
<div style="margin:3px 0 3px 0"> <div style="margin:3px 0 3px 0">
<select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl"> <select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl"></select>
<option value=50>50%</option>
<option value=40>40%</option>
<option selected=selected value=30>30%</option>
<option value=20>20%</option>
<option value=10>10%</option>
<option value=5>5%</option>
<option value=1>1%</option>
</select>
<div style="height:20px">Quality</div> <div style="height:20px">Quality</div>
</div> </div>
<div style="margin:3px 0 3px 0"> <div style="margin:3px 0 3px 0">
@ -3075,9 +3067,13 @@
} }
function applyDesktopSettings() { function applyDesktopSettings() {
var r = '', ops = (features & 512)?[100,80,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1];
for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
QH('d7bitmapquality', r);
d7desktopmode.value = desktopsettings.encoding; d7desktopmode.value = desktopsettings.encoding;
d7showfocus.checked = desktopsettings.showfocus; d7showfocus.checked = desktopsettings.showfocus;
d7showcursor.checked = desktopsettings.showmouse; d7showcursor.checked = desktopsettings.showmouse;
d7bitmapquality.value = 40; // Default value
d7bitmapquality.value = desktopsettings.quality; d7bitmapquality.value = desktopsettings.quality;
d7bitmapscaling.value = desktopsettings.scaling; d7bitmapscaling.value = desktopsettings.scaling;
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus)); QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (desktop.state != 0) && (desktopsettings.showfocus));

View File

@ -682,6 +682,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
if ((obj.parent.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName != 'un-configured') && (obj.args.lanonly != true)) { features += 64; } // Email invites if ((obj.parent.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName != 'un-configured') && (obj.args.lanonly != true)) { features += 64; } // Email invites
if (obj.args.webrtc == true) { features += 128; } // Enable WebRTC (Default false for now) if (obj.args.webrtc == true) { features += 128; } // Enable WebRTC (Default false for now)
if (obj.args.clickonce !== false) { features += 256; } // Enable ClickOnce (Default true) if (obj.args.clickonce !== false) { features += 256; } // Enable ClickOnce (Default true)
if (obj.args.allowhighqualitydesktop == true) { features += 512; } // Enable AllowHighQualityDesktop (Default false)
// Send the master web application // Send the master web application
if ((!obj.args.user) && (obj.args.nousers != true) && (nologout == false)) { logoutcontrol += ' <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>'; } // If a default user is in use or no user mode, don't display the logout button if ((!obj.args.user) && (obj.args.nousers != true) && (nologout == false)) { logoutcontrol += ' <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>'; } // If a default user is in use or no user mode, don't display the logout button