Fixed agent 'msg' dispatching.

Ylian Saint-Hilaire committed Jan 7, 2020 at 13:56 UTC bcf5cfbb5e11804b898d968b266316b4cbab6dfe
3 files changed +201 -233
agents/recoverycore.js
+194 -227
@@ -1,35 +1,30 @@
1
2 var http = require('http');
3 var childProcess = require('child_process');
4 -var meshCoreObj = { "action": "coreinfo", "value": "MeshCore Recovery", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
4 +var meshCoreObj = { action: 'coreinfo', value: "MeshCore Recovery", caps: 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
5 var nextTunnelIndex = 1;
6 var tunnels = {};
7 var fs = require('fs');
8
9 //attachDebugger({ webport: 9994, wait: 1 }).then(function (p) { console.log('Debug on port: ' + p); });
10
11 -function sendConsoleText(msg)
12 -{
13 - require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": msg });
11 +function sendConsoleText(msg) {
12 + require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: msg });
13 }
14 // Return p number of spaces
15 function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
16
17 +setInterval(function () { sendConsoleText('Timer!'); }, 2000);
18 +
19 var path =
20 {
20 - join: function ()
21 - {
21 + join: function () {
22 var x = [];
23 - for (var i in arguments)
24 - {
23 + for (var i in arguments) {
24 var w = arguments[i];
26 - if (w != null)
27 - {
25 + if (w != null) {
26 while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
29 - if (i != 0)
30 - {
31 - while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
32 - }
27 + if (i != 0) { while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } }
28 x.push(w);
29 }
30 }
@@ -53,16 +48,14 @@ function objToString(x, p, pad, ret) {
48 }
49
50 // Split a string taking into account the quoats. Used for command line parsing
56 -function splitArgs(str)
57 -{
51 +function splitArgs(str) {
52 var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
53 do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
54 return myArray;
55 }
56
57 // Parse arguments string array into an object
64 -function parseArgs(argv)
65 -{
58 +function parseArgs(argv) {
59 var results = { '_': [] }, current = null;
60 for (var i = 1, len = argv.length; i < len; i++) {
61 var x = argv[i];
@@ -77,8 +70,7 @@ function parseArgs(argv)
70 return results;
71 }
72 // Get server target url with a custom path
80 -function getServerTargetUrl(path)
81 -{
73 +function getServerTargetUrl(path) {
74 var x = require('MeshAgent').ServerUrl;
75 //sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
76 if (x == null) { return null; }
@@ -89,16 +81,13 @@ function getServerTargetUrl(path)
81 }
82
83 // Get server url. If the url starts with "*/..." change it, it not use the url as is.
92 -function getServerTargetUrlEx(url)
93 -{
84 +function getServerTargetUrlEx(url) {
85 if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
86 return url;
87 }
88
98 -require('MeshAgent').on('Connected', function ()
99 -{
100 - require('os').name().then(function (v)
101 - {
89 +require('MeshAgent').on('Connected', function () {
90 + require('os').name().then(function (v) {
91 sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
92 require('MeshAgent').SendCommand(meshCoreObj);
93 });
@@ -127,209 +116,192 @@ function onTunnelUpgrade(response, s, head) {
116 }
117 }
118
130 -require('MeshAgent').AddCommandHandler(function (data)
131 -{
132 - if (typeof data == 'object')
133 - {
119 +require('MeshAgent').AddCommandHandler(function (data) {
120 + if (typeof data == 'object') {
121 // If this is a console command, parse it and call the console handler
135 - switch (data.action)
136 - {
122 + switch (data.action) {
123 case 'msg':
124 {
139 - switch (data.type)
140 - {
141 - case 'console': { // Process a console command
142 - if (data.value && data.sessionid)
143 - {
144 - var args = splitArgs(data.value);
145 - processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
125 + switch (data.type) {
126 + case 'console': { // Process a console command
127 + if (data.value && data.sessionid) {
128 + var args = splitArgs(data.value);
129 + processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
130 + }
131 + break;
132 }
147 - break;
148 - }
133 case 'tunnel':
134 {
151 - if (data.value != null) { // Process a new tunnel connection request
152 - // Create a new tunnel object
153 - var xurl = getServerTargetUrlEx(data.value);
154 - if (xurl != null) {
155 - var woptions = http.parseUri(xurl);
156 - woptions.rejectUnauthorized = 0;
157 - //sendConsoleText(JSON.stringify(woptions));
158 - var tunnel = http.request(woptions);
159 - tunnel.on('upgrade', function (response, s, head)
160 - {
161 - this.s = s;
162 - s.httprequest = this;
163 - s.tunnel = this;
164 - s.on('end', function ()
165 - {
166 - if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
135 + if (data.value != null) { // Process a new tunnel connection request
136 + // Create a new tunnel object
137 + var xurl = getServerTargetUrlEx(data.value);
138 + if (xurl != null) {
139 + var woptions = http.parseUri(xurl);
140 + woptions.rejectUnauthorized = 0;
141 + //sendConsoleText(JSON.stringify(woptions));
142 + var tunnel = http.request(woptions);
143 + tunnel.on('upgrade', function (response, s, head) {
144 + this.s = s;
145 + s.httprequest = this;
146 + s.tunnel = this;
147 + s.on('end', function () {
148 + if (tunnels[this.httprequest.index] == null) return; // Stop duplicate calls.
149
168 - // If there is a upload or download active on this connection, close the file
169 - if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
170 - if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
150 + // If there is a upload or download active on this connection, close the file
151 + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
152 + if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
153
154
173 - //sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
174 - delete tunnels[this.httprequest.index];
155 + //sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
156 + delete tunnels[this.httprequest.index];
157
176 - // Clean up WebSocket
177 - this.removeAllListeners('data');
178 - });
179 - s.on('data', function (data)
180 - {
181 - // If this is upload data, save it to file
182 - if (this.httprequest.uploadFile)
183 - {
184 - 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.
185 - this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
186 - return;
187 - }
158 + // Clean up WebSocket
159 + this.removeAllListeners('data');
160 + });
161 + s.on('data', function (data) {
162 + // If this is upload data, save it to file
163 + if (this.httprequest.uploadFile) {
164 + 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.
165 + this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
166 + return;
167 + }
168
189 - if (this.httprequest.state == 0) {
190 - // Check if this is a relay connection
191 - if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
192 - } else {
193 - // Handle tunnel data
194 - if (this.httprequest.protocol == 0)
195 - {
196 - // Take a look at the protocol
197 - this.httprequest.protocol = parseInt(data);
198 - if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
199 - if (this.httprequest.protocol == 1)
200 - {
201 - // Remote terminal using native pipes
202 - if (process.platform == "win32")
203 - {
204 - this.httprequest._term = require('win-terminal').Start(80, 25);
205 - this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
206 - this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
207 - this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
208 - }
209 - else
210 - {
211 - this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
212 - this.httprequest.process.tunnel = this;
213 - this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
214 - this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
215 - this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
216 - this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
217 - this.prependListener('end', function () { this.httprequest.process.kill(); });
218 - }
169 + if (this.httprequest.state == 0) {
170 + // Check if this is a relay connection
171 + if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
172 + } else {
173 + // Handle tunnel data
174 + if (this.httprequest.protocol == 0) {
175 + // Take a look at the protocol
176 + this.httprequest.protocol = parseInt(data);
177 + if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
178 + if (this.httprequest.protocol == 1) {
179 + // Remote terminal using native pipes
180 + if (process.platform == "win32") {
181 + this.httprequest._term = require('win-terminal').Start(80, 25);
182 + this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
183 + this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
184 + this.prependListener('end', function () { this.httprequest._term.end(function () { sendConsoleText('Terminal was closed'); }); });
185 + }
186 + else {
187 + this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
188 + this.httprequest.process.tunnel = this;
189 + this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
190 + this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
191 + this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
192 + this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
193 + this.prependListener('end', function () { this.httprequest.process.kill(); });
194 + }
195
220 - this.on('end', function () {
221 - if (process.platform == "win32")
222 - {
223 - // Unpipe the web socket
224 - this.unpipe(this.httprequest._term);
225 - this.httprequest._term.unpipe(this);
196 + this.on('end', function () {
197 + if (process.platform == "win32") {
198 + // Unpipe the web socket
199 + this.unpipe(this.httprequest._term);
200 + this.httprequest._term.unpipe(this);
201
227 - // Clean up
228 - this.httprequest._term.end();
229 - this.httprequest._term = null;
202 + // Clean up
203 + this.httprequest._term.end();
204 + this.httprequest._term = null;
205 + }
206 + });
207 }
231 - });
232 - }
233 - }
234 - else if (this.httprequest.protocol == 5)
235 - {
236 - // Process files commands
237 - var cmd = null;
238 - try { cmd = JSON.parse(data); } catch (e) { };
239 - if (cmd == null) { return; }
240 - if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
241 - if (cmd.action == undefined) { return; }
242 - console.log('action: ', cmd.action);
208 + }
209 + else if (this.httprequest.protocol == 5) {
210 + // Process files commands
211 + var cmd = null;
212 + try { cmd = JSON.parse(data); } catch (e) { };
213 + if (cmd == null) { return; }
214 + if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { return; } // If this is control data, handle it now.
215 + if (cmd.action == undefined) { return; }
216 + console.log('action: ', cmd.action);
217
244 - //sendConsoleText('CMD: ' + JSON.stringify(cmd));
218 + //sendConsoleText('CMD: ' + JSON.stringify(cmd));
219
246 - if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
247 - //console.log(objToString(cmd, 0, ' '));
248 - switch (cmd.action)
249 - {
250 - case 'ls':
251 - // Send the folder content to the browser
252 - var response = getDirectoryInfo(cmd.path);
253 - if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
254 - this.write(new Buffer(JSON.stringify(response)));
255 - break;
256 - case 'mkdir': {
257 - // Create a new empty folder
258 - fs.mkdirSync(cmd.path);
259 - break;
260 - }
261 - case 'rm': {
262 - // Delete, possibly recursive delete
263 - for (var i in cmd.delfiles)
264 - {
265 - try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
220 + if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
221 + //console.log(objToString(cmd, 0, ' '));
222 + switch (cmd.action) {
223 + case 'ls':
224 + // Send the folder content to the browser
225 + var response = getDirectoryInfo(cmd.path);
226 + if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
227 + this.write(new Buffer(JSON.stringify(response)));
228 + break;
229 + case 'mkdir': {
230 + // Create a new empty folder
231 + fs.mkdirSync(cmd.path);
232 + break;
233 + }
234 + case 'rm': {
235 + // Delete, possibly recursive delete
236 + for (var i in cmd.delfiles) {
237 + try { deleteFolderRecursive(path.join(cmd.path, cmd.delfiles[i]), cmd.rec); } catch (e) { }
238 + }
239 + break;
240 + }
241 + case 'rename': {
242 + // Rename a file or folder
243 + var oldfullpath = path.join(cmd.path, cmd.oldname);
244 + var newfullpath = path.join(cmd.path, cmd.newname);
245 + try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
246 + break;
247 + }
248 + case 'upload': {
249 + // Upload a file, browser to agent
250 + if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
251 + if (cmd.path == undefined) break;
252 + var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
253 + try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
254 + this.httprequest.uploadFileid = cmd.reqid;
255 + if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
256 + break;
257 + }
258 + case 'copy': {
259 + // Copy a bunch of files from scpath to dspath
260 + for (var i in cmd.names) {
261 + var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
262 + if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
263 + }
264 + break;
265 + }
266 + case 'move': {
267 + // Move a bunch of files from scpath to dspath
268 + for (var i in cmd.names) {
269 + var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
270 + if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
271 + }
272 + break;
273 + }
274 }
267 - break;
268 - }
269 - case 'rename': {
270 - // Rename a file or folder
271 - var oldfullpath = path.join(cmd.path, cmd.oldname);
272 - var newfullpath = path.join(cmd.path, cmd.newname);
273 - try { fs.renameSync(oldfullpath, newfullpath); } catch (e) { console.log(e); }
274 - break;
275 - }
276 - case 'upload': {
277 - // Upload a file, browser to agent
278 - if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
279 - if (cmd.path == undefined) break;
280 - var filepath = cmd.name ? path.join(cmd.path, cmd.name) : cmd.path;
281 - try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
282 - this.httprequest.uploadFileid = cmd.reqid;
283 - if (this.httprequest.uploadFile) { this.write(new Buffer(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
284 - break;
285 - }
286 - case 'copy': {
287 - // Copy a bunch of files from scpath to dspath
288 - for (var i in cmd.names) {
289 - var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
290 - if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
291 - }
292 - break;
293 - }
294 - case 'move': {
295 - // Move a bunch of files from scpath to dspath
296 - for (var i in cmd.names) {
297 - var sc = path.join(cmd.scpath, cmd.names[i]), ds = path.join(cmd.dspath, cmd.names[i]);
298 - if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
299 - }
300 - break;
275 }
276 }
303 - }
304 - }
305 - });
306 - });
307 - tunnel.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
308 - tunnel.sessionid = data.sessionid;
309 - tunnel.rights = data.rights;
310 - tunnel.state = 0;
311 - tunnel.url = xurl;
312 - tunnel.protocol = 0;
313 - tunnel.tcpaddr = data.tcpaddr;
314 - tunnel.tcpport = data.tcpport;
315 - tunnel.end();
316 - // Put the tunnel in the tunnels list
317 - var index = nextTunnelIndex++;
318 - tunnel.index = index;
319 - tunnels[index] = tunnel;
277 + });
278 + });
279 + tunnel.onerror = function (e) { sendConsoleText("ERROR: " + JSON.stringify(e)); }
280 + tunnel.sessionid = data.sessionid;
281 + tunnel.rights = data.rights;
282 + tunnel.state = 0;
283 + tunnel.url = xurl;
284 + tunnel.protocol = 0;
285 + tunnel.tcpaddr = data.tcpaddr;
286 + tunnel.tcpport = data.tcpport;
287 + tunnel.end();
288 + // Put the tunnel in the tunnels list
289 + var index = nextTunnelIndex++;
290 + tunnel.index = index;
291 + tunnels[index] = tunnel;
292
321 - //sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
293 + //sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
294 + }
295 + }
296 + break;
297 }
323 - }
324 - break;
325 - }
298
327 - default:
328 - // Unknown action, ignore it.
329 - break;
299 + default:
300 + // Unknown action, ignore it.
301 + break;
302 + }
303 + break;
304 }
331 - break;
332 - }
305 default:
306 // Unknown action, ignore it.
307 break;
@@ -337,20 +309,16 @@ require('MeshAgent').AddCommandHandler(function (data)
309 }
310 });
311
340 -function processConsoleCommand(cmd, args, rights, sessionid)
341 -{
342 - try
343 - {
312 +function processConsoleCommand(cmd, args, rights, sessionid) {
313 + try {
314 var response = null;
345 - switch (cmd)
346 - {
315 + switch (cmd) {
316 case 'help':
348 - response = 'Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.';
317 + response = "Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo.";
318 break;
350 -
319 case 'osinfo': { // Return the operating system information
320 var i = 1;
353 - if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
321 + if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = "Calling " + i + " times."; }
322 for (var j = 0; j < i; j++) {
323 var pr = require('os').name();
324 pr.sessionid = sessionid;
@@ -363,34 +331,34 @@ function processConsoleCommand(cmd, args, rights, sessionid)
331 break;
332 }
333 case 'dbget': { // Return the data store value for a given key
366 - if (db == null) { response = 'Database not accessible.'; break; }
334 + if (db == null) { response = "Database not accessible."; break; }
335 if (args['_'].length != 1) {
368 - response = 'Proper usage: dbget (key)'; // Display the value for a given database key
336 + response = "Proper usage: dbget (key)"; // Display the value for a given database key
337 } else {
338 response = db.Get(args['_'][0]);
339 }
340 break;
341 }
342 case 'dbset': { // Set a data store key and value pair
375 - if (db == null) { response = 'Database not accessible.'; break; }
343 + if (db == null) { response = "Database not accessible."; break; }
344 if (args['_'].length != 2) {
377 - response = 'Proper usage: dbset (key) (value)'; // Set a database key
345 + response = "Proper usage: dbset (key) (value)"; // Set a database key
346 } else {
347 var r = db.Put(args['_'][0], args['_'][1]);
380 - response = 'Key set: ' + r;
348 + response = "Key set: " + r;
349 }
350 break;
351 }
352 case 'dbcompact': { // Compact the data store
385 - if (db == null) { response = 'Database not accessible.'; break; }
353 + if (db == null) { response = "Database not accessible."; break; }
354 var r = db.Compact();
387 - response = 'Database compacted: ' + r;
355 + response = "Database compacted: " + r;
356 break;
357 }
358 case 'tunnels': { // Show the list of current tunnels
359 response = '';
392 - for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; }
393 - if (response == '') { response = 'No websocket sessions.'; }
360 + for (var i in tunnels) { response += "Tunnel #" + i + ", " + tunnels[i].url + '\r\n'; }
361 + if (response == '') { response = "No websocket sessions."; }
362 break;
363 }
364 case 'netinfo': { // Show network interface information
@@ -404,13 +372,12 @@ function processConsoleCommand(cmd, args, rights, sessionid)
372 break;
373 }
374 }
407 - } catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); }
375 + } catch (e) { response = "Command returned an exception error: " + e; console.log(e); }
376 if (response != null) { sendConsoleText(response, sessionid); }
377 }
378
379 // Get a formated response for a given directory path
412 -function getDirectoryInfo(reqpath)
413 -{
380 +function getDirectoryInfo(reqpath) {
381 var response = { path: reqpath, dir: [] };
382 if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
383 // List all the drives in the root, or the root itself
meshuser.js
+1 -1
@@ -645,7 +645,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
645 }
646 else if ((command.fileop == 'rename') && (common.IsFilenameValid(command.oldname) == true) && (common.IsFilenameValid(command.newname) == true)) {
647 // Rename
648 - try { fs.renameSync(path + "/" + command.oldname, path + "/" + command.newname); } catch (e) { }
648 + try { fs.renameSync(path + '/' + command.oldname, path + '/' + command.newname); } catch (e) { }
649 }
650 else if ((command.fileop == 'copy') || (command.fileop == 'move')) {
651 if (common.validateArray(command.names, 1) == false) return;
webserver.js
+6 -5
@@ -4262,16 +4262,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4262 // TODO: Add multi-server support
4263 }
4264 }
4265 - } else { // Route this command to the mesh
4265 + } else { // Route this command to all users with MESHRIGHT_AGENTCONSOLE rights to this device group
4266 command.nodeid = nodeid;
4267 var cmdstr = JSON.stringify(command);
4268 - if (obj.GetMeshRights(userid, meshid) == 0) return; // TODO: Check if this is ok
4268
4270 - // Find all connected users for this mesh and send the message
4269 + // Find all connected user sessions with access to this device
4270 for (var userid in obj.wssessions) {
4271 var xsessions = obj.wssessions[userid];
4273 - // Send the message to all users on this server
4274 - for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } }
4272 + if (obj.GetMeshRights(userid, meshid) != 0) {
4273 + // Send the message to all sessions for this user on this server
4274 + for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } }
4275 + }
4276 }
4277
4278 // Send the message to all users of other servers