Fixed agent 'msg' dispatching.

This commit is contained in:
Ylian Saint-Hilaire 2020-01-07 13:56:26 -08:00
parent 9453ee9ba3
commit bcf5cfbb5e
3 changed files with 202 additions and 234 deletions

View File

@ -1,35 +1,30 @@
var http = require('http'); var http = require('http');
var childProcess = require('child_process'); var childProcess = require('child_process');
var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript var meshCoreObj = { action: 'coreinfo', value: "MeshCore Recovery", caps: 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
var nextTunnelIndex = 1; var nextTunnelIndex = 1;
var tunnels = {}; var tunnels = {};
var fs = require('fs'); var fs = require('fs');
//attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); }); //attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
function sendConsoleText(msg) function sendConsoleText(msg) {
{ require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg });
require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
} }
// Return p number of spaces // Return p number of spaces
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; } function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
setInterval(function () { sendConsoleText('Timer!'); }, 2000);
var path = var path =
{ {
join: function () join: function () {
{
var x = []; var x = [];
for (var i in arguments) for (var i in arguments) {
{
var w = arguments[i]; var w = arguments[i];
if (w != null) if (w != null) {
{
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
if (i != 0) if (i != 0) { while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } }
{
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
}
x.push(w); x.push(w);
} }
} }
@ -53,16 +48,14 @@ function objToString(x, p, pad, ret) {
} }
// Split a string taking into account the quoats. Used for command line parsing // Split a string taking into account the quoats. Used for command line parsing
function splitArgs(str) function splitArgs(str) {
{
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi; var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null); do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
return myArray; return myArray;
} }
// Parse arguments string array into an object // Parse arguments string array into an object
function parseArgs(argv) function parseArgs(argv) {
{
var results = { '_': [] }, current = null; var results = { '_': [] }, current = null;
for (var i = 1, len = argv.length; i < len; i++) { for (var i = 1, len = argv.length; i < len; i++) {
var x = argv[i]; var x = argv[i];
@ -77,8 +70,7 @@ function parseArgs(argv)
return results; return results;
} }
// Get server target url with a custom path // Get server target url with a custom path
function getServerTargetUrl(path) function getServerTargetUrl(path) {
{
var x = require('MeshAgent').ServerUrl; var x = require('MeshAgent').ServerUrl;
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl); //sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
if (x == null) { return null; } if (x == null) { return null; }
@ -89,16 +81,13 @@ function getServerTargetUrl(path)
} }
// Get server url. If the url starts with "*/..." change it, it not use the url as is. // Get server url. If the url starts with "*/..." change it, it not use the url as is.
function getServerTargetUrlEx(url) function getServerTargetUrlEx(url) {
{
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); } if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
return url; return url;
} }
require('MeshAgent').on('Connected', function () require('MeshAgent').on('Connected', function () {
{ require('os').name().then(function (v) {
require('os').name().then(function (v)
{
sendConsoleText("Mesh Agent Receovery Console, OS: " + v); sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
require('MeshAgent').SendCommand(meshCoreObj); require('MeshAgent').SendCommand(meshCoreObj);
}); });
@ -127,209 +116,192 @@ function onTunnelUpgrade(response, s, head) {
} }
} }
require('MeshAgent').AddCommandHandler(function (data) require('MeshAgent').AddCommandHandler(function (data) {
{ if (typeof data == 'object') {
if (typeof data == 'object')
{
// If this is a console command, parse it and call the console handler // If this is a console command, parse it and call the console handler
switch (data.action) switch (data.action) {
{
case 'msg': case 'msg':
{ {
switch (data.type) switch (data.type) {
{ case 'console': { // Process a console command
case 'console': { // Process a console command if (data.value && data.sessionid) {
if (data.value && data.sessionid) var args = splitArgs(data.value);
{ processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
var args = splitArgs(data.value); }
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid); break;
} }
break;
}
case 'tunnel': case 'tunnel':
{ {
if (data.value != null) { // Process a new tunnel connection request if (data.value != null) { // Process a new tunnel connection request
// Create a new tunnel object // Create a new tunnel object
var xurl = getServerTargetUrlEx(data.value); var xurl = getServerTargetUrlEx(data.value);
if (xurl != null) { if (xurl != null) {
var woptions = http.parseUri(xurl); var woptions = http.parseUri(xurl);
woptions.rejectUnauthorized = 0; woptions.rejectUnauthorized = 0;
//sendConsoleText(JSON.stringify(woptions)); //sendConsoleText(JSON.stringify(woptions));
var tunnel = http.request(woptions); var tunnel = http.request(woptions);
tunnel.on('upgrade', function (response, s, head) tunnel.on('upgrade', function (response, s, head) {
{ this.s = s;
this.s = s; s.httprequest = this;
s.httprequest = this; s.tunnel = this;
s.tunnel = this; s.on('end', function () {
s.on('end', function () if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
{
if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
// If there is a upload or download active on this connection, close the file // If there is a upload or download active on this connection, close the file
if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; } if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; } if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
//sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid); //sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
delete tunnels[this.httprequest.index]; delete tunnels[this.httprequest.index];
// Clean up WebSocket // Clean up WebSocket
this.removeAllListeners('data'); this.removeAllListeners('data');
}); });
s.on('data', function (data) s.on('data', function (data) {
{ // If this is upload data, save it to file
// If this is upload data, save it to file if (this.httprequest.uploadFile) {
if (this.httprequest.uploadFile) try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
{ this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out. return;
this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
return;
}
if (this.httprequest.state == 0) {
// Check if this is a relay connection
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
} else {
// Handle tunnel data
if (this.httprequest.protocol == 0)
{
// Take a look at the protocol
this.httprequest.protocol = parseInt(data);
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
if (this.httprequest.protocol == 1)
{
// Remote terminal using native pipes
if (process.platform == "win32")
{
this.httprequest._term = require('win-terminal').Start(80, 25);
this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
}
else
{
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
this.httprequest.process.tunnel = this;
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
this.prependListener('end', function () { this.httprequest.process.kill(); });
}
this.on('end', function () {
if (process.platform == "win32")
{
// Unpipe the web socket
this.unpipe(this.httprequest._term);
this.httprequest._term.unpipe(this);
// Clean up
this.httprequest._term.end();
this.httprequest._term = null;
}
});
} }
}
else if (this.httprequest.protocol == 5)
{
// Process files commands
var cmd = null;
try { cmd = JSON.parse(data); } catch (e) { };
if (cmd == null) { return; }
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
if (cmd.action == undefined) { return; }
console.log('action: ', cmd.action);
//sendConsoleText('CMD: ' + JSON.stringify(cmd)); if (this.httprequest.state == 0) {
// Check if this is a relay connection
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
} else {
// Handle tunnel data
if (this.httprequest.protocol == 0) {
// Take a look at the protocol
this.httprequest.protocol = parseInt(data);
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
if (this.httprequest.protocol == 1) {
// Remote terminal using native pipes
if (process.platform == "win32") {
this.httprequest._term = require('win-terminal').Start(80, 25);
this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
}
else {
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
this.httprequest.process.tunnel = this;
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
this.prependListener('end', function () { this.httprequest.process.kill(); });
}
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows this.on('end', function () {
//console.log(objToString(cmd, 0, ' ')); if (process.platform == "win32") {
switch (cmd.action) // Unpipe the web socket
{ this.unpipe(this.httprequest._term);
case 'ls': this.httprequest._term.unpipe(this);
// Send the folder content to the browser
var response = getDirectoryInfo(cmd.path); // Clean up
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; } this.httprequest._term.end();
this.write(new Buffer(JSON.stringify(response))); this.httprequest._term = null;
break; }
case 'mkdir': { });
// Create a new empty folder
fs.mkdirSync(cmd.path);
break;
}
case 'rm': {
// Delete, possibly recursive delete
for (var i in cmd.delfiles)
{
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
} }
break;
} }
case 'rename': { else if (this.httprequest.protocol == 5) {
// Rename a file or folder // Process files commands
var oldfullpath = path.join(cmd.path, cmd.oldname); var cmd = null;
var newfullpath = path.join(cmd.path, cmd.newname); try { cmd = JSON.parse(data); } catch (e) { };
try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); } if (cmd == null) { return; }
break; if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
} if (cmd.action == undefined) { return; }
case 'upload': { console.log('action: ', cmd.action);
// Upload a file, browser to agent
if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; } //sendConsoleText('CMD: ' + JSON.stringify(cmd));
if (cmd.path == undefined) break;
var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path; if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; } //console.log(objToString(cmd, 0, ' '));
this.httprequest.uploadFileid = cmd.reqid; switch (cmd.action) {
if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); } case 'ls':
break; // Send the folder content to the browser
} var response = getDirectoryInfo(cmd.path);
case 'copy': { if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
// Copy a bunch of files from scpath to dspath this.write(new Buffer(JSON.stringify(response)));
for (var i in cmd.names) { break;
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]); case 'mkdir': {
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } } // Create a new empty folder
fs.mkdirSync(cmd.path);
break;
}
case 'rm': {
// Delete, possibly recursive delete
for (var i in cmd.delfiles) {
try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
}
break;
}
case 'rename': {
// Rename a file or folder
var oldfullpath = path.join(cmd.path, cmd.oldname);
var newfullpath = path.join(cmd.path, cmd.newname);
try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
break;
}
case 'upload': {
// Upload a file, browser to agent
if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
if (cmd.path == undefined) break;
var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
this.httprequest.uploadFileid = cmd.reqid;
if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
break;
}
case 'copy': {
// Copy a bunch of files from scpath to dspath
for (var i in cmd.names) {
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
}
break;
}
case 'move': {
// Move a bunch of files from scpath to dspath
for (var i in cmd.names) {
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
}
break;
}
} }
break;
}
case 'move': {
// Move a bunch of files from scpath to dspath
for (var i in cmd.names) {
var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
}
break;
} }
} }
} });
} });
}); tunnel.onerror = function (e) { sendConsoleText("ERROR: " + JSON.stringify(e)); }
}); tunnel.sessionid = data.sessionid;
tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); } tunnel.rights = data.rights;
tunnel.sessionid = data.sessionid; tunnel.state = 0;
tunnel.rights = data.rights; tunnel.url = xurl;
tunnel.state = 0; tunnel.protocol = 0;
tunnel.url = xurl; tunnel.tcpaddr = data.tcpaddr;
tunnel.protocol = 0; tunnel.tcpport = data.tcpport;
tunnel.tcpaddr = data.tcpaddr; tunnel.end();
tunnel.tcpport = data.tcpport; // Put the tunnel in the tunnels list
tunnel.end(); var index = nextTunnelIndex++;
// Put the tunnel in the tunnels list tunnel.index = index;
var index = nextTunnelIndex++; tunnels[index] = tunnel;
tunnel.index = index;
tunnels[index] = tunnel;
//sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid); //sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
}
}
break;
} }
}
break;
}
default: default:
// Unknown action, ignore it. // Unknown action, ignore it.
break; break;
}
break;
} }
break;
}
default: default:
// Unknown action, ignore it. // Unknown action, ignore it.
break; break;
@ -337,20 +309,16 @@ require('MeshAgent').AddCommandHandler(function (data)
} }
}); });
function processConsoleCommand(cmd, args, rights, sessionid) function processConsoleCommand(cmd, args, rights, sessionid) {
{ try {
try
{
var response = null; var response = null;
switch (cmd) switch (cmd) {
{
case 'help': case 'help':
response = 'Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.'; response = "Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.";
break; break;
case 'osinfo': { // Return the operating system information case 'osinfo': { // Return the operating system information
var i = 1; var i = 1;
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; } if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = "Calling " + i + " times."; }
for (var j = 0; j < i; j++) { for (var j = 0; j < i; j++) {
var pr = require('os').name(); var pr = require('os').name();
pr.sessionid = sessionid; pr.sessionid = sessionid;
@ -363,34 +331,34 @@ function processConsoleCommand(cmd, args, rights, sessionid)
break; break;
} }
case 'dbget': { // Return the data store value for a given key case 'dbget': { // Return the data store value for a given key
if (db == null) { response = 'Database not accessible.'; break; } if (db == null) { response = "Database not accessible."; break; }
if (args['_'].length != 1) { if (args['_'].length != 1) {
response = 'Proper usage: dbget (key)'; // Display the value for a given database key response = "Proper usage: dbget (key)"; // Display the value for a given database key
} else { } else {
response = db.Get(args['_'][0]); response = db.Get(args['_'][0]);
} }
break; break;
} }
case 'dbset': { // Set a data store key and value pair case 'dbset': { // Set a data store key and value pair
if (db == null) { response = 'Database not accessible.'; break; } if (db == null) { response = "Database not accessible."; break; }
if (args['_'].length != 2) { if (args['_'].length != 2) {
response = 'Proper usage: dbset (key) (value)'; // Set a database key response = "Proper usage: dbset (key) (value)"; // Set a database key
} else { } else {
var r = db.Put(args['_'][0], args['_'][1]); var r = db.Put(args['_'][0], args['_'][1]);
response = 'Key set: ' + r; response = "Key set: " + r;
} }
break; break;
} }
case 'dbcompact': { // Compact the data store case 'dbcompact': { // Compact the data store
if (db == null) { response = 'Database not accessible.'; break; } if (db == null) { response = "Database not accessible."; break; }
var r = db.Compact(); var r = db.Compact();
response = 'Database compacted: ' + r; response = "Database compacted: " + r;
break; break;
} }
case 'tunnels': { // Show the list of current tunnels case 'tunnels': { // Show the list of current tunnels
response = ''; response = '';
for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; } for (var i in tunnels) { response += "Tunnel #" + i + ", " + tunnels[i].url + '\r\n'; }
if (response == '') { response = 'No websocket sessions.'; } if (response == '') { response = "No websocket sessions."; }
break; break;
} }
case 'netinfo': { // Show network interface information case 'netinfo': { // Show network interface information
@ -404,13 +372,12 @@ function processConsoleCommand(cmd, args, rights, sessionid)
break; break;
} }
} }
} catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); } } catch (e) { response = "Command returned an exception error: " + e; console.log(e); }
if (response != null) { sendConsoleText(response, sessionid); } if (response != null) { sendConsoleText(response, sessionid); }
} }
// Get a formated response for a given directory path // Get a formated response for a given directory path
function getDirectoryInfo(reqpath) function getDirectoryInfo(reqpath) {
{
var response = { path: reqpath, dir: [] }; var response = { path: reqpath, dir: [] };
if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) { if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
// List all the drives in the root, or the root itself // List all the drives in the root, or the root itself

View File

@ -645,7 +645,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
} }
else if ((command.fileop == 'rename') && (common.IsFilenameValid(command.oldname) == true) && (common.IsFilenameValid(command.newname) == true)) { else if ((command.fileop == 'rename') && (common.IsFilenameValid(command.oldname) == true) && (common.IsFilenameValid(command.newname) == true)) {
// Rename // Rename
try { fs.renameSync(path + "/" + command.oldname, path + "/" + command.newname); } catch (e) { } try { fs.renameSync(path + '/' + command.oldname, path + '/' + command.newname); } catch (e) { }
} }
else if ((command.fileop == 'copy') || (command.fileop == 'move')) { else if ((command.fileop == 'copy') || (command.fileop == 'move')) {
if (common.validateArray(command.names, 1) == false) return; if (common.validateArray(command.names, 1) == false) return;

View File

@ -4262,16 +4262,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// TODO: Add multi-server support // TODO: Add multi-server support
} }
} }
} else { // Route this command to the mesh } else { // Route this command to all users with MESHRIGHT_AGENTCONSOLE rights to this device group
command.nodeid = nodeid; command.nodeid = nodeid;
var cmdstr = JSON.stringify(command); var cmdstr = JSON.stringify(command);
if (obj.GetMeshRights(userid, meshid) == 0) return; // TODO: Check if this is ok
// Find all connected users for this mesh and send the message // Find all connected user sessions with access to this device
for (var userid in obj.wssessions) { for (var userid in obj.wssessions) {
var xsessions = obj.wssessions[userid]; var xsessions = obj.wssessions[userid];
// Send the message to all users on this server if (obj.GetMeshRights(userid, meshid) != 0) {
for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } } // Send the message to all sessions for this user on this server
for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } }
}
} }
// Send the message to all users of other servers // Send the message to all users of other servers