mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 22:25:52 -05:00
Merge branch 'master' of https://github.com/Ylianst/MeshCentral
This commit is contained in:
commit
993f3c2777
@ -271,20 +271,17 @@
|
||||
<Content Include="readme.md" />
|
||||
<Content Include="sample-config.json" />
|
||||
<Content Include="SourceFileList.txt" />
|
||||
<Content Include="translate\readme.txt" />
|
||||
<Content Include="translate\translate.json" />
|
||||
<Content Include="views\agentinvite.handlebars" />
|
||||
<Content Include="views\default-min.handlebars" />
|
||||
<Content Include="views\default-mobile-min.handlebars" />
|
||||
<Content Include="views\default-mobile.handlebars" />
|
||||
<Content Include="views\default.handlebars" />
|
||||
<Content Include="views\download.handlebars" />
|
||||
<Content Include="views\error404-mobile.handlebars" />
|
||||
<Content Include="views\error404.handlebars" />
|
||||
<Content Include="views\login-min.handlebars" />
|
||||
<Content Include="views\login-mobile-min.handlebars" />
|
||||
<Content Include="views\login-mobile.handlebars" />
|
||||
<Content Include="views\login.handlebars" />
|
||||
<Content Include="views\message.handlebars" />
|
||||
<Content Include="views\messenger-min.handlebars" />
|
||||
<Content Include="views\messenger.handlebars" />
|
||||
<Content Include="views\terms-mobile.handlebars" />
|
||||
<Content Include="views\terms.handlebars" />
|
||||
|
Binary file not shown.
Binary file not shown.
@ -141,6 +141,7 @@ function run(argv) {
|
||||
if ((typeof args.serverid) == 'string') { settings.serverid = args.serverid; }
|
||||
if ((typeof args.serverhttpshash) == 'string') { settings.serverhttpshash = args.serverhttpshash; }
|
||||
if ((typeof args.remoteport) == 'string') { settings.remoteport = parseInt(args.remoteport); }
|
||||
if ((typeof args.remotetarget) == 'string') { settings.remotetarget = args.remotetarget; }
|
||||
if ((typeof args.out) == 'string') { settings.output = args.out; }
|
||||
if ((typeof args.output) == 'string') { settings.output = args.output; }
|
||||
if ((typeof args.debug) == 'string') { settings.debuglevel = parseInt(args.debug); }
|
||||
@ -2049,10 +2050,10 @@ function startRouter() {
|
||||
tcpserver.on('error', function (e) { console.log('ERROR: ' + JSON.stringify(e)); exit(0); return; });
|
||||
tcpserver.listen(settings.localport, function () {
|
||||
// We started listening.
|
||||
if (settings.remotename == null) {
|
||||
if (settings.remotetarget == null) {
|
||||
console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.');
|
||||
} else {
|
||||
console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotename + ':' + settings.remoteport + '.');
|
||||
console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.');
|
||||
}
|
||||
console.log('Press ctrl-c to exit.');
|
||||
|
||||
@ -2069,7 +2070,7 @@ function OnTcpClientConnected(c) {
|
||||
c.on('end', function () { disconnectTunnel(this, this.websocket, 'Client closed'); });
|
||||
c.pause();
|
||||
try {
|
||||
options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport);
|
||||
options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget));
|
||||
} catch (e) { console.log('Unable to parse \"serverUrl\".'); process.exit(1); return; }
|
||||
options.checkServerIdentity = onVerifyServer;
|
||||
options.rejectUnauthorized = false;
|
||||
@ -2564,46 +2565,53 @@ function removeItemFromArray(array, element) {
|
||||
}
|
||||
|
||||
// Run MeshCmd, but before we do, we need to see if what type of service we are going to be
|
||||
var serviceName = null;
|
||||
var serviceOpSpecified = 0;
|
||||
var serviceInstall = 0;
|
||||
|
||||
var serviceName = null, serviceDisplayName = null, serviceDesc = null;
|
||||
for (var i in process.argv) {
|
||||
if (process.argv[i].toLowerCase() == 'install') { serviceInstall = 1 } else if (process.argv[i].toLowerCase() == 'uninstall') { serviceInstall = -1 }
|
||||
if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) { serviceName = 'MicroLMS'; break; }
|
||||
if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) { serviceName = 'MeshCommander'; break; }
|
||||
if (process.argv[i].toLowerCase() == 'install') { process.argv[i] = '-install'; }
|
||||
if (process.argv[i].toLowerCase() == 'uninstall') { process.argv[i] = '-uninstall'; }
|
||||
if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) {
|
||||
serviceName = 'MicroLMS';
|
||||
serviceDisplayName = 'MicroLMS Service for Intel(R) AMT';
|
||||
serviceDesc = 'Intel AMT Micro Local Manageability Service (MicroLMS)';
|
||||
} else if ((process.argv[i].toLowerCase() == 'intellms')) {
|
||||
serviceName = 'LMS';
|
||||
serviceDisplayName = 'Intel(R) Management and Security Application Local Management Service';
|
||||
serviceDesc = 'Intel(R) Management and Security Application Local Management Service - Provides OS-related Intel(R) ME functionality.';
|
||||
} else if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) {
|
||||
serviceName = 'MeshCommander';
|
||||
serviceDisplayName = 'MeshCommander, Intel AMT Management console';
|
||||
serviceDesc = 'MeshCommander is a Intel AMT management console.';
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceName == null) {
|
||||
for (var i in process.argv) {
|
||||
if ((process.argv[i].toLowerCase() == 'install') || (process.argv[i].toLowerCase() == 'uninstall')) {
|
||||
console.log('In order to install/uninstall, a service type must be specified.');
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
if (process.execPath.includes('MicroLMS')) { serviceName = 'MicroLMS'; }
|
||||
else if (process.execPath.includes('LMS')) { serviceName = 'LMS'; }
|
||||
else if (process.execPath.includes('MeshCommander')) { serviceName = 'MeshCommander'; }
|
||||
else { serviceName = 'not_a_service'; }
|
||||
if (serviceName == null) { for (var i in process.argv) { if ((process.argv[i].toLowerCase() == '-install') || (process.argv[i].toLowerCase() == '-uninstall')) { console.log('In order to install/uninstall, a service type must be specified.'); process.exit(); } } }
|
||||
if (serviceName == null) { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } process.exit(); }
|
||||
}
|
||||
|
||||
if (serviceInstall == 0) {
|
||||
run(process.argv);
|
||||
} else {
|
||||
var serviceHost = require('service-host');
|
||||
var meshcmdService = new serviceHost({ name: serviceName, startType: 'AUTO_START' });
|
||||
var serviceHost = require('service-host');
|
||||
var meshcmdService = new serviceHost({ name: serviceName, displayName: serviceDisplayName, startType: 'AUTO_START', description: serviceDesc });
|
||||
|
||||
// Called when the background service is started.
|
||||
meshcmdService.on('serviceStart', function onStart() {
|
||||
console.setDestination(console.Destinations.DISABLED); // Disable console.log().
|
||||
if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } //
|
||||
else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); }
|
||||
else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
|
||||
});
|
||||
// Called when the background service is started.
|
||||
meshcmdService.on('serviceStart', function onStart() {
|
||||
//process.coreDumpLocation = 'C:\\tmp\\meshcommander.dmp';
|
||||
//process.on('exit', function () { console.log('exit3'); _debugCrash(); });
|
||||
console.setDestination(console.Destinations.DISABLED); // Disable console.log().
|
||||
//console.setDestination(console.Destinations.LOGFILE);
|
||||
//attachDebuger({ webport: 0, wait: 1 }).then(console.log, console.log);
|
||||
|
||||
// Called when the background service is stopping
|
||||
meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
|
||||
if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } // Start MicroLMS
|
||||
else if (process.execPath.includes('LMS')) { run([process.execPath, 'microlms']); } // Start MicroLMS
|
||||
else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); } // Start MeshCommander
|
||||
else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
|
||||
});
|
||||
|
||||
// Called when the executable is not running as a service, run normally.
|
||||
meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
|
||||
meshcmdService.run();
|
||||
}
|
||||
// Called when the background service is stopping
|
||||
meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
|
||||
|
||||
// Called when the executable is not running as a service, run normally.
|
||||
meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
|
||||
meshcmdService.run();
|
||||
|
78
agents/meshcmd.min.js
vendored
78
agents/meshcmd.min.js
vendored
@ -141,6 +141,7 @@ function run(argv) {
|
||||
if ((typeof args.serverid) == 'string') { settings.serverid = args.serverid; }
|
||||
if ((typeof args.serverhttpshash) == 'string') { settings.serverhttpshash = args.serverhttpshash; }
|
||||
if ((typeof args.remoteport) == 'string') { settings.remoteport = parseInt(args.remoteport); }
|
||||
if ((typeof args.remotetarget) == 'string') { settings.remotetarget = args.remotetarget; }
|
||||
if ((typeof args.out) == 'string') { settings.output = args.out; }
|
||||
if ((typeof args.output) == 'string') { settings.output = args.output; }
|
||||
if ((typeof args.debug) == 'string') { settings.debuglevel = parseInt(args.debug); }
|
||||
@ -2049,10 +2050,10 @@ function startRouter() {
|
||||
tcpserver.on('error', function (e) { console.log('ERROR: ' + JSON.stringify(e)); exit(0); return; });
|
||||
tcpserver.listen(settings.localport, function () {
|
||||
// We started listening.
|
||||
if (settings.remotename == null) {
|
||||
if (settings.remotetarget == null) {
|
||||
console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.');
|
||||
} else {
|
||||
console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotename + ':' + settings.remoteport + '.');
|
||||
console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.');
|
||||
}
|
||||
console.log('Press ctrl-c to exit.');
|
||||
|
||||
@ -2069,7 +2070,7 @@ function OnTcpClientConnected(c) {
|
||||
c.on('end', function () { disconnectTunnel(this, this.websocket, 'Client closed'); });
|
||||
c.pause();
|
||||
try {
|
||||
options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport);
|
||||
options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget));
|
||||
} catch (e) { console.log('Unable to parse \"serverUrl\".'); process.exit(1); return; }
|
||||
options.checkServerIdentity = onVerifyServer;
|
||||
options.rejectUnauthorized = false;
|
||||
@ -2564,46 +2565,53 @@ function removeItemFromArray(array, element) {
|
||||
}
|
||||
|
||||
// Run MeshCmd, but before we do, we need to see if what type of service we are going to be
|
||||
var serviceName = null;
|
||||
var serviceOpSpecified = 0;
|
||||
var serviceInstall = 0;
|
||||
|
||||
var serviceName = null, serviceDisplayName = null, serviceDesc = null;
|
||||
for (var i in process.argv) {
|
||||
if (process.argv[i].toLowerCase() == 'install') { serviceInstall = 1 } else if (process.argv[i].toLowerCase() == 'uninstall') { serviceInstall = -1 }
|
||||
if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) { serviceName = 'MicroLMS'; break; }
|
||||
if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) { serviceName = 'MeshCommander'; break; }
|
||||
if (process.argv[i].toLowerCase() == 'install') { process.argv[i] = '-install'; }
|
||||
if (process.argv[i].toLowerCase() == 'uninstall') { process.argv[i] = '-uninstall'; }
|
||||
if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) {
|
||||
serviceName = 'MicroLMS';
|
||||
serviceDisplayName = 'MicroLMS Service for Intel(R) AMT';
|
||||
serviceDesc = 'Intel AMT Micro Local Manageability Service (MicroLMS)';
|
||||
} else if ((process.argv[i].toLowerCase() == 'intellms')) {
|
||||
serviceName = 'LMS';
|
||||
serviceDisplayName = 'Intel(R) Management and Security Application Local Management Service';
|
||||
serviceDesc = 'Intel(R) Management and Security Application Local Management Service - Provides OS-related Intel(R) ME functionality.';
|
||||
} else if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) {
|
||||
serviceName = 'MeshCommander';
|
||||
serviceDisplayName = 'MeshCommander, Intel AMT Management console';
|
||||
serviceDesc = 'MeshCommander is a Intel AMT management console.';
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceName == null) {
|
||||
for (var i in process.argv) {
|
||||
if ((process.argv[i].toLowerCase() == 'install') || (process.argv[i].toLowerCase() == 'uninstall')) {
|
||||
console.log('In order to install/uninstall, a service type must be specified.');
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
if (process.execPath.includes('MicroLMS')) { serviceName = 'MicroLMS'; }
|
||||
else if (process.execPath.includes('LMS')) { serviceName = 'LMS'; }
|
||||
else if (process.execPath.includes('MeshCommander')) { serviceName = 'MeshCommander'; }
|
||||
else { serviceName = 'not_a_service'; }
|
||||
if (serviceName == null) { for (var i in process.argv) { if ((process.argv[i].toLowerCase() == '-install') || (process.argv[i].toLowerCase() == '-uninstall')) { console.log('In order to install/uninstall, a service type must be specified.'); process.exit(); } } }
|
||||
if (serviceName == null) { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } process.exit(); }
|
||||
}
|
||||
|
||||
if (serviceInstall == 0) {
|
||||
run(process.argv);
|
||||
} else {
|
||||
var serviceHost = require('service-host');
|
||||
var meshcmdService = new serviceHost({ name: serviceName, startType: 'AUTO_START' });
|
||||
var serviceHost = require('service-host');
|
||||
var meshcmdService = new serviceHost({ name: serviceName, displayName: serviceDisplayName, startType: 'AUTO_START', description: serviceDesc });
|
||||
|
||||
// Called when the background service is started.
|
||||
meshcmdService.on('serviceStart', function onStart() {
|
||||
console.setDestination(console.Destinations.DISABLED); // Disable console.log().
|
||||
if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } //
|
||||
else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); }
|
||||
else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
|
||||
});
|
||||
// Called when the background service is started.
|
||||
meshcmdService.on('serviceStart', function onStart() {
|
||||
//process.coreDumpLocation = 'C:\\tmp\\meshcommander.dmp';
|
||||
//process.on('exit', function () { console.log('exit3'); _debugCrash(); });
|
||||
console.setDestination(console.Destinations.DISABLED); // Disable console.log().
|
||||
//console.setDestination(console.Destinations.LOGFILE);
|
||||
//attachDebuger({ webport: 0, wait: 1 }).then(console.log, console.log);
|
||||
|
||||
// Called when the background service is stopping
|
||||
meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
|
||||
if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } // Start MicroLMS
|
||||
else if (process.execPath.includes('LMS')) { run([process.execPath, 'microlms']); } // Start MicroLMS
|
||||
else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); } // Start MeshCommander
|
||||
else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
|
||||
});
|
||||
|
||||
// Called when the executable is not running as a service, run normally.
|
||||
meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
|
||||
meshcmdService.run();
|
||||
}
|
||||
// Called when the background service is stopping
|
||||
meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
|
||||
|
||||
// Called when the executable is not running as a service, run normally.
|
||||
meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
|
||||
meshcmdService.run();
|
||||
|
@ -754,6 +754,15 @@ function createMeshCore(agent) {
|
||||
for (var i in data.macs) { sendWakeOnLan(data.macs[i]); }
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
// Uninstall this agent
|
||||
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
|
||||
if (require('service-manager').manager.getService(agentName).isMe()) {
|
||||
try { diagnosticAgent_uninstall(); } catch (x) { }
|
||||
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
|
||||
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
|
||||
}
|
||||
break;
|
||||
case 'poweraction': {
|
||||
// Server telling us to execute a power action
|
||||
if ((mesh.ExecPowerState != undefined) && (data.actiontype)) {
|
||||
@ -810,15 +819,7 @@ function createMeshCore(agent) {
|
||||
case 'ping': { mesh.SendCommand('{"action":"pong"}'); break; }
|
||||
case 'pong': { break; }
|
||||
case 'plugin': {
|
||||
if (typeof data.pluginaction == 'string') {
|
||||
try {
|
||||
MeshServerLog('Plugin called', data);
|
||||
// Not yet implemented
|
||||
// require(data.plugin.name).serveraction(data);
|
||||
} catch (e) {
|
||||
MeshServerLog('Error calling plugin', data);
|
||||
}
|
||||
}
|
||||
try { require(data.plugin).consoleaction(data, data.rights, data.sessionid, this); } catch (e) { throw e; }
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1998,17 +1999,12 @@ function createMeshCore(agent) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
case 'uninstallagent': // Uninstall this agent
|
||||
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
|
||||
if (!require('service-manager').manager.getService(agentName).isMe()) {
|
||||
response = 'Uininstall failed, this instance is not the service instance';
|
||||
}
|
||||
else {
|
||||
try {
|
||||
diagnosticAgent_uninstall();
|
||||
}
|
||||
catch (x) {
|
||||
}
|
||||
} else {
|
||||
try { diagnosticAgent_uninstall(); } catch (x) { }
|
||||
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
|
||||
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
|
||||
}
|
||||
|
30
agents/meshcore.min.js
vendored
30
agents/meshcore.min.js
vendored
@ -754,6 +754,15 @@ function createMeshCore(agent) {
|
||||
for (var i in data.macs) { sendWakeOnLan(data.macs[i]); }
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
// Uninstall this agent
|
||||
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
|
||||
if (require('service-manager').manager.getService(agentName).isMe()) {
|
||||
try { diagnosticAgent_uninstall(); } catch (x) { }
|
||||
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
|
||||
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
|
||||
}
|
||||
break;
|
||||
case 'poweraction': {
|
||||
// Server telling us to execute a power action
|
||||
if ((mesh.ExecPowerState != undefined) && (data.actiontype)) {
|
||||
@ -810,15 +819,7 @@ function createMeshCore(agent) {
|
||||
case 'ping': { mesh.SendCommand('{"action":"pong"}'); break; }
|
||||
case 'pong': { break; }
|
||||
case 'plugin': {
|
||||
if (typeof data.pluginaction == 'string') {
|
||||
try {
|
||||
MeshServerLog('Plugin called', data);
|
||||
// Not yet implemented
|
||||
// require(data.plugin.name).serveraction(data);
|
||||
} catch (e) {
|
||||
MeshServerLog('Error calling plugin', data);
|
||||
}
|
||||
}
|
||||
try { require(data.plugin).consoleaction(data, data.rights, data.sessionid, this); } catch (e) { throw e; }
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1942,17 +1943,12 @@ function createMeshCore(agent) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
case 'uninstallagent': // Uninstall this agent
|
||||
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
|
||||
if (!require('service-manager').manager.getService(agentName).isMe()) {
|
||||
response = 'Uininstall failed, this instance is not the service instance';
|
||||
}
|
||||
else {
|
||||
try {
|
||||
diagnosticAgent_uninstall();
|
||||
}
|
||||
catch (x) {
|
||||
}
|
||||
} else {
|
||||
try { diagnosticAgent_uninstall(); } catch (x) { }
|
||||
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
|
||||
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
|
||||
}
|
||||
|
@ -1,389 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var SERVICE_WIN32 = 0x00000010 | 0x00000020;
|
||||
var SERVICE_STATE = { STOPPED: 0x00000001, SERVICE_START_PENDING: 0x00000002, SERVICE_STOP_PENDING: 0x00000003, RUNNING: 0x00000004 };
|
||||
var SERVICE_ACCEPT = { SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004, SERVICE_ACCEPT_POWEREVENT: 0x00000040, SERVICE_ACCEPT_SESSIONCHANGE: 0x00000080 };
|
||||
|
||||
var SERVICE_CONTROL = { SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001, SERVICE_CONTROL_POWEREVENT: 0x0000000D, SERVICE_CONTROL_SESSIONCHANGE: 0x0000000E};
|
||||
var SESSION_CHANGE_TYPE =
|
||||
{
|
||||
WTS_CONSOLE_CONNECT: 0x1,
|
||||
WTS_CONSOLE_DISCONNECT: 0x2,
|
||||
WTS_REMOTE_CONNECT: 0x3,
|
||||
WTS_REMOTE_DISCONNECT: 0x4,
|
||||
WTS_SESSION_LOGON: 0x5,
|
||||
WTS_SESSION_LOGOFF: 0x6,
|
||||
WTS_SESSION_LOCK: 0x7,
|
||||
WTS_SESSION_UNLOCK: 0x8,
|
||||
WTS_SESSION_REMOTE_CONTROL: 0x9,
|
||||
WTS_SESSION_CREATE: 0xa,
|
||||
WTS_SESSION_TERMINATE: 0xb
|
||||
};
|
||||
|
||||
|
||||
var NO_ERROR = 0;
|
||||
|
||||
var serviceManager = require('service-manager');
|
||||
|
||||
function serviceHost(serviceName)
|
||||
{
|
||||
this._ObjectID = 'service-host';
|
||||
var emitterUtils = require('events').inherits(this);
|
||||
emitterUtils.createEvent('serviceStart');
|
||||
emitterUtils.createEvent('serviceStop');
|
||||
emitterUtils.createEvent('normalStart');
|
||||
emitterUtils.createEvent('session');
|
||||
emitterUtils.createEvent('powerStateChange');
|
||||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this.GM = require('_GenericMarshal');
|
||||
this.Advapi = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||
this.Advapi.CreateMethod({ method: 'StartServiceCtrlDispatcherA', threadDispatch: 1 });
|
||||
this.Advapi.CreateMethod('RegisterServiceCtrlHandlerExA');
|
||||
this.Advapi.CreateMethod('SetServiceStatus');
|
||||
this.Kernel32 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
this.Kernel32.CreateMethod('GetLastError');
|
||||
|
||||
this.Ole32 = this.GM.CreateNativeProxy('Ole32.dll');
|
||||
this.Ole32.CreateMethod('CoInitializeEx');
|
||||
this.Ole32.CreateMethod('CoUninitialize');
|
||||
|
||||
this._ServiceName = this.GM.CreateVariable(typeof (serviceName) == 'string' ? serviceName : serviceName.name);
|
||||
this._ServiceMain = this.GM.GetGenericGlobalCallback(2);
|
||||
this._ServiceMain.Parent = this;
|
||||
this._ServiceMain.GM = this.GM;
|
||||
this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv)
|
||||
{
|
||||
//ToDo: Check to make sure this is for us
|
||||
|
||||
this.Parent._ServiceStatus = this.GM.CreateVariable(28);
|
||||
//typedef struct _SERVICE_STATUS {
|
||||
// DWORD dwServiceType;
|
||||
// DWORD dwCurrentState;
|
||||
// DWORD dwControlsAccepted;
|
||||
// DWORD dwWin32ExitCode;
|
||||
// DWORD dwServiceSpecificExitCode;
|
||||
// DWORD dwCheckPoint;
|
||||
// DWORD dwWaitHint;
|
||||
//} SERVICE_STATUS, *LPSERVICE_STATUS;
|
||||
|
||||
// Initialise service status
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_WIN32);
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_STOPPED, 4);
|
||||
this.Parent._ServiceStatusHandle = this.Parent.Advapi.RegisterServiceCtrlHandlerExA(this.Parent._ServiceName, this.Parent._ServiceControlHandler, this.Parent.GM.StashObject(this.Parent._ServiceControlHandler));
|
||||
if(this.Parent._ServiceStatusHandle.Val == 0)
|
||||
{
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Service is starting
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_START_PENDING, 4);
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
|
||||
// Service running
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.RUNNING, 4);
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_ACCEPT.SERVICE_ACCEPT_STOP | SERVICE_ACCEPT.SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT.SERVICE_ACCEPT_SESSIONCHANGE, 8);
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
|
||||
this.Parent.Ole32.CoInitializeEx(0, 2);
|
||||
this.Parent.on('~', function OnServiceHostFinalizer()
|
||||
{
|
||||
var GM = require('_GenericMarshal');
|
||||
var Advapi = GM.CreateNativeProxy('Advapi32.dll');
|
||||
Advapi.CreateMethod('SetServiceStatus');
|
||||
|
||||
Kernel32 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
Kernel32.CreateMethod('GetLastError');
|
||||
|
||||
var status = GM.CreateVariable(28);
|
||||
|
||||
// Service was stopped
|
||||
status.toBuffer().writeUInt32LE(SERVICE_WIN32);
|
||||
status.toBuffer().writeUInt32LE(0x00000001, 4);
|
||||
status.toBuffer().writeUInt32LE(0, 8);
|
||||
|
||||
Advapi.SetServiceStatus(this._ServiceStatusHandle, status);
|
||||
|
||||
this.Ole32.CoUninitialize();
|
||||
});
|
||||
|
||||
this.Parent.emit('serviceStart');
|
||||
});
|
||||
this._ServiceControlHandler = this.GM.GetGenericGlobalCallback(4);
|
||||
this._ServiceControlHandler.Parent = this;
|
||||
this._ServiceControlHandler.GM = this.GM;
|
||||
this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code, eventType, eventData, context)
|
||||
{
|
||||
var j = this.Parent.GM.UnstashObject(context);
|
||||
if (j != null && j == this)
|
||||
{
|
||||
switch (code.Val)
|
||||
{
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_STOP:
|
||||
this.Parent.emit('serviceStop');
|
||||
return;
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_SESSIONCHANGE:
|
||||
var sessionId = eventData.Deref(4, 4).toBuffer().readUInt32LE();
|
||||
switch(eventType.Val)
|
||||
{
|
||||
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGON:
|
||||
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGOFF:
|
||||
require('user-sessions').emit('changed');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (serviceName) { this._ServiceOptions = typeof (serviceName) == 'object' ? serviceName : { name: serviceName }; }
|
||||
else
|
||||
{
|
||||
throw ('Must specify either ServiceName or Options');
|
||||
}
|
||||
if (!this._ServiceOptions.servicePath)
|
||||
{
|
||||
this._ServiceOptions.servicePath = process.execPath;
|
||||
}
|
||||
|
||||
this.run = function run()
|
||||
{
|
||||
var serviceOperation = 0;
|
||||
|
||||
for(var i = 0; i<process.argv.length; ++i)
|
||||
{
|
||||
switch(process.argv[i])
|
||||
{
|
||||
case '-install':
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
try
|
||||
{
|
||||
this._svcManager.installService(this._ServiceOptions);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.log(e);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
console.log(this._ServiceOptions.name + ' installed');
|
||||
process.exit();
|
||||
break;
|
||||
case '-uninstall':
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
try
|
||||
{
|
||||
this._svcManager.uninstallService(this._ServiceOptions);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.log(e);
|
||||
process.exit();
|
||||
}
|
||||
if (process.platform == 'win32' || process.platform == 'darwin')
|
||||
{
|
||||
// Only do this on Windows/MacOS, becuase Linux is async... It'll complete later
|
||||
console.log(this._ServiceOptions.name + ' uninstalled');
|
||||
process.exit();
|
||||
}
|
||||
i = process.argv.length;
|
||||
serviceOperation = 1;
|
||||
break;
|
||||
case 'start':
|
||||
case '-d':
|
||||
if (process.platform != 'win32') { break; }
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
this._svcManager.getService(this._ServiceOptions.name).start();
|
||||
console.log(this._ServiceOptions.name + ' starting...');
|
||||
process.exit();
|
||||
break;
|
||||
case 'stop':
|
||||
case '-s':
|
||||
if (process.platform != 'win32') { break; }
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
this._svcManager.getService(this._ServiceOptions.name).stop();
|
||||
console.log(this._ServiceOptions.name + ' stopping...');
|
||||
process.exit();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
var serviceTable = this.GM.CreateVariable(4 * this.GM.PointerSize);
|
||||
this._ServiceName.pointerBuffer().copy(serviceTable.toBuffer());
|
||||
this._ServiceMain.pointerBuffer().copy(serviceTable.toBuffer(), this.GM.PointerSize);
|
||||
this._sscd = this.Advapi.StartServiceCtrlDispatcherA(serviceTable);
|
||||
this._sscd.parent = this;
|
||||
this._sscd.on('done', function OnStartServiceCtrlDispatcherA(retVal) {
|
||||
if (retVal.Val == 0)
|
||||
{
|
||||
this.parent.emit('normalStart');
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
else if (process.platform == 'linux')
|
||||
{
|
||||
var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
|
||||
|
||||
for (var i = 0; i < process.argv.length; ++i) {
|
||||
switch (process.argv[i]) {
|
||||
case 'start':
|
||||
case '-d':
|
||||
var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
|
||||
var pstream = null;
|
||||
try {
|
||||
pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
if (pstream == null) {
|
||||
pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
|
||||
}
|
||||
pstream.end(child.pid.toString());
|
||||
|
||||
console.log(moduleName + ' started!');
|
||||
process.exit();
|
||||
break;
|
||||
case 'stop':
|
||||
case '-s':
|
||||
var pid = null;
|
||||
try {
|
||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||
require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
if (pid == null) {
|
||||
try {
|
||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||
require('fs').unlinkSync('.' + moduleName + '.pid');
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
process.kill(pid);
|
||||
console.log(moduleName + ' stopped');
|
||||
}
|
||||
else {
|
||||
console.log(moduleName + ' not running');
|
||||
}
|
||||
process.exit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceOperation == 0) {
|
||||
// This is non-windows, so we need to check how this binary was started to determine if this was a service start
|
||||
|
||||
// Start by checking if we were started with start/stop
|
||||
var pid = null;
|
||||
try {
|
||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
if (pid == null) {
|
||||
try {
|
||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (pid != null && pid == process.pid) {
|
||||
this.emit('serviceStart');
|
||||
}
|
||||
else {
|
||||
// Now we need to check if we were started with systemd
|
||||
if (require('process-manager').getProcessInfo(1).Name == 'systemd') {
|
||||
this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._checkpid.result = '';
|
||||
this._checkpid.parent = this;
|
||||
this._checkpid.on('exit', function onCheckPIDExit() {
|
||||
var lines = this.result.split('\r\n');
|
||||
for (i in lines) {
|
||||
if (lines[i].startsWith(' Main PID:')) {
|
||||
var tokens = lines[i].split(' ');
|
||||
if (parseInt(tokens[3]) == process.pid) {
|
||||
this.parent.emit('serviceStart');
|
||||
}
|
||||
else {
|
||||
this.parent.emit('normalStart');
|
||||
}
|
||||
delete this.parent._checkpid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.parent.emit('normalStart');
|
||||
delete this.parent._checkpid;
|
||||
});
|
||||
this._checkpid.stdout.on('data', function (chunk) { this.parent.result += chunk.toString(); });
|
||||
this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
|
||||
this._checkpid.stdin.write('exit\n');
|
||||
}
|
||||
else {
|
||||
// This isn't even a systemd platform, so this couldn't have been a service start
|
||||
this.emit('normalStart');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'darwin')
|
||||
{
|
||||
// First let's fetch all the PIDs of running services
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('launchctl list\nexit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var tokens, i;
|
||||
var p = {};
|
||||
for (i = 1; i < lines.length; ++i)
|
||||
{
|
||||
tokens = lines[i].split('\t');
|
||||
if (tokens[0] && tokens[0] != '-') { p[tokens[0]] = tokens[0]; }
|
||||
}
|
||||
|
||||
if(p[process.pid.toString()])
|
||||
{
|
||||
// We are a service!
|
||||
this.emit('serviceStart');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.emit('normalStart');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = serviceHost;
|
@ -1,497 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
function parseServiceStatus(token)
|
||||
{
|
||||
var j = {};
|
||||
var serviceType = token.Deref(0, 4).IntVal;
|
||||
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
|
||||
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
|
||||
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||
{
|
||||
case 0x00000005:
|
||||
j.state = 'CONTINUE_PENDING';
|
||||
break;
|
||||
case 0x00000006:
|
||||
j.state = 'PAUSE_PENDING';
|
||||
break;
|
||||
case 0x00000007:
|
||||
j.state = 'PAUSED';
|
||||
break;
|
||||
case 0x00000004:
|
||||
j.state = 'RUNNING';
|
||||
break;
|
||||
case 0x00000002:
|
||||
j.state = 'START_PENDING';
|
||||
break;
|
||||
case 0x00000003:
|
||||
j.state = 'STOP_PENDING';
|
||||
break;
|
||||
case 0x00000001:
|
||||
j.state = 'STOPPED';
|
||||
break;
|
||||
}
|
||||
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||
j.controlsAccepted = [];
|
||||
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||
{
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
|
||||
}
|
||||
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
|
||||
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
|
||||
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
|
||||
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
|
||||
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
|
||||
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
|
||||
j.pid = token.Deref((7 * 4), 4).toBuffer().readUInt32LE();
|
||||
return (j);
|
||||
}
|
||||
|
||||
function serviceManager()
|
||||
{
|
||||
this._ObjectID = 'service-manager';
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this.GM = require('_GenericMarshal');
|
||||
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||
this.proxy.CreateMethod('OpenSCManagerA');
|
||||
this.proxy.CreateMethod('EnumServicesStatusExA');
|
||||
this.proxy.CreateMethod('OpenServiceA');
|
||||
this.proxy.CreateMethod('QueryServiceStatusEx');
|
||||
this.proxy.CreateMethod('ControlService');
|
||||
this.proxy.CreateMethod('StartServiceA');
|
||||
this.proxy.CreateMethod('CloseServiceHandle');
|
||||
this.proxy.CreateMethod('CreateServiceA');
|
||||
this.proxy.CreateMethod('ChangeServiceConfig2A');
|
||||
this.proxy.CreateMethod('DeleteService');
|
||||
this.proxy.CreateMethod('AllocateAndInitializeSid');
|
||||
this.proxy.CreateMethod('CheckTokenMembership');
|
||||
this.proxy.CreateMethod('FreeSid');
|
||||
|
||||
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
this.proxy2.CreateMethod('GetLastError');
|
||||
|
||||
this.isAdmin = function isAdmin() {
|
||||
var NTAuthority = this.GM.CreateVariable(6);
|
||||
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||
var AdministratorsGroup = this.GM.CreatePointer();
|
||||
var admin = false;
|
||||
|
||||
if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||
{
|
||||
var member = this.GM.CreateInteger();
|
||||
if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||
{
|
||||
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||
}
|
||||
this.proxy.FreeSid(AdministratorsGroup.Deref());
|
||||
}
|
||||
return admin;
|
||||
};
|
||||
this.getProgramFolder = function getProgramFolder()
|
||||
{
|
||||
if (require('os').arch() == 'x64')
|
||||
{
|
||||
// 64 bit Windows
|
||||
if (this.GM.PointerSize == 4)
|
||||
{
|
||||
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||
}
|
||||
return process.env['ProgramFiles']; // 64 bit App
|
||||
}
|
||||
|
||||
// 32 bit Windows
|
||||
return process.env['ProgramFiles'];
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||
|
||||
this.enumerateService = function () {
|
||||
var machineName = this.GM.CreatePointer();
|
||||
var dbName = this.GM.CreatePointer();
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
|
||||
|
||||
var bytesNeeded = this.GM.CreatePointer();
|
||||
var servicesReturned = this.GM.CreatePointer();
|
||||
var resumeHandle = this.GM.CreatePointer();
|
||||
//var services = this.proxy.CreateVariable(262144);
|
||||
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
if (bytesNeeded.IntVal <= 0) {
|
||||
throw ('error enumerating services');
|
||||
}
|
||||
var sz = bytesNeeded.IntVal;
|
||||
var services = this.GM.CreateVariable(sz);
|
||||
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
console.log("servicesReturned", servicesReturned.IntVal);
|
||||
|
||||
var ptrSize = dbName._size;
|
||||
var blockSize = 36 + (2 * ptrSize);
|
||||
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
|
||||
var retVal = [];
|
||||
for (var i = 0; i < servicesReturned.IntVal; ++i) {
|
||||
var token = services.Deref(i * blockSize, blockSize);
|
||||
var j = {};
|
||||
j.name = token.Deref(0, ptrSize).Deref().String;
|
||||
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
|
||||
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
|
||||
retVal.push(j);
|
||||
}
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (retVal);
|
||||
}
|
||||
this.getService = function (name) {
|
||||
var serviceName = this.GM.CreateVariable(name);
|
||||
var ptr = this.GM.CreatePointer();
|
||||
var bytesNeeded = this.GM.CreateVariable(ptr._size);
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
|
||||
if (handle.Val == 0) { throw ('could not open ServiceManager'); }
|
||||
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
|
||||
if (h.Val != 0) {
|
||||
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
|
||||
var status = this.GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE());
|
||||
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
|
||||
if (success != 0) {
|
||||
retVal = {};
|
||||
retVal.status = parseServiceStatus(status);
|
||||
retVal._scm = handle;
|
||||
retVal._service = h;
|
||||
retVal._GM = this.GM;
|
||||
retVal._proxy = this.proxy;
|
||||
require('events').inherits(retVal);
|
||||
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
|
||||
retVal.name = name;
|
||||
retVal.stop = function () {
|
||||
if (this.status.state == 'RUNNING') {
|
||||
var newstate = this._GM.CreateVariable(36);
|
||||
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.stop() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
retVal.start = function () {
|
||||
if (this.status.state == 'STOPPED') {
|
||||
var success = this._proxy.StartServiceA(this._service, 0, 0);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.start() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
return (retVal);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('could not find service: ' + name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.isAdmin = function isAdmin()
|
||||
{
|
||||
return (require('user-sessions').isRoot());
|
||||
}
|
||||
}
|
||||
this.installService = function installService(options)
|
||||
{
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
|
||||
|
||||
// Before we start, we need to copy the binary to the right place
|
||||
var folder = this.getServiceFolder();
|
||||
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
|
||||
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
|
||||
options.servicePath = folder + '\\' + options.name + '.exe';
|
||||
|
||||
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||
if (handle.Val == 0) { throw ('error opening SCManager'); }
|
||||
var serviceName = this.GM.CreateVariable(options.name);
|
||||
var displayName = this.GM.CreateVariable(options.name);
|
||||
var allAccess = 0x000F01FF;
|
||||
var serviceType;
|
||||
|
||||
|
||||
switch (options.startType) {
|
||||
case 'BOOT_START':
|
||||
serviceType = 0x00;
|
||||
break;
|
||||
case 'SYSTEM_START':
|
||||
serviceType = 0x01;
|
||||
break;
|
||||
case 'AUTO_START':
|
||||
serviceType = 0x02;
|
||||
break;
|
||||
case 'DEMAND_START':
|
||||
serviceType = 0x03;
|
||||
break;
|
||||
default:
|
||||
serviceType = 0x04; // Disabled
|
||||
break;
|
||||
}
|
||||
|
||||
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
|
||||
if (h.Val == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service: ' + this.proxy2.GetLastError().Val); }
|
||||
if (options.description) {
|
||||
console.log(options.description);
|
||||
|
||||
var dscPtr = this.GM.CreatePointer();
|
||||
dscPtr.Val = this.GM.CreateVariable(options.description);
|
||||
|
||||
if (this.proxy.ChangeServiceConfig2A(h, 1, dscPtr) == 0) {
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('Unable to set description');
|
||||
}
|
||||
}
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (this.getService(options.name));
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||
console.log('copying ' + options.servicePath);
|
||||
var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/etc/init.d/' + options.name, m);
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('update-rc.d ' + options.name + ' defaults\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
//update-rc.d meshagent defaults # creates symlinks for rc.d
|
||||
//service meshagent start
|
||||
|
||||
this._update.waitExit();
|
||||
|
||||
break;
|
||||
case 'systemd':
|
||||
var serviceDescription = options.description ? options.description : 'MeshCentral Agent';
|
||||
if (!require('fs').existsSync('/usr/local/mesh')) { require('fs').mkdirSync('/usr/local/mesh'); }
|
||||
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh/' + options.name);
|
||||
var m = require('fs').statSync('/usr/local/mesh/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/usr/local/mesh/' + options.name, m);
|
||||
require('fs').writeFileSync('/lib/systemd/system/' + options.name + '.service', '[Unit]\nDescription=' + serviceDescription + '\n[Service]\nExecStart=/usr/local/mesh/' + options.name + '\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=' + options.name + '.service\n', { flags: 'w' });
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl enable ' + options.name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(process.platform == 'darwin')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||
|
||||
// Mac OS
|
||||
var stdoutpath = (options.stdout ? ('<key>StandardOutPath</key>\n<string>' + options.stdout + '</string>') : '');
|
||||
var autoStart = (options.startType == 'AUTO_START' ? '<true/>' : '<false/>');
|
||||
var params = ' <key>ProgramArguments</key>\n';
|
||||
params += ' <array>\n';
|
||||
params += (' <string>/usr/local/mesh_services/' + options.name + '/' + options.name + '</string>\n');
|
||||
if(options.parameters)
|
||||
{
|
||||
for(var itm in options.parameters)
|
||||
{
|
||||
params += (' <string>' + options.parameters[itm] + '</string>\n');
|
||||
}
|
||||
}
|
||||
params += ' </array>\n';
|
||||
|
||||
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||
plist += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
||||
plist += '<plist version="1.0">\n';
|
||||
plist += ' <dict>\n';
|
||||
plist += ' <key>Label</key>\n';
|
||||
plist += (' <string>' + options.name + '</string>\n');
|
||||
plist += (params + '\n');
|
||||
plist += ' <key>WorkingDirectory</key>\n';
|
||||
plist += (' <string>/usr/local/mesh_services/' + options.name + '</string>\n');
|
||||
plist += (stdoutpath + '\n');
|
||||
plist += ' <key>RunAtLoad</key>\n';
|
||||
plist += (autoStart + '\n');
|
||||
plist += ' </dict>\n';
|
||||
plist += '</plist>';
|
||||
|
||||
if (!require('fs').existsSync('/usr/local/mesh_services')) { require('fs').mkdirSync('/usr/local/mesh_services'); }
|
||||
if (!require('fs').existsSync('/Library/LaunchDaemons/' + options.name + '.plist'))
|
||||
{
|
||||
if (!require('fs').existsSync('/usr/local/mesh_services/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_services/' + options.name); }
|
||||
if (options.binary)
|
||||
{
|
||||
require('fs').writeFileSync('/usr/local/mesh_services/' + options.name + '/' + options.name, options.binary);
|
||||
}
|
||||
else
|
||||
{
|
||||
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_services/' + options.name + '/' + options.name);
|
||||
}
|
||||
require('fs').writeFileSync('/Library/LaunchDaemons/' + options.name + '.plist', plist);
|
||||
var m = require('fs').statSync('/usr/local/mesh_services/' + options.name + '/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/usr/local/mesh_services/' + options.name + '/' + options.name, m);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Service: ' + options.name + ' already exists');
|
||||
}
|
||||
}
|
||||
}
|
||||
this.uninstallService = function uninstallService(name)
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||
|
||||
if (typeof (name) == 'object') { name = name.name; }
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
var service = this.getService(name);
|
||||
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||
{
|
||||
if (this.proxy.DeleteService(service._service) == 0)
|
||||
{
|
||||
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'linux')
|
||||
{
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('service ' + name + ' stop\n');
|
||||
this._update.stdin.write('update-rc.d -f ' + name + ' remove\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/etc/init.d/' + name);
|
||||
console.log(name + ' uninstalled');
|
||||
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(name + ' could not be uninstalled', e)
|
||||
}
|
||||
break;
|
||||
case 'systemd':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl stop ' + name + '.service\n');
|
||||
this._update.stdin.write('systemctl disable ' + name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/usr/local/mesh/' + name);
|
||||
require('fs').unlinkSync('/lib/systemd/system/' + name + '.service');
|
||||
console.log(name + ' uninstalled');
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(name + ' could not be uninstalled', e)
|
||||
}
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'darwin')
|
||||
{
|
||||
if (require('fs').existsSync('/Library/LaunchDaemons/' + name + '.plist'))
|
||||
{
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.on('data', function (chunk) { });
|
||||
child.stdin.write('launchctl stop ' + name + '\n');
|
||||
child.stdin.write('launchctl unload /Library/LaunchDaemons/' + name + '.plist\n');
|
||||
child.stdin.write('exit\n');
|
||||
child.waitExit();
|
||||
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/usr/local/mesh_services/' + name + '/' + name);
|
||||
require('fs').unlinkSync('/Library/LaunchDaemons/' + name + '.plist');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
throw ('Error uninstalling service: ' + name + ' => ' + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
require('fs').rmdirSync('/usr/local/mesh_services/' + name);
|
||||
}
|
||||
catch(e)
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Service: ' + name + ' does not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
this.getServiceType = function getServiceType()
|
||||
{
|
||||
return (require('process-manager').getProcessInfo(1).Name);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = serviceManager;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -24,6 +24,7 @@ limitations under the License.
|
||||
|
||||
const exeJavaScriptGuid = 'B996015880544A19B7F7E9BE44914C18';
|
||||
const exeMeshPolicyGuid = 'B996015880544A19B7F7E9BE44914C19';
|
||||
const exeNullPolicyGuid = 'B996015880544A19B7F7E9BE44914C20';
|
||||
|
||||
|
||||
// Changes a Windows Executable to add JavaScript inside of it.
|
||||
@ -76,6 +77,7 @@ module.exports.streamExeWithJavaScript = function (options) {
|
||||
// sourceFileName: 'pathToBinary',
|
||||
// destinationStream: 'outputStream'
|
||||
// msh: 'mshContent',
|
||||
// randomPolicy: true, // Set is the MSH contains random data
|
||||
// peinfo {} // Optional, if PE header already parsed place it here.
|
||||
// }
|
||||
//
|
||||
@ -100,7 +102,7 @@ module.exports.streamExeWithMeshPolicy = function (options) {
|
||||
var sz = Buffer.alloc(4);
|
||||
sz.writeUInt32BE(this.options.msh.length, 0);
|
||||
this.options.destinationStream.write(sz); // Length in small endian
|
||||
this.options.destinationStream.end(Buffer.from(exeMeshPolicyGuid, 'hex')); // Guid
|
||||
this.options.destinationStream.end(Buffer.from((this.options.randomPolicy === true) ? exeNullPolicyGuid : exeMeshPolicyGuid, 'hex')); // Guid
|
||||
});
|
||||
// Pipe the entire source binary without ending the stream.
|
||||
options.destinationStream.sourceStream.pipe(options.destinationStream, { end: false });
|
||||
@ -140,7 +142,7 @@ module.exports.streamExeWithMeshPolicy = function (options) {
|
||||
var sz = Buffer.alloc(4);
|
||||
sz.writeUInt32BE(this.options.msh.length, 0);
|
||||
this.options.destinationStream.write(sz); // MSH Length, small-endian
|
||||
this.options.destinationStream.end(Buffer.from(exeMeshPolicyGuid, 'hex')); // MSH GUID
|
||||
this.options.destinationStream.end(Buffer.from((this.options.randomPolicy === true) ? exeNullPolicyGuid : exeMeshPolicyGuid, 'hex')); // Guid
|
||||
});
|
||||
source3.pipe(this.options.destinationStream, { end: false });
|
||||
this.options.sourceStream = source3;
|
||||
|
@ -1626,12 +1626,38 @@ function CreateMeshCentralServer(config, args) {
|
||||
obj.meshAgentBinaries[archid].path = agentpath;
|
||||
obj.meshAgentBinaries[archid].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?id=' + archid;
|
||||
obj.meshAgentBinaries[archid].size = stats.size;
|
||||
if (obj.args.agentsinram) { obj.meshAgentBinaries[archid].data = obj.fs.readFileSync(agentpath); }
|
||||
|
||||
// If this is a windows binary, pull binary information
|
||||
if (obj.meshAgentsArchitectureNumbers[archid].platform == 'win32') {
|
||||
try { obj.meshAgentBinaries[archid].pe = obj.exeHandler.parseWindowsExecutable(agentpath); } catch (e) { }
|
||||
}
|
||||
|
||||
// If agents must be stored in RAM or if this is a Windows 32/64 agent, load the agent in RAM.
|
||||
if ((obj.args.agentsinram) || (archid == 3) || (archid == 4)) {
|
||||
if ((archid == 3) || (archid == 4)) {
|
||||
// Load the agent with a random msh added to it.
|
||||
var outStream = new require('stream').Duplex();
|
||||
outStream.meshAgentBinary = obj.meshAgentBinaries[archid];
|
||||
outStream.meshAgentBinary.randomMsh = Buffer.from(obj.crypto.randomBytes(64), 'binary').toString('base64');
|
||||
outStream.bufferList = [];
|
||||
outStream._write = function (chunk, encoding, callback) { this.bufferList.push(chunk); if (callback) callback(); }; // Append the chuck.
|
||||
outStream._read = function (size) { }; // Do nothing, this is not going to be called.
|
||||
outStream.on('finish', function () { this.meshAgentBinary.data = Buffer.concat(this.bufferList); this.meshAgentBinary.size = this.meshAgentBinary.data.length; delete this.bufferList; }) // Merge all chunks
|
||||
obj.exeHandler.streamExeWithMeshPolicy(
|
||||
{
|
||||
platform: 'win32',
|
||||
sourceFileName: agentpath,
|
||||
destinationStream: outStream,
|
||||
randomPolicy: true, // Indicates that the msh policy is random data.
|
||||
msh: outStream.meshAgentBinary.randomMsh,
|
||||
peinfo: obj.meshAgentBinaries[archid].pe
|
||||
});
|
||||
} else {
|
||||
// Load the agent as-is
|
||||
obj.meshAgentBinaries[archid].data = obj.fs.readFileSync(agentpath);
|
||||
}
|
||||
}
|
||||
|
||||
// Hash the binary
|
||||
var hashStream = obj.crypto.createHash('sha384');
|
||||
hashStream.archid = archid;
|
||||
|
66
meshuser.js
66
meshuser.js
@ -35,6 +35,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
const MESHRIGHT_DESKLIMITEDINPUT = 4096;
|
||||
const MESHRIGHT_LIMITEVENTS = 8192;
|
||||
const MESHRIGHT_CHATNOTIFY = 16384;
|
||||
const MESHRIGHT_UNINSTALL = 32768;
|
||||
|
||||
// Site rights
|
||||
const SITERIGHT_SERVERBACKUP = 1;
|
||||
@ -49,6 +50,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
var obj = {};
|
||||
obj.user = user;
|
||||
obj.domain = domain;
|
||||
obj.ws = ws;
|
||||
|
||||
// Server side Intel AMT stack
|
||||
const WsmanComm = require('./amt/amt-wsman-comm.js');
|
||||
@ -609,7 +611,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
try { fs.mkdirSync(path); } catch (e) { }
|
||||
try { fs.mkdirSync(path + "/" + command.newfolder); } catch (e) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (command.fileop == 'delete') {
|
||||
// Delete a file
|
||||
if (common.validateArray(command.delfiles, 1) == false) return;
|
||||
@ -667,7 +669,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
switch (cmd) {
|
||||
case 'help': {
|
||||
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
|
||||
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
|
||||
r += 'migrationagents, agentstats, webstats, mpsstats, swarmstats, acceleratorsstats, updatecheck, serverupdate, nodeconfig,\r\n';
|
||||
r += 'heapdump, relays, autobackup, backupconfig, dupagents, dispatchtable.';
|
||||
break;
|
||||
@ -733,7 +735,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'info': {
|
||||
var info = process.memoryUsage();
|
||||
info.dbType = ['None','NeDB','MongoJS','MongoDB'][parent.db.databaseType];
|
||||
info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType];
|
||||
if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; }
|
||||
try { info.platform = process.platform; } catch (ex) { }
|
||||
try { info.arch = process.arch; } catch (ex) { }
|
||||
@ -811,7 +813,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (config.domains[i].yubikey && config.domains[i].yubikey.secret) { config.domains[i].yubikey.secret = '(present)'; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
r = JSON.stringify(removeAllUnderScore(config), null, 4);
|
||||
break;
|
||||
}
|
||||
@ -1333,7 +1335,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (command.email != null) { newuser.email = command.email.toLowerCase(); if (command.emailVerified === true) { newuser.emailVerified = true; } } // Email
|
||||
if (command.resetNextLogin === true) { newuser.passchange = -1; } else { newuser.passchange = Math.floor(Date.now() / 1000); }
|
||||
if (user.groups) { newuser.groups = user.groups; } // New accounts are automatically part of our groups (Realms).
|
||||
|
||||
|
||||
parent.users[newuserid] = newuser;
|
||||
|
||||
// Create a user, generate a salt and hash the password
|
||||
@ -1860,7 +1862,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
if (unknownUsers.length > 0) {
|
||||
// Send error back, user not found.
|
||||
displayNotificationMessage('User' + ((unknownUsers.length > 1)?'s':'') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', 'Device Group', 'ServerNotify');
|
||||
displayNotificationMessage('User' + ((unknownUsers.length > 1) ? 's' : '') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', 'Device Group', 'ServerNotify');
|
||||
}
|
||||
|
||||
if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: 'ok', removed: removedCount, failed: failCount })); } catch (ex) { } }
|
||||
@ -2188,6 +2190,37 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
try { ws.send(JSON.stringify({ action: 'wakedevices' })); } catch (ex) { }
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if (mesh.links[user._id] != null && ((mesh.links[user._id].rights & MESHRIGHT_UNINSTALL) != 0)) {
|
||||
// Send uninstall command to connected agent
|
||||
var agent = parent.wsagents[node._id];
|
||||
if (agent != null) {
|
||||
//console.log('Asking agent ' + agent.dbNodeKey + ' to uninstall.');
|
||||
try { agent.send(JSON.stringify({ action: 'uninstallagent' })); } catch (ex) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'poweraction':
|
||||
@ -2450,8 +2483,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
case 'inviteAgent':
|
||||
{
|
||||
var err = null, mesh = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
if ((parent.parent.mailserver == null) || (args.lanonly == true)) { err = 'Unsupported feature'; } // This operation requires the email server
|
||||
else if ((parent.parent.certificates.CommonName == null) || (parent.parent.certificates.CommonName.indexOf('.') == -1)) { err = 'Unsupported feature'; } // Server name must be configured
|
||||
else if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check meshid
|
||||
@ -3001,7 +3033,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Invalid node id' })); } catch (ex) { } return; } }
|
||||
var node = nodes[0];
|
||||
|
||||
|
||||
// Get the device group for this node
|
||||
var mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
@ -3038,11 +3070,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if (common.validateInt(command.mode, 0, 3) == false) break; // Check connection mode
|
||||
// Validate if communication mode is possible
|
||||
if (command.mode == null || command.mode==0) {
|
||||
if (command.mode == null || command.mode == 0) {
|
||||
break; //unsupported
|
||||
} else if (command.mode == 1) {
|
||||
var state = parent.parent.GetConnectivityState(command.nodeid);
|
||||
if ( (state == null) || (state.connectivity & 4)==0 ) break;
|
||||
if ((state == null) || (state.connectivity & 4) == 0) break;
|
||||
} else if (command.mode == 2) {
|
||||
if (parent.parent.mpsserver.ciraConnections[command.nodeid] == null) break;
|
||||
} else if (command.mode == 3) {
|
||||
@ -3068,15 +3100,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'plugin': {
|
||||
if (parent.parent.pluginHandler == null) break; // If the plugin's are not supported, reject this command.
|
||||
command.userid = user._id;
|
||||
|
||||
if (command.routeToNode === true) {
|
||||
routeCommandToNode(command);
|
||||
routeCommandToNode(command);
|
||||
} else {
|
||||
// TODO
|
||||
try {
|
||||
var pluginHandler = require('./pluginHandler.js').pluginHandler(parent.parent);
|
||||
pluginHandler.plugins[command.plugin].serveraction(command, obj, parent);
|
||||
} catch (e) { console.log('Error loading plugin handler (' + e + ')'); }
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Unknown user action
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.4.2-z",
|
||||
"version": "0.4.3-c",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
@ -37,8 +37,10 @@
|
||||
"express": "^4.17.0",
|
||||
"express-handlebars": "^3.1.0",
|
||||
"express-ws": "^4.0.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"ipcheck": "^0.1.0",
|
||||
"meshcentral": "*",
|
||||
"minify-js": "0.0.4",
|
||||
"minimist": "^1.2.0",
|
||||
"multiparty": "^4.2.1",
|
||||
"nedb": "^1.8.0",
|
||||
|
@ -1,18 +1,4 @@
|
||||
@ECHO OFF
|
||||
CALL:CompressHandlebars default
|
||||
CALL:CompressHandlebars default-mobile
|
||||
CALL:CompressHandlebars login
|
||||
CALL:CompressHandlebars login-mobile
|
||||
CALL:CompressHandlebars messenger
|
||||
PAUSE
|
||||
GOTO:eof
|
||||
|
||||
:CompressHandlebars
|
||||
ECHO COMPRESS ..\views\%~1.handlebars TO ..\views\%~1-min.handlebars
|
||||
DEL ..\views\%~1-min.handlebars
|
||||
COPY ..\views\%~1.handlebars index.html
|
||||
..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe compress.wcc -c
|
||||
COPY compress.htm ..\views\%~1-min.handlebars
|
||||
DEL compress.htm
|
||||
DEL index.html
|
||||
GOTO:eof
|
||||
CD ..\translate
|
||||
C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js minifyall
|
||||
C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js translateall
|
||||
|
3
public/minify.bat
Normal file
3
public/minify.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@ECHO OFF
|
||||
CD ..\translate
|
||||
C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js minifyall
|
1
public/player-min.htm
Normal file
1
public/player-min.htm
Normal file
File diff suppressed because one or more lines are too long
1
public/translations/player-min_fr.htm
Normal file
1
public/translations/player-min_fr.htm
Normal file
File diff suppressed because one or more lines are too long
@ -13,7 +13,8 @@ var translationTable = null;
|
||||
var sourceStrings = null;
|
||||
var jsdom = null; //require('jsdom');
|
||||
var esprima = null; //require('esprima'); // https://www.npmjs.com/package/esprima
|
||||
//var { JSDOM } = jsdom;
|
||||
var minifyLib = 2; // 0 = None, 1 = minify-js, 2 = HTMLMinifier
|
||||
var minify = null;
|
||||
|
||||
var meshCentralSourceFiles = [
|
||||
"../views/agentinvite.handlebars",
|
||||
@ -21,6 +22,7 @@ var meshCentralSourceFiles = [
|
||||
"../views/default-mobile.handlebars",
|
||||
"../views/download.handlebars",
|
||||
"../views/error404.handlebars",
|
||||
"../views/error404-mobile.handlebars",
|
||||
"../views/login.handlebars",
|
||||
"../views/login-mobile.handlebars",
|
||||
"../views/message.handlebars",
|
||||
@ -32,15 +34,20 @@ var meshCentralSourceFiles = [
|
||||
// node translate.json EXTRACT bob.json ../meshcentral/views/default.handlebars
|
||||
// node translate.js TRANSLATE fr test2.json ../meshcentral/views/default.handlebars
|
||||
|
||||
InstallModules(['jsdom', 'esprima'], start);
|
||||
var libs = ['jsdom', 'esprima', 'minify-js'];
|
||||
if (minifyLib == 1) { libs.push('minify-js'); }
|
||||
if (minifyLib == 2) { libs.push('html-minifier'); }
|
||||
InstallModules(libs, start);
|
||||
|
||||
function start() {
|
||||
jsdom = require('jsdom');
|
||||
esprima = require('esprima'); // https://www.npmjs.com/package/esprima
|
||||
if (minifyLib == 1) { minify = require('minify-js'); }
|
||||
if (minifyLib == 2) { minify = require('html-minifier').minify; } // https://www.npmjs.com/package/html-minifier
|
||||
|
||||
var command = null;
|
||||
if (process.argv.length > 2) { command = process.argv[2].toLowerCase(); }
|
||||
if (['check', 'extract', 'extractall', 'translate', 'translateall'].indexOf(command) == -1) { command = null; }
|
||||
if (['check', 'extract', 'extractall', 'translate', 'translateall', 'minifyall'].indexOf(command) == -1) { command = null; }
|
||||
|
||||
console.log('MeshCentral web site translator');
|
||||
if (command == null) {
|
||||
@ -61,6 +68,9 @@ function start() {
|
||||
console.log('');
|
||||
console.log(' TRANSLATEALL');
|
||||
console.log(' Translate all MeshCentral strings using the languages.json file.');
|
||||
console.log('');
|
||||
console.log(' MINIFYALL');
|
||||
console.log(' Minify the main MeshCentral english web pages.');
|
||||
process.exit();
|
||||
return;
|
||||
}
|
||||
@ -111,6 +121,44 @@ function start() {
|
||||
|
||||
translate(lang, langFile, sources, false);
|
||||
}
|
||||
|
||||
if (command == 'minifyall') {
|
||||
for (var i in meshCentralSourceFiles) {
|
||||
var outname = meshCentralSourceFiles[i];
|
||||
var outnamemin = null;
|
||||
if (outname.endsWith('.handlebars')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 11) + '-min.handlebars');
|
||||
} else if (outname.endsWith('.html')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 5) + '-min.html');
|
||||
} else if (outname.endsWith('.htm')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 4) + '-min.htm');
|
||||
} else {
|
||||
outnamemin = (outname, outname + '.min');
|
||||
}
|
||||
console.log('Generating ' + outnamemin + '...');
|
||||
|
||||
// Minify the file
|
||||
if (minifyLib = 2) {
|
||||
var minifiedOut = minify(fs.readFileSync(outname).toString(), {
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: false, // This is not good.
|
||||
collapseWhitespace: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
removeComments: true,
|
||||
removeOptionalTags: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeTagWhitespace: true,
|
||||
preserveLineBreaks: false,
|
||||
useShortDoctype: true
|
||||
});
|
||||
fs.writeFileSync(outnamemin, minifiedOut, { flag: 'w+' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function translate(lang, langFile, sources, createSubDir) {
|
||||
@ -129,7 +177,7 @@ function translate(lang, langFile, sources, createSubDir) {
|
||||
for (var i in langs) { translateEx(i, langFileData, sources, createSubDir); }
|
||||
}
|
||||
|
||||
process.exit();
|
||||
//process.exit();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -252,14 +300,59 @@ function translateFromHtml(lang, file, createSubDir) {
|
||||
var out = dom.serialize();
|
||||
|
||||
var outname = file;
|
||||
var outnamemin = null;
|
||||
if (createSubDir != null) { outname = path.join(path.dirname(file), createSubDir, path.basename(file)); }
|
||||
if (outname.endsWith('.handlebars')) { outname = (outname.substring(0, outname.length - 11) + '_' + lang + '.handlebars'); }
|
||||
else if (outname.endsWith('.html')) { outname = (outname.substring(0, outname.length - 5) + '_' + lang + '.html'); }
|
||||
else if (outname.endsWith('.htm')) { outname = (outname.substring(0, outname.length - 4) + '_' + lang + '.htm'); }
|
||||
else { outname = (outname + '_' + lang); }
|
||||
if (outname.endsWith('.handlebars')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 11) + '-min_' + lang + '.handlebars');
|
||||
outname = (outname.substring(0, outname.length - 11) + '_' + lang + '.handlebars');
|
||||
} else if (outname.endsWith('.html')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 5) + '-min_' + lang + '.html');
|
||||
outname = (outname.substring(0, outname.length - 5) + '_' + lang + '.html');
|
||||
} else if (outname.endsWith('.htm')) {
|
||||
outnamemin = (outname.substring(0, outname.length - 4) + '-min_' + lang + '.htm');
|
||||
outname = (outname.substring(0, outname.length - 4) + '_' + lang + '.htm');
|
||||
} else {
|
||||
outnamemin = (outname + '_' + lang + '.min');
|
||||
outname = (outname + '_' + lang);
|
||||
}
|
||||
fs.writeFileSync(outname, out, { flag: 'w+' });
|
||||
|
||||
// Minify the file
|
||||
if (minifyLib == 1) {
|
||||
minify.file({
|
||||
file: outname,
|
||||
dist: outnamemin
|
||||
}, (e, compress) => {
|
||||
if (e) { console.log('ERROR ', e); return done(); }
|
||||
compress.run((e) => { e ? console.log('Minification fail', e) : console.log('Minification sucess'); minifyDone(); });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Minify the file
|
||||
if (minifyLib = 2) {
|
||||
var minifiedOut = minify(out, {
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: false, // This is not good.
|
||||
collapseWhitespace: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
removeComments: true,
|
||||
removeOptionalTags: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeTagWhitespace: true,
|
||||
preserveLineBreaks: false,
|
||||
useShortDoctype: true
|
||||
});
|
||||
fs.writeFileSync(outnamemin, minifiedOut, { flag: 'w+' });
|
||||
}
|
||||
}
|
||||
|
||||
function minifyDone() { console.log('Completed minification.'); }
|
||||
|
||||
function translateStrings(name, node) {
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
var subnode = node.childNodes[i];
|
||||
|
1
views/agentinvite-min.handlebars
Normal file
1
views/agentinvite-min.handlebars
Normal file
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 one or more lines are too long
@ -568,8 +568,8 @@
|
||||
</div>
|
||||
<div style="height:60px">
|
||||
<div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:white">
|
||||
<label><input type="checkbox" id='d7showfocus'>Show Focus Tool<br></label>
|
||||
<label><input type="checkbox" id='d7showcursor'>Show Local Mouse Cursor<br</label>>
|
||||
<label><input type="checkbox" id='d7showfocus' />Show Focus Tool</label><br />
|
||||
<label><input type="checkbox" id='d7showcursor' />Show Local Mouse Cursor</label><br />
|
||||
</div>
|
||||
<div>Other</div>
|
||||
</div>
|
||||
|
@ -3331,13 +3331,24 @@
|
||||
}
|
||||
|
||||
function groupActionFunction() {
|
||||
var mqttx = '';
|
||||
if (features & 0x00400000) { // Check if any of the selected devices have a MQTT connection active
|
||||
var addedOptions = '';
|
||||
|
||||
// Check if any of the selected devices have a MQTT connection active
|
||||
if (features & 0x00400000) {
|
||||
var nodeids = getCheckedDevices();
|
||||
for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { mqttx = '<option value=103>' + "Send MQTT Message" + '</option>'; } }
|
||||
for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Send MQTT Message" + '</option>'; break; } }
|
||||
}
|
||||
|
||||
// Display the "Uninstall Agent" option if allowed and we selected connected devices.
|
||||
for (var i in nodeids) {
|
||||
var node = getNodeFromId(nodeids[i]);
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
}
|
||||
|
||||
var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
|
||||
x += addHtmlValue("Operation", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Reset devices" + '</option><option value=2>' + "Power off devices" + '</option><option value=102>' + "Move to device group" + '</option>' + mqttx + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
x += addHtmlValue("Operation", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Reset devices" + '</option><option value=2>' + "Power off devices" + '</option><option value=102>' + "Move to device group" + '</option>' + addedOptions + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
|
||||
}
|
||||
|
||||
@ -3365,6 +3376,9 @@
|
||||
} else if (op == 103) {
|
||||
// Send MQTT Message
|
||||
p10showSendMqttMsgDialog(getCheckedDevices());
|
||||
} else if (op == 104) {
|
||||
// Uninstall agent
|
||||
p10showSendUninstallAgentDialog(getCheckedDevices());
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
|
||||
@ -4505,6 +4519,7 @@
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
y += '</select>';
|
||||
x += addHtmlValue("Operation", y);
|
||||
setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
|
||||
@ -4518,6 +4533,9 @@
|
||||
} else if (op == 103) {
|
||||
// Send MQTT Message
|
||||
p10showSendMqttMsgDialog([currentNode._id]);
|
||||
} else if (op == 104) {
|
||||
// Uninstall agent
|
||||
p10showSendUninstallAgentDialog([currentNode._id]);
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
|
||||
@ -4664,6 +4682,21 @@
|
||||
meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
|
||||
}
|
||||
|
||||
function p10showSendUninstallAgentDialog(nodeids) {
|
||||
if (xxdialogMode) return false;
|
||||
var x = '';
|
||||
if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
|
||||
x += '<br /><br />';
|
||||
if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
|
||||
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
|
||||
setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
|
||||
p10validateSendUninstallAgentDialog();
|
||||
return false;
|
||||
}
|
||||
|
||||
function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
|
||||
function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
|
||||
|
||||
function p10showChangeGroupDialog(nodeids) {
|
||||
if (xxdialogMode) return false;
|
||||
var targetMeshId = null;
|
||||
@ -7406,6 +7439,7 @@
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Edit Device Notes" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Show Only Own Events" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Notify" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>' + "Uninstall Agent" + '</label><br>';
|
||||
x += '</div>';
|
||||
if (userid == null) {
|
||||
setDialogMode(2, "Add Users to Device Group", 3, p20showAddMeshUserDialogEx, x);
|
||||
@ -7433,7 +7467,7 @@
|
||||
if (meshrights & 128) { Q('p20editnotes').checked = true; }
|
||||
if (meshrights & 8192) { Q('p20limitevents').checked = true; }
|
||||
if (meshrights & 16384) { Q('p20chatnotify').checked = true; }
|
||||
|
||||
if (meshrights & 32768) { Q('p20uninstall').checked = true; }
|
||||
}
|
||||
}
|
||||
p20validateAddMeshUserDialog();
|
||||
@ -7481,21 +7515,24 @@
|
||||
}
|
||||
QE('idx_dlgOkButton', ok);
|
||||
|
||||
var nc = !Q('p20fulladmin').checked;
|
||||
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
||||
QE('p20editmesh', (!Q('p20fulladmin').checked) && (meshrights == 0xFFFFFFFF));
|
||||
QE('p20manageusers', !Q('p20fulladmin').checked);
|
||||
QE('p20managecomputers', !Q('p20fulladmin').checked);
|
||||
QE('p20remotecontrol', !Q('p20fulladmin').checked);
|
||||
QE('p20meshagentconsole', !Q('p20fulladmin').checked);
|
||||
QE('p20meshserverfiles', !Q('p20fulladmin').checked);
|
||||
QE('p20wakedevices', !Q('p20fulladmin').checked);
|
||||
QE('p20editnotes', !Q('p20fulladmin').checked);
|
||||
QE('p20limitevents', !Q('p20fulladmin').checked);
|
||||
QE('p20remoteview', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20remotelimitedinput', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
|
||||
QE('p20noterminal', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20nofiles', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20noamt', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF));
|
||||
QE('p20manageusers', nc);
|
||||
QE('p20managecomputers', nc);
|
||||
QE('p20remotecontrol', nc);
|
||||
QE('p20meshagentconsole', nc);
|
||||
QE('p20meshserverfiles', nc);
|
||||
QE('p20wakedevices', nc);
|
||||
QE('p20editnotes', nc);
|
||||
QE('p20limitevents', nc);
|
||||
QE('p20remoteview', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20remotelimitedinput', nc && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
|
||||
QE('p20noterminal', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20nofiles', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20noamt', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20chatnotify', nc);
|
||||
QE('p20uninstall', nc);
|
||||
}
|
||||
|
||||
function p20showAddMeshUserDialogEx(b, t) {
|
||||
@ -7519,6 +7556,7 @@
|
||||
if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
|
||||
if (Q('p20limitevents').checked == true) meshadmin += 8192;
|
||||
if (Q('p20chatnotify').checked == true) meshadmin += 16384;
|
||||
if (Q('p20uninstall').checked == true) meshadmin += 32768;
|
||||
}
|
||||
|
||||
if (t == null) {
|
||||
@ -7555,6 +7593,7 @@
|
||||
if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Limited Input");
|
||||
if ((meshrights & 8192) != 0) r.push("Self Events Only");
|
||||
if ((meshrights & 16384) != 0) r.push("Chat & Notify");
|
||||
if ((meshrights & 32768) != 0) r.push("Uninstall");
|
||||
}
|
||||
if (r.length == 0) { r.push("No Rights"); }
|
||||
var uname = xuserid.split('/')[2];
|
||||
|
1
views/download-min.handlebars
Normal file
1
views/download-min.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - Download</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>Download</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right>{{{rootCertLink}}} <a href=terms>Terms & Privacy</a></table></div></div></div>
|
1
views/error404-min.handlebars
Normal file
1
views/error404-min.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>MeshCentral - Terms of use</title><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0">{{{logoutControl}}}</div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>♦<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><div style=text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:20px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Back</a></table></div></div><script>"use strict";var uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),terms="{{{terms}}}";function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel"),Q("uiViewButton4").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,webPageStackMenu=!0,toggleFullScreen(0),toggleStackMenu(0),QC("column_l").add("room4submenu")}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function toggleFullScreen(e){1===e&&putstore("webPageFullScreen",webPageFullScreen=!webPageFullScreen);0==webPageFullScreen?(QC("body").remove("menu_stack"),QC("body").remove("fullscreen"),QC("body").remove("arg_hide")):QC("body").add("fullscreen"),QV("body",!0)}function toggleStackMenu(e){1==webPageFullScreen&&(1===e&&putstore("webPageStackMenu",webPageStackMenu=!webPageStackMenu),0==webPageStackMenu?QC("body").remove("menu_stack"):QC("body").add("menu_stack"))}function putstore(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,t)}catch(e){}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var o=localStorage.getItem(e);return null==o||null==o?t:o}catch(e){return t}}""!=terms&&QH("column_l",decodeURIComponent(terms)),QV("column_l",!0),userInterfaceSelectMenu()</script>
|
1
views/error404-mobile-min.handlebars
Normal file
1
views/error404-mobile-min.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><title>MeshCentral - Terms of use</title><style type=text/css>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p>{{{logoutControl}}}</div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=padding-left:10px;padding-right:10px><div style=text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:16px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}} <a href=/ >Back</a></table></div></div>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -267,6 +267,8 @@
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
@ -309,14 +311,14 @@
|
||||
center();
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if ('{{loginmode}}' == '4') {
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
@ -347,7 +349,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ('{{loginmode}}' == '5') {
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
@ -260,6 +260,8 @@
|
||||
<script>
|
||||
'use strict';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
var passRequirements = '{{{passRequirements}}}';
|
||||
@ -318,14 +320,14 @@
|
||||
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if ('{{loginmode}}' == '4') {
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
@ -358,7 +360,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ('{{loginmode}}' == '5') {
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
1
views/message-min.handlebars
Normal file
1
views/message-min.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - {{{title3}}}</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>{{{title3}}}</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=terms>Terms & Privacy</a></table></div></div></div>
|
File diff suppressed because one or more lines are too long
1
views/translations/agentinvite-min_fr.handlebars
Normal file
1
views/translations/agentinvite-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
8378
views/translations/default-min_fr.handlebars
Normal file
8378
views/translations/default-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
1
views/translations/default-mobile-min_fr.handlebars
Normal file
1
views/translations/default-mobile-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
@ -566,9 +566,9 @@
|
||||
</div>
|
||||
<div style="height:60px">
|
||||
<div style="float:right;border:1px solid #666;width:200px;height:60px;overflow-y:scroll;background-color:white">
|
||||
<label><input type="checkbox" id="d7showfocus">Show Focus Tool<br></label>
|
||||
<label><input type="checkbox" id="d7showcursor">Show Local Mouse Cursor<br< label="">>
|
||||
</br<></label></div>
|
||||
<label><input type="checkbox" id="d7showfocus">Show Focus Tool</label><br>
|
||||
<label><input type="checkbox" id="d7showcursor">Show Local Mouse Cursor</label><br>
|
||||
</div>
|
||||
<div>Autre</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3329,13 +3329,24 @@
|
||||
}
|
||||
|
||||
function groupActionFunction() {
|
||||
var mqttx = '';
|
||||
if (features & 0x00400000) { // Check if any of the selected devices have a MQTT connection active
|
||||
var addedOptions = '';
|
||||
|
||||
// Check if any of the selected devices have a MQTT connection active
|
||||
if (features & 0x00400000) {
|
||||
var nodeids = getCheckedDevices();
|
||||
for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { mqttx = '<option value=103>' + "Envoyer un Message MQTT" + '</option>'; } }
|
||||
for (var i in nodeids) { if ((getNodeFromId(nodeids[i]).conn & 16) != 0) { addedOptions += '<option value=103>' + "Envoyer un Message MQTT" + '</option>'; break; } }
|
||||
}
|
||||
|
||||
// Display the "Uninstall Agent" option if allowed and we selected connected devices.
|
||||
for (var i in nodeids) {
|
||||
var node = getNodeFromId(nodeids[i]);
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
}
|
||||
|
||||
var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
|
||||
x += addHtmlValue("Opération", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Réinitialiser les appareils" + '</option><option value=2>' + "Éteindre les appareils" + '</option><option value=102>' + "Move to device group" + '</option>' + mqttx + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
x += addHtmlValue("Opération", '<select id=d2groupop><option value=100>' + "Wake-up devices" + '</option><option value=4>' + "Sleep devices" + '</option><option value=3>' + "Réinitialiser les appareils" + '</option><option value=2>' + "Éteindre les appareils" + '</option><option value=102>' + "Move to device group" + '</option>' + addedOptions + '<option value=101>' + "Delete devices" + '</option></select>');
|
||||
setDialogMode(2, "Action de groupe", 3, groupActionFunctionEx, x);
|
||||
}
|
||||
|
||||
@ -3363,6 +3374,9 @@
|
||||
} else if (op == 103) {
|
||||
// Send MQTT Message
|
||||
p10showSendMqttMsgDialog(getCheckedDevices());
|
||||
} else if (op == 104) {
|
||||
// Uninstall agent
|
||||
p10showSendUninstallAgentDialog(getCheckedDevices());
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: parseInt(op) });
|
||||
@ -4503,6 +4517,7 @@
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((meshrights & 8) != 0) { y += '<option value=4>' + "Dormir" + '</option><option value=3>' + "Réinitialiser" + '</option><option value=2>' + "Éteindre" + '</option>'; } // Remote control permission
|
||||
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Envoyer un Message MQTT" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
y += '</select>';
|
||||
x += addHtmlValue("Opération", y);
|
||||
setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
|
||||
@ -4516,6 +4531,9 @@
|
||||
} else if (op == 103) {
|
||||
// Send MQTT Message
|
||||
p10showSendMqttMsgDialog([currentNode._id]);
|
||||
} else if (op == 104) {
|
||||
// Uninstall agent
|
||||
p10showSendUninstallAgentDialog([currentNode._id]);
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: parseInt(op) });
|
||||
@ -4662,6 +4680,21 @@
|
||||
meshserver.send({ action: 'sendmqttmsg', nodeids: nodeids, topic: Q('dp2topic').value, msg: Q('dp2msg').value });
|
||||
}
|
||||
|
||||
function p10showSendUninstallAgentDialog(nodeids) {
|
||||
if (xxdialogMode) return false;
|
||||
var x = '';
|
||||
if (nodeids.length > 1) { x = format("Are you sure you want to uninstall the selected {0} agents?", nodeids.length); } else { x = "Are you sure you want to uninstall selected agent?"; }
|
||||
x += '<br /><br />';
|
||||
if (nodeids.length > 1) { x += "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connect for this command to work."; } else { x += "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work."; }
|
||||
x += '<br /><br /><label style=color:red><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
|
||||
setDialogMode(2, "Uninstall agent", 3, p10showSendUninstallAgentDialogEx, x, nodeids);
|
||||
p10validateSendUninstallAgentDialog();
|
||||
return false;
|
||||
}
|
||||
|
||||
function p10validateSendUninstallAgentDialog() { QE('idx_dlgOkButton', Q('p10check').checked); }
|
||||
function p10showSendUninstallAgentDialogEx(b, nodeids) { meshserver.send({ action: 'uninstallagent', nodeids: nodeids }); }
|
||||
|
||||
function p10showChangeGroupDialog(nodeids) {
|
||||
if (xxdialogMode) return false;
|
||||
var targetMeshId = null;
|
||||
@ -7404,6 +7437,7 @@
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Edit Device Notes" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Show Only Own Events" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Notify" + '</label><br>';
|
||||
x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20uninstall>' + "Uninstall Agent" + '</label><br>';
|
||||
x += '</div>';
|
||||
if (userid == null) {
|
||||
setDialogMode(2, "Add Users to Device Group", 3, p20showAddMeshUserDialogEx, x);
|
||||
@ -7431,7 +7465,7 @@
|
||||
if (meshrights & 128) { Q('p20editnotes').checked = true; }
|
||||
if (meshrights & 8192) { Q('p20limitevents').checked = true; }
|
||||
if (meshrights & 16384) { Q('p20chatnotify').checked = true; }
|
||||
|
||||
if (meshrights & 32768) { Q('p20uninstall').checked = true; }
|
||||
}
|
||||
}
|
||||
p20validateAddMeshUserDialog();
|
||||
@ -7479,21 +7513,24 @@
|
||||
}
|
||||
QE('idx_dlgOkButton', ok);
|
||||
|
||||
var nc = !Q('p20fulladmin').checked;
|
||||
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
||||
QE('p20editmesh', (!Q('p20fulladmin').checked) && (meshrights == 0xFFFFFFFF));
|
||||
QE('p20manageusers', !Q('p20fulladmin').checked);
|
||||
QE('p20managecomputers', !Q('p20fulladmin').checked);
|
||||
QE('p20remotecontrol', !Q('p20fulladmin').checked);
|
||||
QE('p20meshagentconsole', !Q('p20fulladmin').checked);
|
||||
QE('p20meshserverfiles', !Q('p20fulladmin').checked);
|
||||
QE('p20wakedevices', !Q('p20fulladmin').checked);
|
||||
QE('p20editnotes', !Q('p20fulladmin').checked);
|
||||
QE('p20limitevents', !Q('p20fulladmin').checked);
|
||||
QE('p20remoteview', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20remotelimitedinput', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
|
||||
QE('p20noterminal', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20nofiles', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20noamt', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked);
|
||||
QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF));
|
||||
QE('p20manageusers', nc);
|
||||
QE('p20managecomputers', nc);
|
||||
QE('p20remotecontrol', nc);
|
||||
QE('p20meshagentconsole', nc);
|
||||
QE('p20meshserverfiles', nc);
|
||||
QE('p20wakedevices', nc);
|
||||
QE('p20editnotes', nc);
|
||||
QE('p20limitevents', nc);
|
||||
QE('p20remoteview', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20remotelimitedinput', nc && Q('p20remotecontrol').checked && !Q('p20remoteview').checked);
|
||||
QE('p20noterminal', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20nofiles', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20noamt', nc && Q('p20remotecontrol').checked);
|
||||
QE('p20chatnotify', nc);
|
||||
QE('p20uninstall', nc);
|
||||
}
|
||||
|
||||
function p20showAddMeshUserDialogEx(b, t) {
|
||||
@ -7517,6 +7554,7 @@
|
||||
if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
|
||||
if (Q('p20limitevents').checked == true) meshadmin += 8192;
|
||||
if (Q('p20chatnotify').checked == true) meshadmin += 16384;
|
||||
if (Q('p20uninstall').checked == true) meshadmin += 32768;
|
||||
}
|
||||
|
||||
if (t == null) {
|
||||
@ -7553,6 +7591,7 @@
|
||||
if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Limited Input");
|
||||
if ((meshrights & 8192) != 0) r.push("Self Events Only");
|
||||
if ((meshrights & 16384) != 0) r.push("Chat & Notify");
|
||||
if ((meshrights & 32768) != 0) r.push("Uninstall");
|
||||
}
|
||||
if (r.length == 0) { r.push("No Rights"); }
|
||||
var uname = xuserid.split('/')[2];
|
||||
|
1
views/translations/download-min_fr.handlebars
Normal file
1
views/translations/download-min_fr.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - Download</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>Download</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right>{{{rootCertLink}}} <a href=terms>Terms & Privacy</a></table></div></div></div>
|
1
views/translations/error404-min_fr.handlebars
Normal file
1
views/translations/error404-min_fr.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=styles/style.css media=screen rel=stylesheet title=CSS><script src=scripts/common-0.0.1.js></script><title>MeshCentral - Terms of use</title><body id=body onload='"undefined"!=typeof startup&&startup()'style=display:none;overflow:hidden><div id=container><div id=masthead class=noselect style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p id=logoutControl style="color:#fff;font-size:11px;margin:10px 10px 0">{{{logoutControl}}}</div><div id=page_leftbar><div style=height:16px></div></div><div id=topbar class="noselect style3"style=height:24px;position:relative><div id=uiMenuButton title="User interface selection"onclick=showUserInterfaceSelectMenu()>♦<div id=uiMenu style=display:none><div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class=uiSelector1></div></div><div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class=uiSelector2></div></div><div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class=uiSelector3></div></div><div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Basculer mode nuit"><div class=uiSelector4></div></div></div></div></div><div id=column_l style="max-height:calc(100vh - 135px);overflow-y:auto"><div style=text-align:center;padding-top:30px;font-size:200px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:20px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:20px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=/ >Retour</a></table></div></div><script>"use strict";var uiMode=parseInt(getstore("uiMode",1)),webPageStackMenu=!1,webPageFullScreen=!0,nightMode="1"==getstore("_nightMode","0"),terms="{{{terms}}}";function showUserInterfaceSelectMenu(){Q("uiViewButton1").classList.remove("uiSelectorSel"),Q("uiViewButton2").classList.remove("uiSelectorSel"),Q("uiViewButton3").classList.remove("uiSelectorSel"),Q("uiViewButton4").classList.remove("uiSelectorSel");try{Q("uiViewButton"+uiMode).classList.add("uiSelectorSel")}catch(e){}QV("uiMenu","none"==QS("uiMenu").display),nightMode&&Q("uiViewButton4").classList.add("uiSelectorSel")}function userInterfaceSelectMenu(e){e&&putstore("uiMode",uiMode=e),webPageFullScreen=uiMode<3,webPageStackMenu=!0,toggleFullScreen(0),toggleStackMenu(0),QC("column_l").add("room4submenu")}function toggleNightMode(){(nightMode=!nightMode)?QC("body").add("night"):QC("body").remove("night"),putstore("_nightMode",nightMode?"1":"0")}function toggleFullScreen(e){1===e&&putstore("webPageFullScreen",webPageFullScreen=!webPageFullScreen);0==webPageFullScreen?(QC("body").remove("menu_stack"),QC("body").remove("fullscreen"),QC("body").remove("arg_hide")):QC("body").add("fullscreen"),QV("body",!0)}function toggleStackMenu(e){1==webPageFullScreen&&(1===e&&putstore("webPageStackMenu",webPageStackMenu=!webPageStackMenu),0==webPageStackMenu?QC("body").remove("menu_stack"):QC("body").add("menu_stack"))}function putstore(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(e,t)}catch(e){}}function getstore(e,t){try{if("undefined"==typeof localStorage)return t;var o=localStorage.getItem(e);return null==o||null==o?t:o}catch(e){return t}}""!=terms&&QH("column_l",decodeURIComponent(terms)),QV("column_l",!0),userInterfaceSelectMenu()</script>
|
1
views/translations/error404-mobile-min_fr.handlebars
Normal file
1
views/translations/error404-mobile-min_fr.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><title>MeshCentral - Terms of use</title><style type=text/css>a{color:#036;text-decoration:underline}#footer a{color:#fff;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}</style><body onload='"undefined"!=typeof startup&&startup()'style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:#000;font-size:13px;font-family:\'Trebuchet MS\',Arial,Helvetica,sans-serif"><div id=container><div id=masthead style="background:url(logo.png) 0 0;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px><strong><font style=font-size:36px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px><strong><font style=font-size:12px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div><p>{{{logoutControl}}}</div><div id=page_content style=overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%><div id=column_l style=padding-left:10px;padding-right:10px><div style=text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb><b>404</b></div><div style=text-align:center;font-size:16px;font-family:Arial;color:#999>This page does not exist</div><div style=text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999><a href=/ style=text-decoration:none><b>Go to main site</b></a></div></div></div><div id=footer style=height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0><table cellpadding=0 cellspacing=6 style=width:100%><tr><td style=text-align:left;color:#fff>{{{footer}}}<td style=text-align:right>{{{rootCertLink}}} <a href=/ >Retour</a></table></div></div>
|
55
views/translations/error404-mobile_fr.handlebars
Normal file
55
views/translations/error404-mobile_fr.handlebars
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html><html><head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<title>MeshCentral - Terms of use</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
color: #036;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#footer a:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;max-width:100%;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
|
||||
<div id="container">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:4px">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:7px">
|
||||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
<p>{{{logoutControl}}}</p>
|
||||
</div>
|
||||
<div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
|
||||
<div id="column_l" style="padding-left:10px;padding-right:10px">
|
||||
<div style="text-align:center;padding-top:30px;font-size:100px;font-family:Arial;color:#bbb"><b>404</b></div>
|
||||
<div style="text-align:center;font-size:16px;font-family:Arial;color:#999">This page does not exist</div>
|
||||
<div style="text-align:center;padding-top:16px;font-size:20px;font-family:Arial;color:#999"><a href="/" style="text-decoration:none"><b>Go to main site</b></a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
|
||||
<table cellpadding="0" cellspacing="6" style="width:100%">
|
||||
<tbody><tr>
|
||||
<td style="text-align:left;color:white">{{{footer}}}</td>
|
||||
<td style="text-align:right">{{{rootCertLink}}} <a href="/">Retour</a></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body></html>
|
1
views/translations/login-min_fr.handlebars
Normal file
1
views/translations/login-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
1
views/translations/login-mobile-min_fr.handlebars
Normal file
1
views/translations/login-mobile-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
@ -265,6 +265,8 @@
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
@ -307,14 +309,14 @@
|
||||
center();
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if ('{{loginmode}}' == '4') {
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
@ -345,7 +347,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ('{{loginmode}}' == '5') {
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
@ -258,6 +258,8 @@
|
||||
<script>
|
||||
'use strict';
|
||||
var passhint = '{{{passhint}}}';
|
||||
var loginMode = '{{{loginmode}}}';
|
||||
var newAccount = '{{{newAccount}}}';
|
||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||
var emailCheck = ('{{{emailcheck}}}' == 'true');
|
||||
var passRequirements = '{{{passRequirements}}}';
|
||||
@ -316,14 +318,14 @@
|
||||
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
|
||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||
QV('newAccountPass', (newAccountPass == 1));
|
||||
QV('resetAccountDiv', (emailCheck == true));
|
||||
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
|
||||
|
||||
if ('{{loginmode}}' == '4') {
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
@ -356,7 +358,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ('{{loginmode}}' == '5') {
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
1
views/translations/message-min_fr.handlebars
Normal file
1
views/translations/message-min_fr.handlebars
Normal file
@ -0,0 +1 @@
|
||||
<!doctypehtml><html dir=ltr xmlns=http://www.w3.org/1999/xhtml><meta http-equiv=X-UA-Compatible content="IE=edge"><meta content="text/html;charset=utf-8"http-equiv=Content-Type><meta name=viewport content="user-scalable=1,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name=apple-mobile-web-app-capable content=yes><meta name=format-detection content="telephone=no"><link type=text/css href=/styles/style.css media=screen rel=stylesheet title=CSS><title>MeshCentral - {{{title3}}}</title><div id=container style=max-height:100vh><div id=mastheadx></div><div id=masthead style="background:url(logo.png) 0 0;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden"><div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px><strong><font style=font-size:46px;font-family:Arial,Helvetica,sans-serif>{{{title}}}</font></strong></div><div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px><strong><font style=font-size:14px;font-family:Arial,Helvetica,sans-serif>{{{title2}}}</font></strong></div></div><div id=page_content style=max-height:calc(100vh-138px)><div id=column_l><h1>{{{title3}}}</h1><p style=margin-left:20px>{{{message}}}</p><br></div><div id=footer><table cellpadding=0 cellspacing=10 style=width:100%><tr><td style=text-align:left><td style=text-align:right><a href=terms>Terms & Privacy</a></table></div></div></div>
|
1
views/translations/messenger-min_fr.handlebars
Normal file
1
views/translations/messenger-min_fr.handlebars
Normal file
File diff suppressed because one or more lines are too long
@ -2854,7 +2854,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (argentInfo == null) { res.sendStatus(404); return; }
|
||||
if ((req.query.meshid == null) || (argentInfo.platform != 'win32')) {
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' });
|
||||
res.sendFile(argentInfo.path);
|
||||
if (argentInfo.data == null) { res.sendFile(argentInfo.path); } else { res.end(argentInfo.data); }
|
||||
} else {
|
||||
// We are going to embed the .msh file into the Windows executable (signed or not).
|
||||
// First, fetch the mesh object to build the .msh file
|
||||
@ -2955,6 +2955,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
localPort: 1234,
|
||||
remoteName: node.name,
|
||||
remoteNodeId: node._id,
|
||||
remoteTarget: '',
|
||||
remotePort: 3389,
|
||||
username: '',
|
||||
password: '',
|
||||
|
Loading…
Reference in New Issue
Block a user