Removed mobile setup when in LAN mode.
Ylian Saint-Hilaire committed
Jan 24, 2021 at 21:51 UTC
a885664a4190b943f50563b6ea2e1525b908624b
5 files changed
+2609
-3159
agents/meshcore.js
+674
-1329
@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16
17
-process.on('uncaughtException', function (ex)
18
-{
17
+process.on('uncaughtException', function (ex) {
18
require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "uncaughtException1: " + ex });
19
});
20
@@ -42,11 +41,9 @@ var MESHRIGHT_CHATNOTIFY = 16384;
41
var MESHRIGHT_UNINSTALL = 32768;
42
var MESHRIGHT_NODESKTOP = 65536;
43
45
-if (require('MeshAgent').ARCHID == null)
46
-{
44
+if (require('MeshAgent').ARCHID == null) {
45
var id = null;
48
- switch (process.platform)
49
- {
46
+ switch (process.platform) {
47
case 'win32':
48
id = require('_GenericMarshal').PointerSize == 4 ? 3 : 4;
49
break;
@@ -54,12 +51,10 @@ if (require('MeshAgent').ARCHID == null)
51
id = require('_GenericMarshal').PointerSize == 4 ? 31 : 30;
52
break;
53
case 'darwin':
57
- try
58
- {
54
+ try {
55
id = require('os').arch() == 'x64' ? 16 : 29;
56
}
61
- catch (xx)
62
- {
57
+ catch (xx) {
58
id = 16;
59
}
60
break; break;
@@ -72,11 +67,9 @@ var agentFileHttpRequests = {}; // Currently active agent HTTPS GET requests fro
67
var agentFileHttpPendingRequests = []; // Pending HTTPS GET requests from the server.
68
var debugConsole = (_MSH().debugConsole == 1);
69
75
-if (process.platform == 'win32' && require('user-sessions').isRoot())
76
-{
70
+if (process.platform == 'win32' && require('user-sessions').isRoot()) {
71
// Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
78
- try
79
- {
72
+ try {
73
var writtenSize = 0, actualSize = Math.floor(require('fs').statSync(process.execPath).size / 1024);
74
try { writtenSize = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize'); } catch (e) { }
75
if (writtenSize != actualSize) { try { require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize', actualSize); } catch (e) { } }
@@ -84,24 +77,20 @@ if (process.platform == 'win32' && require('user-sessions').isRoot())
77
78
// Check to see if we are the Installed Mesh Agent Service, if we are, make sure we can run in Safe Mode
79
var svcname = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
87
- try
88
- {
80
+ try {
81
svcname = require('MeshAgent').serviceName;
82
}
91
- catch (x)
92
- {
83
+ catch (x) {
84
}
85
95
- try
96
- {
86
+ try {
87
var meshCheck = false;
88
try { meshCheck = require('service-manager').manager.getService(svcname).isMe(); } catch (e) { }
89
if (meshCheck && require('win-bcd').isSafeModeService && !require('win-bcd').isSafeModeService(svcname)) { require('win-bcd').enableSafeModeService(svcname); }
90
} catch (e) { }
91
}
92
103
-if (process.platform == 'darwin' && !process.versions)
104
-{
93
+if (process.platform == 'darwin' && !process.versions) {
94
// This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly
95
var child = require('child_process').execFile('/bin/sh', ['sh']);
96
child.stdout.str = '';
@@ -110,21 +99,18 @@ if (process.platform == 'darwin' && !process.versions)
99
child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }");
100
child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n");
101
child.waitExit();
113
- if (child.stdout.str.trim() == 'Crashed')
114
- {
102
+ if (child.stdout.str.trim() == 'Crashed') {
103
child = require('child_process').execFile('/bin/sh', ['sh']);
104
child.stdout.str = '';
105
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
106
child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n");
107
child.waitExit();
108
121
- if (parseInt(child.stdout.str.trim()) == process.pid)
122
- {
109
+ if (parseInt(child.stdout.str.trim()) == process.pid) {
110
// The currently running MeshAgent is us, so we can continue with the update
111
var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString();
112
var tokens = plist.split('<key>KeepAlive</key>');
126
- if (tokens[1].split('>')[0].split('<')[1] == 'dict')
127
- {
113
+ if (tokens[1].split('>')[0].split('<')[1] == 'dict') {
114
var tmp = tokens[1].split('</dict>');
115
tmp.shift();
116
tokens[1] = '\n <true/>' + tmp.join('</dict>');
@@ -180,8 +166,7 @@ if (process.platform == 'darwin' && !process.versions)
166
}
167
168
// Add an Intel AMT event to the log
183
-function addAmtEvent(msg)
184
-{
169
+function addAmtEvent(msg) {
170
if (obj.amtevents == null) { obj.amtevents = []; }
171
var d = new Date();
172
obj.amtevents.push(zeroPad(d.getHours(), 2) + ':' + zeroPad(d.getMinutes(), 2) + ':' + zeroPad(d.getSeconds(), 2) + ', ' + msg);
@@ -196,10 +181,8 @@ if (process.platform != 'win32') { try { require('fs').unlinkSync(process.cwd()
181
obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC');
182
try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH, writableAll: true, maxConnections: 5 }); } catch (e) { }
183
obj.DAIPC._daipc = [];
199
-obj.DAIPC.on('connection', function (c)
200
-{
201
- c._send = function (j)
202
- {
184
+obj.DAIPC.on('connection', function (c) {
185
+ c._send = function (j) {
186
var data = JSON.stringify(j);
187
var packet = Buffer.alloc(data.length + 4);
188
packet.writeUInt32LE(data.length + 4, 0);
@@ -209,8 +192,7 @@ obj.DAIPC.on('connection', function (c)
192
this._daipc.push(c);
193
c.parent = this;
194
c.on('end', function () { removeRegisteredApp(this); });
212
- c.on('data', function (chunk)
213
- {
195
+ c.on('data', function (chunk) {
196
if (chunk.length < 4) { this.unshift(chunk); return; }
197
var len = chunk.readUInt32LE(0);
198
if (len > 8192) { removeRegisteredApp(this); this.end(); return; }
@@ -220,10 +202,8 @@ obj.DAIPC.on('connection', function (c)
202
try { data = JSON.parse(data.toString()); } catch (e) { }
203
if ((data == null) || (typeof data.cmd != 'string')) return;
204
223
- try
224
- {
225
- switch (data.cmd)
226
- {
205
+ try {
206
+ switch (data.cmd) {
207
case 'requesthelp':
208
if (this._registered == null) return;
209
sendConsoleText('Request Help (' + this._registered + '): ' + data.value);
@@ -238,8 +218,7 @@ obj.DAIPC.on('connection', function (c)
218
try { mesh.SendCommand({ action: 'sessions', type: 'help', value: {} }); } catch (e) { }
219
break;
220
case 'register':
241
- if (typeof data.value == 'string')
242
- {
221
+ if (typeof data.value == 'string') {
222
this._registered = data.value;
223
var apps = {};
224
apps[data.value] = 1;
@@ -248,15 +227,13 @@ obj.DAIPC.on('connection', function (c)
227
}
228
break;
229
case 'query':
251
- switch (data.value)
252
- {
230
+ switch (data.value) {
231
case 'connection':
232
data.result = require('MeshAgent').ConnectedServer;
233
this._send(data);
234
break;
235
case 'descriptors':
258
- require('ChainViewer').getSnapshot().then(function (f)
259
- {
236
+ require('ChainViewer').getSnapshot().then(function (f) {
237
this.tag.payload.result = f;
238
this.tag.ipc._send(this.tag.payload);
239
}).parentPromise.tag = { ipc: this, payload: data };
@@ -280,8 +257,7 @@ obj.DAIPC.on('connection', function (c)
257
try { mesh.SendCommand({ action: 'meshToolInfo', name: data.name, hash: data.hash, cookie: data.cookie ? true : false, pipe: true }); } catch (e) { }
258
break;
259
case 'console':
283
- if (debugConsole)
284
- {
260
+ if (debugConsole) {
261
var args = splitArgs(data.value);
262
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), 0, 'pipe');
263
}
@@ -293,28 +269,24 @@ obj.DAIPC.on('connection', function (c)
269
});
270
271
// Send current sessions to registered apps
296
-function broadcastSessionsToRegisteredApps(x)
297
-{
272
+function broadcastSessionsToRegisteredApps(x) {
273
broadcastToRegisteredApps({ cmd: 'sessions', sessions: tunnelUserCount });
274
}
275
276
// Send this object to all registered local applications
302
-function broadcastToRegisteredApps(x)
303
-{
277
+function broadcastToRegisteredApps(x) {
278
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
279
for (var i in obj.DAIPC._daipc) { if (obj.DAIPC._daipc[i]._registered != null) { obj.DAIPC._daipc[i]._send(x); } }
280
}
281
282
// Send this object to a specific registered local applications
309
-function sendToRegisteredApp(appid, x)
310
-{
283
+function sendToRegisteredApp(appid, x) {
284
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
285
for (var i in obj.DAIPC._daipc) { if (obj.DAIPC._daipc[i]._registered == appid) { obj.DAIPC._daipc[i]._send(x); } }
286
}
287
288
// Send list of registered apps to the server
316
-function updateRegisteredAppsToServer()
317
-{
289
+function updateRegisteredAppsToServer() {
290
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
291
var apps = {};
292
for (var i in obj.DAIPC._daipc) { if (apps[obj.DAIPC._daipc[i]._registered] == null) { apps[obj.DAIPC._daipc[i]._registered] = 1; } else { apps[obj.DAIPC._daipc[i]._registered]++; } }
@@ -322,32 +294,26 @@ function updateRegisteredAppsToServer()
294
}
295
296
// Remove a registered app
325
-function removeRegisteredApp(pipe)
326
-{
297
+function removeRegisteredApp(pipe) {
298
for (var i = obj.DAIPC._daipc.length - 1; i >= 0; i--) { if (obj.DAIPC._daipc[i] === pipe) { obj.DAIPC._daipc.splice(i, 1); } }
299
if (pipe._registered != null) updateRegisteredAppsToServer();
300
}
301
331
-function diagnosticAgent_uninstall()
332
-{
302
+function diagnosticAgent_uninstall() {
303
require('service-manager').manager.uninstallService('meshagentDiagnostic');
304
require('task-scheduler').delete('meshagentDiagnostic/periodicStart');
305
}
336
-function diagnosticAgent_installCheck(install)
337
-{
338
- try
339
- {
306
+function diagnosticAgent_installCheck(install) {
307
+ try {
308
var diag = require('service-manager').manager.getService('meshagentDiagnostic');
309
return (diag);
310
}
343
- catch (e)
344
- {
311
+ catch (e) {
312
}
313
if (!install) { return (null); }
314
315
var svc = null;
349
- try
350
- {
316
+ try {
317
require('service-manager').manager.installService(
318
{
319
name: 'meshagentDiagnostic',
@@ -359,8 +325,7 @@ function diagnosticAgent_installCheck(install)
325
});
326
svc = require('service-manager').manager.getService('meshagentDiagnostic');
327
}
362
- catch (e)
363
- {
328
+ catch (e) {
329
return (null);
330
}
331
var proxyConfig = require('global-tunnel').proxyConfig;
@@ -373,12 +338,10 @@ function diagnosticAgent_installCheck(install)
338
ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri);
339
if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); }
340
if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); }
376
- if (proxyConfig)
377
- {
341
+ if (proxyConfig) {
342
ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port);
343
}
380
- else
381
- {
344
+ else {
345
ddb.Put('ignoreProxyFile', '1');
346
}
347
@@ -395,24 +358,18 @@ function diagnosticAgent_installCheck(install)
358
}
359
360
// Monitor the file 'batterystate.txt' in the agent's folder and sends battery update when this file is changed.
398
-if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('fs').watch != null))
399
-{
361
+if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('fs').watch != null)) {
362
// Setup manual battery monitoring
401
- require('MeshAgent')._batteryFileWatcher = require('fs').watch(process.cwd(), function ()
402
- {
363
+ require('MeshAgent')._batteryFileWatcher = require('fs').watch(process.cwd(), function () {
364
if (require('MeshAgent')._batteryFileTimer != null) return;
404
- require('MeshAgent')._batteryFileTimer = setTimeout(function ()
405
- {
406
- try
407
- {
365
+ require('MeshAgent')._batteryFileTimer = setTimeout(function () {
366
+ try {
367
require('MeshAgent')._batteryFileTimer = null;
368
var data = null;
369
try { data = require('fs').readFileSync(process.cwd() + 'batterystate.txt').toString(); } catch (e) { }
411
- if ((data != null) && (data.length < 10))
412
- {
370
+ if ((data != null) && (data.length < 10)) {
371
data = data.split(',');
414
- if ((data.length == 2) && ((data[0] == 'ac') || (data[0] == 'dc')))
415
- {
372
+ if ((data.length == 2) && ((data[0] == 'ac') || (data[0] == 'dc'))) {
373
var level = parseInt(data[1]);
374
if ((level >= 0) && (level <= 100)) { require('MeshAgent').SendCommand({ action: 'battery', state: data[0], level: level }); }
375
}
@@ -421,31 +378,24 @@ if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('
378
}, 1000);
379
});
380
}
424
-else
425
-{
381
+else {
382
// Setup normal battery monitoring
427
- if (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered())
428
- {
429
- require('MeshAgent')._battLevelChanged = function _battLevelChanged(val)
430
- {
383
+ if (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered()) {
384
+ require('MeshAgent')._battLevelChanged = function _battLevelChanged(val) {
385
_battLevelChanged.self._currentBatteryLevel = val;
386
_battLevelChanged.self.SendCommand({ action: 'battery', state: _battLevelChanged.self._currentPowerState, level: val });
387
};
388
require('MeshAgent')._battLevelChanged.self = require('MeshAgent');
435
- require('MeshAgent')._powerChanged = function _powerChanged(val)
436
- {
389
+ require('MeshAgent')._powerChanged = function _powerChanged(val) {
390
_powerChanged.self._currentPowerState = (val == 'AC' ? 'ac' : 'dc');
391
_powerChanged.self.SendCommand({ action: 'battery', state: (val == 'AC' ? 'ac' : 'dc'), level: _powerChanged.self._currentBatteryLevel });
392
};
393
require('MeshAgent')._powerChanged.self = require('MeshAgent');
441
- require('MeshAgent').on('Connected', function (status)
442
- {
443
- if (status == 0)
444
- {
394
+ require('MeshAgent').on('Connected', function (status) {
395
+ if (status == 0) {
396
require('power-monitor').removeListener('acdc', this._powerChanged);
397
require('power-monitor').removeListener('batteryLevel', this._battLevelChanged);
447
- } else
448
- {
398
+ } else {
399
require('power-monitor').on('acdc', this._powerChanged);
400
require('power-monitor').on('batteryLevel', this._battLevelChanged);
401
}
@@ -462,30 +412,23 @@ try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; meshCoreO
412
413
414
// Setup logged in user monitoring (THIS IS BROKEN IN WIN7)
465
-try
466
-{
415
+try {
416
var userSession = require('user-sessions');
468
- userSession.on('changed', function onUserSessionChanged()
469
- {
470
- userSession.enumerateUsers().then(function (users)
471
- {
472
- if (process.platform == 'linux')
473
- {
474
- if (userSession._startTime == null)
475
- {
417
+ userSession.on('changed', function onUserSessionChanged() {
418
+ userSession.enumerateUsers().then(function (users) {
419
+ if (process.platform == 'linux') {
420
+ if (userSession._startTime == null) {
421
userSession._startTime = Date.now();
422
userSession._count = users.length;
423
}
479
- else if (Date.now() - userSession._startTime < 10000 && users.length == userSession._count)
480
- {
424
+ else if (Date.now() - userSession._startTime < 10000 && users.length == userSession._count) {
425
userSession.removeAllListeners('changed');
426
return;
427
}
428
}
429
430
var u = [], a = users.Active;
487
- for (var i = 0; i < a.length; i++)
488
- {
431
+ for (var i = 0; i < a.length; i++) {
432
var un = a[i].Domain ? (a[i].Domain + '\\' + a[i].Username) : (a[i].Username);
433
if (u.indexOf(un) == -1) { u.push(un); } // Only push users in the list once.
434
}
@@ -517,11 +460,9 @@ var apftunnel = null;
460
var tunnelUserCount = { terminal: {}, files: {}, tcp: {}, udp: {}, msg: {} }; // List of userid->count sessions for terminal, files and TCP/UDP routing
461
462
// Add to the server event log
520
-function MeshServerLog(msg, state)
521
-{
463
+function MeshServerLog(msg, state) {
464
if (typeof msg == 'string') { msg = { action: 'log', msg: msg }; } else { msg.action = 'log'; }
523
- if (state)
524
- {
465
+ if (state) {
466
if (state.userid) { msg.userid = state.userid; }
467
if (state.username) { msg.username = state.username; }
468
if (state.sessionid) { msg.sessionid = state.sessionid; }
@@ -531,11 +472,9 @@ function MeshServerLog(msg, state)
472
}
473
474
// Add to the server event log, use internationalized events
534
-function MeshServerLogEx(id, args, msg, state)
535
-{
475
+function MeshServerLogEx(id, args, msg, state) {
476
var msg = { action: 'log', msgid: id, msgArgs: args, msg: msg };
537
- if (state)
538
- {
477
+ if (state) {
478
if (state.userid) { msg.userid = state.userid; }
479
if (state.username) { msg.username = state.username; }
480
if (state.sessionid) { msg.sessionid = state.sessionid; }
@@ -550,16 +489,12 @@ sha = require('SHA256Stream');
489
mesh = require('MeshAgent');
490
childProcess = require('child_process');
491
553
-if (mesh.hasKVM == 1)
554
-{ // if the agent is compiled with KVM support
492
+if (mesh.hasKVM == 1) { // if the agent is compiled with KVM support
493
// Check if this computer supports a desktop
556
- try
557
- {
558
- if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support))
559
- {
494
+ try {
495
+ if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support)) {
496
meshCoreObj.caps |= 1; meshCoreObjChanged();
561
- } else if (process.platform == 'linux' || process.platform == 'freebsd')
562
- {
497
+ } else if (process.platform == 'linux' || process.platform == 'freebsd') {
498
require('monitor-info').on('kvmSupportDetected', function (value) { meshCoreObj.caps |= 1; meshCoreObjChanged(); });
499
}
500
} catch (e) { }
@@ -579,23 +514,18 @@ try {
514
// Fetch the SMBios Tables
515
var SMBiosTables = null;
516
var SMBiosTablesRaw = null;
582
-try
583
-{
517
+try {
518
var SMBiosModule = null;
519
try { SMBiosModule = require('smbios'); } catch (e) { }
586
- if (SMBiosModule != null)
587
- {
588
- SMBiosModule.get(function (data)
589
- {
590
- if (data != null)
591
- {
520
+ if (SMBiosModule != null) {
521
+ SMBiosModule.get(function (data) {
522
+ if (data != null) {
523
SMBiosTablesRaw = data;
524
SMBiosTables = require('smbios').parse(data)
525
if (mesh.isControlChannelConnected) { mesh.SendCommand({ action: 'smbios', value: SMBiosTablesRaw }); }
526
527
// If SMBios tables say that Intel AMT is present, try to connect MEI
597
- if (SMBiosTables.amtInfo && (SMBiosTables.amtInfo.AMT == true))
598
- {
528
+ if (SMBiosTables.amtInfo && (SMBiosTables.amtInfo.AMT == true)) {
529
var amtmodule = require('amt-manage');
530
amt = new amtmodule(mesh, db, false);
531
amt.on('portBinding_LMS', function (map) { mesh.SendCommand({ action: 'lmsinfo', value: { ports: map.keys() } }); });
@@ -609,8 +539,7 @@ try
539
} catch (e) { sendConsoleText("ex1: " + e); }
540
541
// Try to load up the WIFI scanner
612
-try
613
-{
542
+try {
543
var wifiScannerLib = require('wifi-scanner');
544
wifiScanner = new wifiScannerLib();
545
wifiScanner.on('accessPoint', function (data) { sendConsoleText("wifiScanner: " + data); });
@@ -619,28 +548,21 @@ try
548
// Get our location (lat/long) using our public IP address
549
var getIpLocationDataExInProgress = false;
550
var getIpLocationDataExCounts = [0, 0];
622
-function getIpLocationDataEx(func)
623
-{
551
+function getIpLocationDataEx(func) {
552
if (getIpLocationDataExInProgress == true) { return false; }
625
- try
626
- {
553
+ try {
554
getIpLocationDataExInProgress = true;
555
getIpLocationDataExCounts[0]++;
556
var options = http.parseUri("http://ipinfo.io/json");
557
options.method = 'GET';
631
- http.request(options, function (resp)
632
- {
633
- if (resp.statusCode == 200)
634
- {
558
+ http.request(options, function (resp) {
559
+ if (resp.statusCode == 200) {
560
var geoData = '';
561
resp.data = function (geoipdata) { geoData += geoipdata; };
637
- resp.end = function ()
638
- {
562
+ resp.end = function () {
563
var location = null;
640
- try
641
- {
642
- if (typeof geoData == 'string')
643
- {
564
+ try {
565
+ if (typeof geoData == 'string') {
566
var result = JSON.parse(geoData);
567
if (result.ip && result.loc) { location = result; }
568
}
@@ -657,61 +579,49 @@ function getIpLocationDataEx(func)
579
}
580
581
// Remove all Gateway MAC addresses for interface list. This is useful because the gateway MAC is not always populated reliably.
660
-function clearGatewayMac(str)
661
-{
582
+function clearGatewayMac(str) {
583
if (str == null) return null;
584
var x = JSON.parse(str);
585
for (var i in x.netif) { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } }
586
return JSON.stringify(x);
587
}
588
668
-function getIpLocationData(func)
669
-{
589
+function getIpLocationData(func) {
590
// Get the location information for the cache if possible
591
var publicLocationInfo = db.Get('publicLocationInfo');
592
if (publicLocationInfo != null) { publicLocationInfo = JSON.parse(publicLocationInfo); }
673
- if (publicLocationInfo == null)
674
- {
593
+ if (publicLocationInfo == null) {
594
// Nothing in the cache, fetch the data
676
- getIpLocationDataEx(function (locationData)
677
- {
678
- if (locationData != null)
679
- {
595
+ getIpLocationDataEx(function (locationData) {
596
+ if (locationData != null) {
597
publicLocationInfo = {};
598
publicLocationInfo.netInfoStr = lastNetworkInfo;
599
publicLocationInfo.locationData = locationData;
600
var x = db.Put('publicLocationInfo', JSON.stringify(publicLocationInfo)); // Save to database
601
if (func) func(locationData); // Report the new location
602
}
686
- else
687
- {
603
+ else {
604
if (func) func(null); // Report no location
605
}
606
});
607
}
692
- else
693
- {
608
+ else {
609
// Check the cache
695
- if (clearGatewayMac(publicLocationInfo.netInfoStr) == clearGatewayMac(lastNetworkInfo))
696
- {
610
+ if (clearGatewayMac(publicLocationInfo.netInfoStr) == clearGatewayMac(lastNetworkInfo)) {
611
// Cache match
612
if (func) func(publicLocationInfo.locationData);
613
}
700
- else
701
- {
614
+ else {
615
// Cache mismatch
703
- getIpLocationDataEx(function (locationData)
704
- {
705
- if (locationData != null)
706
- {
616
+ getIpLocationDataEx(function (locationData) {
617
+ if (locationData != null) {
618
publicLocationInfo = {};
619
publicLocationInfo.netInfoStr = lastNetworkInfo;
620
publicLocationInfo.locationData = locationData;
621
var x = db.Put('publicLocationInfo', JSON.stringify(publicLocationInfo)); // Save to database
622
if (func) func(locationData); // Report the new location
623
}
713
- else
714
- {
624
+ else {
625
if (func) func(publicLocationInfo.locationData); // Can't get new location, report the old location
626
}
627
});
@@ -720,10 +630,8 @@ function getIpLocationData(func)
630
}
631
632
// Polyfill String.endsWith
723
-if (!String.prototype.endsWith)
724
-{
725
- String.prototype.endsWith = function (searchString, position)
726
- {
633
+if (!String.prototype.endsWith) {
634
+ String.prototype.endsWith = function (searchString, position) {
635
var subjectString = this.toString();
636
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { position = subjectString.length; }
637
position -= searchString.length;
@@ -735,17 +643,13 @@ if (!String.prototype.endsWith)
643
// Polyfill path.join
644
obj.path =
645
{
738
- join: function ()
739
- {
646
+ join: function () {
647
var x = [];
741
- for (var i in arguments)
742
- {
648
+ for (var i in arguments) {
649
var w = arguments[i];
744
- if (w != null)
745
- {
650
+ if (w != null) {
651
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
747
- if (i != 0)
748
- {
652
+ if (i != 0) {
653
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
654
}
655
x.push(w);
@@ -769,8 +673,7 @@ function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r
673
function buf2rstr(buf) { var r = ''; for (var i = 0; i < buf.length; i++) { r += String.fromCharCode(buf[i]); } return r; }
674
675
// Convert a hex string to a raw string // TODO: Do this using Buffer(), will be MUCH faster
772
-function hex2rstr(d)
773
-{
676
+function hex2rstr(d) {
677
if (typeof d != "string" || d.length == 0) return '';
678
var r = '', m = ('' + d).match(/../g), t;
679
while (t = m.shift()) r += String.fromCharCode('0x' + t);
@@ -778,8 +681,7 @@ function hex2rstr(d)
681
}
682
683
// Convert an object to string with all functions
781
-function objToString(x, p, pad, ret)
782
-{
684
+function objToString(x, p, pad, ret) {
685
if (ret == undefined) ret = '';
686
if (p == undefined) p = 0;
687
if (x == null) { return '[null]'; }
@@ -797,26 +699,21 @@ function objToString(x, p, pad, ret)
699
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
700
701
// Split a string taking into account the quoats. Used for command line parsing
800
-function splitArgs(str)
801
-{
702
+function splitArgs(str) {
703
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
704
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
705
return myArray;
706
}
707
708
// Parse arguments string array into an object
808
-function parseArgs(argv)
809
-{
709
+function parseArgs(argv) {
710
var results = { '_': [] }, current = null;
811
- for (var i = 1, len = argv.length; i < len; i++)
812
- {
711
+ for (var i = 1, len = argv.length; i < len; i++) {
712
var x = argv[i];
814
- if (x.length > 2 && x[0] == '-' && x[1] == '-')
815
- {
713
+ if (x.length > 2 && x[0] == '-' && x[1] == '-') {
714
if (current != null) { results[current] = true; }
715
current = x.substring(2);
818
- } else
819
- {
716
+ } else {
717
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
718
}
719
}
@@ -825,8 +722,7 @@ function parseArgs(argv)
722
}
723
724
// Get server target url with a custom path
828
-function getServerTargetUrl(path)
829
-{
725
+function getServerTargetUrl(path) {
726
var x = mesh.ServerUrl;
727
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
728
if (x == null) { return null; }
@@ -837,35 +733,27 @@ function getServerTargetUrl(path)
733
}
734
735
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
840
-function getServerTargetUrlEx(url)
841
-{
736
+function getServerTargetUrlEx(url) {
737
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
738
return url;
739
}
740
741
// Send a wake-on-lan packet
847
-function sendWakeOnLan(hexMac)
848
-{
742
+function sendWakeOnLan(hexMac) {
743
hexMac = hexMac.split(':').join('');
744
var count = 0;
851
- try
852
- {
745
+ try {
746
var interfaces = require('os').networkInterfaces();
747
var magic = 'FFFFFFFFFFFF';
748
for (var x = 1; x <= 16; ++x) { magic += hexMac; }
749
var magicbin = Buffer.from(magic, 'hex');
750
858
- for (var adapter in interfaces)
859
- {
860
- if (interfaces.hasOwnProperty(adapter))
861
- {
862
- for (var i = 0; i < interfaces[adapter].length; ++i)
863
- {
751
+ for (var adapter in interfaces) {
752
+ if (interfaces.hasOwnProperty(adapter)) {
753
+ for (var i = 0; i < interfaces[adapter].length; ++i) {
754
var addr = interfaces[adapter][i];
865
- if ((addr.family == 'IPv4') && (addr.mac != '00:00:00:00:00:00'))
866
- {
867
- try
868
- {
755
+ if ((addr.family == 'IPv4') && (addr.mac != '00:00:00:00:00:00')) {
756
+ try {
757
var socket = require('dgram').createSocket({ type: 'udp4' });
758
socket.bind({ address: addr.address });
759
socket.setBroadcast(true);
@@ -885,22 +773,17 @@ function sendWakeOnLan(hexMac)
773
}
774
775
// Handle a mesh agent command
888
-function handleServerCommand(data)
889
-{
890
- if (typeof data == 'object')
891
- {
776
+function handleServerCommand(data) {
777
+ if (typeof data == 'object') {
778
// If this is a console command, parse it and call the console handler
893
- switch (data.action)
894
- {
779
+ switch (data.action) {
780
case 'agentupdate':
781
agentUpdate_Start(data.url, { hash: data.hash, tlshash: data.servertlshash, sessionid: data.sessionid });
782
break;
783
case 'msg': {
899
- switch (data.type)
900
- {
784
+ switch (data.type) {
785
case 'console': { // Process a console command
902
- if (data.value && data.sessionid)
903
- {
786
+ if (data.value && data.sessionid) {
787
MeshServerLogEx(17, [data.value], "Processing console command: " + data.value, data);
788
var args = splitArgs(data.value);
789
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
@@ -908,12 +791,10 @@ function handleServerCommand(data)
791
break;
792
}
793
case 'tunnel': {
911
- if (data.value != null)
912
- { // Process a new tunnel connection request
794
+ if (data.value != null) { // Process a new tunnel connection request
795
// Create a new tunnel object
796
var xurl = getServerTargetUrlEx(data.value);
915
- if (xurl != null)
916
- {
797
+ if (xurl != null) {
798
xurl = xurl.split('$').join('%24').split('@').join('%40'); // Escape the $ and @ characters
799
var woptions = http.parseUri(xurl);
800
woptions.perMessageDeflate = false;
@@ -921,8 +802,7 @@ function handleServerCommand(data)
802
803
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
804
woptions.rejectUnauthorized = 0;
924
- woptions.checkServerIdentity = function checkServerIdentity(certs)
925
- {
805
+ woptions.checkServerIdentity = function checkServerIdentity(certs) {
806
// If the tunnel certificate matches the control channel certificate, accept the connection
807
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
808
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
@@ -965,8 +845,7 @@ function handleServerCommand(data)
845
}
846
case 'messagebox': {
847
// Display a message box
968
- if (data.title && data.msg)
969
- {
848
+ if (data.title && data.msg) {
849
MeshServerLogEx(18, [data.title, data.msg], "Displaying message box, title=" + data.title + ", message=" + data.msg, data);
850
data.msg = data.msg.split('\r').join('\\r').split('\n').join('\\n');
851
try { require('message-box').create(data.title, data.msg, 120); } catch (e) { }
@@ -975,10 +854,8 @@ function handleServerCommand(data)
854
}
855
case 'ps': {
856
// Return the list of running processes
978
- if (data.sessionid)
979
- {
980
- processManager.getProcesses(function (plist)
981
- {
857
+ if (data.sessionid) {
858
+ processManager.getProcesses(function (plist) {
859
mesh.SendCommand({ action: 'msg', type: 'ps', value: JSON.stringify(plist), sessionid: data.sessionid });
860
});
861
}
@@ -986,8 +863,7 @@ function handleServerCommand(data)
863
}
864
case 'pskill': {
865
// Kill a process
989
- if (data.value)
990
- {
866
+ if (data.value) {
867
MeshServerLogEx(19, [data.value], "Killing process " + data.value, data);
868
try { process.kill(data.value); } catch (e) { sendConsoleText("pskill: " + JSON.stringify(e)); }
869
}
@@ -1002,8 +878,7 @@ function handleServerCommand(data)
878
}
879
case 'serviceStop': {
880
// Stop a service
1005
- try
1006
- {
881
+ try {
882
var service = require('service-manager').manager.getService(data.serviceName);
883
if (service != null) { service.stop(); }
884
} catch (e) { }
@@ -1011,8 +886,7 @@ function handleServerCommand(data)
886
}
887
case 'serviceStart': {
888
// Start a service
1014
- try
1015
- {
889
+ try {
890
var service = require('service-manager').manager.getService(data.serviceName);
891
if (service != null) { service.start(); }
892
} catch (e) { }
@@ -1020,8 +894,7 @@ function handleServerCommand(data)
894
}
895
case 'serviceRestart': {
896
// Restart a service
1023
- try
1024
- {
897
+ try {
898
var service = require('service-manager').manager.getService(data.serviceName);
899
if (service != null) { service.restart(); }
900
} catch (e) { }
@@ -1030,16 +903,12 @@ function handleServerCommand(data)
903
case 'deskBackground':
904
{
905
// Toggle desktop background
1033
- try
1034
- {
1035
- if (process.platform == 'win32')
1036
- {
906
+ try {
907
+ if (process.platform == 'win32') {
908
var stype = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
909
var sid = undefined;
1039
- if (stype == 1)
1040
- {
1041
- if (require('MeshAgent')._tsid != null)
1042
- {
910
+ if (stype == 1) {
911
+ if (require('MeshAgent')._tsid != null) {
912
stype = 5;
913
sid = require('MeshAgent')._tsid;
914
}
@@ -1055,15 +924,13 @@ function handleServerCommand(data)
924
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
925
child.stderr.on('data', function () { });
926
child.waitExit();
1058
- } else
1059
- {
927
+ } else {
928
var id = require('user-sessions').consoleUid();
929
var current = require('linux-gnome-helpers').getDesktopWallpaper(id);
930
if (current != '/dev/null') { require('MeshAgent')._wallpaper = current; }
931
require('linux-gnome-helpers').setDesktopWallpaper(id, current != '/dev/null' ? undefined : require('MeshAgent')._wallpaper);
932
}
1065
- } catch (e)
1066
- {
933
+ } catch (e) {
934
sendConsoleText(e);
935
}
936
break;
@@ -1078,22 +945,16 @@ function handleServerCommand(data)
945
case 'getclip': {
946
// Send the load clipboard back to the user
947
//sendConsoleText('getClip: ' + JSON.stringify(data));
1081
- if (require('MeshAgent').isService)
1082
- {
1083
- require('clipboard').dispatchRead().then(function (str)
1084
- {
1085
- if (str)
1086
- {
948
+ if (require('MeshAgent').isService) {
949
+ require('clipboard').dispatchRead().then(function (str) {
950
+ if (str) {
951
MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
952
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
953
}
954
});
1091
- } else
1092
- {
1093
- require("clipboard").read().then(function (str)
1094
- {
1095
- if (str)
1096
- {
955
+ } else {
956
+ require("clipboard").read().then(function (str) {
957
+ if (str) {
958
MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
959
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
960
}
@@ -1104,8 +965,7 @@ function handleServerCommand(data)
965
case 'setclip': {
966
// Set the load clipboard to a user value
967
sendConsoleText('setClip: ' + JSON.stringify(data));
1107
- if (typeof data.data == 'string')
1108
- {
968
+ if (typeof data.data == 'string') {
969
MeshServerLogEx(22, [data.data.length], "Setting clipboard content, " + data.data.length + " byte(s)", data);
970
if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard
971
mesh.SendCommand({ action: 'msg', type: 'setclip', sessionid: data.sessionid, success: true });
@@ -1126,8 +986,7 @@ function handleServerCommand(data)
986
var cpuuse = require('sysinfo').cpuUtilization();
987
cpuuse.sessionid = data.sessionid;
988
cpuuse.tag = data.tag;
1129
- cpuuse.then(function (data)
1130
- {
989
+ cpuuse.then(function (data) {
990
mesh.SendCommand(JSON.stringify(
991
{
992
action: 'msg',
@@ -1152,8 +1011,7 @@ function handleServerCommand(data)
1011
break;
1012
}
1013
case 'acmactivate': {
1155
- if (amt != null)
1156
- {
1014
+ if (amt != null) {
1015
MeshServerLogEx(23, null, "Attempting Intel AMT ACM mode activation", data);
1016
amt.setAcmResponse(data);
1017
}
@@ -1171,21 +1029,17 @@ function handleServerCommand(data)
1029
1030
// data.runAsUser: 0=Agent,1=UserOrAgent,2=UserOnly
1031
var options = {};
1174
- if (data.runAsUser > 0)
1175
- {
1032
+ if (data.runAsUser > 0) {
1033
try { options.uid = require('user-sessions').consoleUid(); } catch (e) { }
1034
options.type = require('child_process').SpawnTypes.TERM;
1035
}
1179
- if (data.runAsUser == 2)
1180
- {
1036
+ if (data.runAsUser == 2) {
1037
if (options.uid == null) break;
1038
if (((require('user-sessions').minUid != null) && (options.uid < require('user-sessions').minUid()))) break; // This command can only run as user.
1039
}
1040
1185
- if (process.platform == 'win32')
1186
- {
1187
- if (data.type == 1)
1188
- {
1041
+ if (process.platform == 'win32') {
1042
+ if (data.type == 1) {
1043
// Windows command shell
1044
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd'], options);
1045
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
@@ -1193,8 +1047,7 @@ function handleServerCommand(data)
1047
mesh.cmdchild.stderr.on('data', function (c) { sendConsoleText(c.toString()); });
1048
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
1049
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
1196
- } else if (data.type == 2)
1197
- {
1050
+ } else if (data.type == 2) {
1051
// Windows Powershell
1052
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-'], options);
1053
mesh.cmdchild.descriptorMetadata = 'UserCommandsPowerShell';
@@ -1203,8 +1056,7 @@ function handleServerCommand(data)
1056
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
1057
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
1058
}
1206
- } else if (data.type == 3)
1207
- {
1059
+ } else if (data.type == 3) {
1060
// Linux shell
1061
mesh.cmdchild = require('child_process').execFile('/bin/sh', ['sh'], options);
1062
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
@@ -1218,16 +1070,13 @@ function handleServerCommand(data)
1070
case 'uninstallagent':
1071
// Uninstall this agent
1072
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
1221
- try
1222
- {
1073
+ try {
1074
agentName = require('MeshAgent').serviceName;
1075
}
1225
- catch (x)
1226
- {
1076
+ catch (x) {
1077
}
1078
1229
- if (require('service-manager').manager.getService(agentName).isMe())
1230
- {
1079
+ if (require('service-manager').manager.getService(agentName).isMe()) {
1080
try { diagnosticAgent_uninstall(); } catch (e) { }
1081
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
1082
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 });
@@ -1235,8 +1084,7 @@ function handleServerCommand(data)
1084
break;
1085
case 'poweraction': {
1086
// Server telling us to execute a power action
1238
- if ((mesh.ExecPowerState != undefined) && (data.actiontype))
1239
- {
1087
+ if ((mesh.ExecPowerState != undefined) && (data.actiontype)) {
1088
var forced = 0;
1089
if (data.forced == 1) { forced = 1; }
1090
data.actiontype = parseInt(data.actiontype);
@@ -1254,8 +1102,7 @@ function handleServerCommand(data)
1102
}
1103
case 'toast': {
1104
// Display a toast message
1257
- if (data.title && data.msg)
1258
- {
1105
+ if (data.title && data.msg) {
1106
MeshServerLogEx(26, [data.title, data.msg], "Displaying toast message, title=" + data.title + ", message=" + data.msg, data);
1107
data.msg = data.msg.split('\r').join('\\r').split('\n').join('\\n');
1108
try { require('toaster').Toast(data.title, data.msg); } catch (e) { }
@@ -1272,8 +1119,7 @@ function handleServerCommand(data)
1119
case 'amtconfig': {
1120
// Perform Intel AMT activation and/or configuration
1121
if ((apftunnel != null) || (amt == null) || (typeof data.user != 'string') || (typeof data.pass != 'string')) break;
1275
- amt.getMeiState(15, function (state)
1276
- {
1122
+ amt.getMeiState(15, function (state) {
1123
if ((apftunnel != null) || (amt == null)) return;
1124
if ((state == null) || (state.ProvisioningState == null)) return;
1125
if ((state.UUID == null) || (state.UUID.length != 36)) return; // Bad UUID
@@ -1290,12 +1136,10 @@ function handleServerCommand(data)
1136
};
1137
addAmtEvent('LMS tunnel start.');
1138
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
1293
- apftunnel.onJsonControl = function (data)
1294
- {
1139
+ apftunnel.onJsonControl = function (data) {
1140
if (data.action == 'console') { addAmtEvent(data.msg); } // Add console message to AMT event log
1141
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
1297
- if (data.action == 'deactivate')
1298
- { // Request CCM deactivation
1142
+ if (data.action == 'deactivate') { // Request CCM deactivation
1143
var amtMeiModule, amtMei;
1144
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { if (apftunnel) apftunnel.sendMeiDeactivationState(1); return; }
1145
amtMei.on('error', function (e) { if (apftunnel) apftunnel.sendMeiDeactivationState(1); });
@@ -1315,8 +1159,7 @@ function handleServerCommand(data)
1159
}
1160
case 'sysinfo': {
1161
// Fetch system information
1318
- getSystemInformation(function (results)
1319
- {
1162
+ getSystemInformation(function (results) {
1163
if ((results != null) && (data.hash != results.hash)) { mesh.SendCommand({ action: 'sysinfo', sessionid: this.sessionid, data: results }); }
1164
});
1165
break;
@@ -1329,18 +1172,14 @@ function handleServerCommand(data)
1172
}
1173
case 'coredump':
1174
// Set the current agent coredump situation.
1332
- if (data.value === true)
1333
- {
1334
- if (process.platform == 'win32')
1335
- {
1175
+ if (data.value === true) {
1176
+ if (process.platform == 'win32') {
1177
// TODO: This replace() below is not ideal, would be better to remove the .exe at the end instead of replace.
1178
process.coreDumpLocation = process.execPath.replace('.exe', '.dmp');
1338
- } else
1339
- {
1179
+ } else {
1180
process.coreDumpLocation = (process.cwd() != '//') ? (process.cwd() + 'core') : null;
1181
}
1342
- } else if (data.value === false)
1343
- {
1182
+ } else if (data.value === false) {
1183
process.coreDumpLocation = null;
1184
}
1185
break;
@@ -1349,18 +1188,15 @@ function handleServerCommand(data)
1188
var r = { action: 'getcoredump', value: (process.coreDumpLocation != null) };
1189
var coreDumpPath = null;
1190
if (process.platform == 'win32') { coreDumpPath = process.coreDumpLocation; } else { coreDumpPath = (process.cwd() != '//') ? fs.existsSync(process.cwd() + 'core') : null; }
1352
- if ((coreDumpPath != null) && (fs.existsSync(coreDumpPath)))
1353
- {
1354
- try
1355
- {
1191
+ if ((coreDumpPath != null) && (fs.existsSync(coreDumpPath))) {
1192
+ try {
1193
var coredate = fs.statSync(coreDumpPath).mtime;
1194
var coretime = new Date(coredate).getTime();
1195
var agenttime = new Date(fs.statSync(process.execPath).mtime).getTime();
1196
if (coretime > agenttime) { r.exists = (db.Get('CoreDumpTime') != coredate); }
1197
} catch (ex) { }
1198
}
1362
- if (r.exists == true)
1363
- {
1199
+ if (r.exists == true) {
1200
r.agenthashhex = getSHA384FileHash(process.execPath).toString('hex'); // Hash of current agent
1201
r.corehashhex = getSHA384FileHash(coreDumpPath).toString('hex'); // Hash of core dump file
1202
}
@@ -1381,8 +1217,7 @@ function handleServerCommand(data)
1217
}
1218
1219
// Agent just get a file from the server and save it locally.
1384
-function serverFetchFile()
1385
-{
1220
+function serverFetchFile() {
1221
if ((Object.keys(agentFileHttpRequests).length > 4) || (agentFileHttpPendingRequests.length == 0)) return; // No more than 4 active HTTPS requests to the server.
1222
var data = agentFileHttpPendingRequests.shift();
1223
if ((data.overwrite !== true) && fs.existsSync(data.path)) return; // Don't overwrite an existing file.
@@ -1393,8 +1228,7 @@ function serverFetchFile()
1228
1229
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
1230
agentFileHttpOptions.rejectUnauthorized = 0;
1396
- agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs)
1397
- {
1231
+ agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs) {
1232
// If the tunnel certificate matches the control channel certificate, accept the connection
1233
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
1234
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
@@ -1405,11 +1239,9 @@ function serverFetchFile()
1239
1240
if (agentFileHttpOptions == null) return;
1241
var agentFileHttpRequest = http.request(agentFileHttpOptions,
1408
- function (response)
1409
- {
1242
+ function (response) {
1243
response.xparent = this;
1411
- try
1412
- {
1244
+ try {
1245
response.xfile = fs.createWriteStream(this.xpath, { flags: 'wbN' })
1246
response.pipe(response.xfile);
1247
response.end = function () { delete agentFileHttpRequests[this.xparent.xurlpath]; delete this.xparent; serverFetchFile(); }
@@ -1432,13 +1264,10 @@ function onFileWatcher(a, b) {
1264
}
1265
*/
1266
1435
-function getSystemInformation(func)
1436
-{
1437
- try
1438
- {
1267
+function getSystemInformation(func) {
1268
+ try {
1269
var results = { hardware: require('identifiers').get() }; // Hardware info
1440
- if (results.hardware && results.hardware.windows)
1441
- {
1270
+ if (results.hardware && results.hardware.windows) {
1271
// Remove extra entries and things that change quickly
1272
var x = results.hardware.windows.osinfo;
1273
try { delete x.FreePhysicalMemory; } catch (e) { }
@@ -1448,24 +1277,19 @@ function getSystemInformation(func)
1277
try { delete x.MaxProcessMemorySize; } catch (e) { }
1278
try { delete x.TotalVirtualMemorySize; } catch (e) { }
1279
try { delete x.TotalVisibleMemorySize; } catch (e) { }
1451
- try
1452
- {
1280
+ try {
1281
if (results.hardware.windows.memory) { for (var i in results.hardware.windows.memory) { delete results.hardware.windows.memory[i].Node; } }
1282
if (results.hardware.windows.osinfo) { delete results.hardware.windows.osinfo.Node; }
1283
if (results.hardware.windows.partitions) { for (var i in results.hardware.windows.partitions) { delete results.hardware.windows.partitions[i].Node; } }
1284
} catch (e) { }
1285
}
1458
- if (process.platform == 'win32')
1459
- {
1286
+ if (process.platform == 'win32') {
1287
results.pendingReboot = require('win-info').pendingReboot(); // Pending reboot
1461
- if (require('identifiers').volumes != null)
1462
- {
1463
- try
1464
- {
1288
+ if (require('identifiers').volumes != null) {
1289
+ try {
1290
results.volumes = require('identifiers').volumes();
1291
}
1467
- catch (e)
1468
- {
1292
+ catch (e) {
1293
}
1294
}
1295
}
@@ -1499,46 +1323,35 @@ function getSystemInformation(func)
1323
}
1324
1325
// Get a formated response for a given directory path
1502
-function getDirectoryInfo(reqpath)
1503
-{
1326
+function getDirectoryInfo(reqpath) {
1327
var response = { path: reqpath, dir: [] };
1505
- if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32'))
1506
- {
1328
+ if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
1329
// List all the drives in the root, or the root itself
1330
var results = null;
1331
try { results = fs.readDrivesSync(); } catch (e) { } // TODO: Anyway to get drive total size and free space? Could draw a progress bar.
1510
- if (results != null)
1511
- {
1512
- for (var i = 0; i < results.length; ++i)
1513
- {
1332
+ if (results != null) {
1333
+ for (var i = 0; i < results.length; ++i) {
1334
var drive = { n: results[i].name, t: 1 };
1335
if (results[i].type == 'REMOVABLE') { drive.dt = 'removable'; } // TODO: See if this is USB/CDROM or something else, we can draw icons.
1336
response.dir.push(drive);
1337
}
1338
}
1519
- } else
1520
- {
1339
+ } else {
1340
// List all the files and folders in this path
1341
if (reqpath == '') { reqpath = '/'; }
1342
var results = null, xpath = obj.path.join(reqpath, '*');
1343
//if (process.platform == "win32") { xpath = xpath.split('/').join('\\'); }
1344
try { results = fs.readdirSync(xpath); } catch (e) { }
1526
- if (results != null)
1527
- {
1528
- for (var i = 0; i < results.length; ++i)
1529
- {
1530
- if ((results[i] != '.') && (results[i] != '..'))
1531
- {
1345
+ if (results != null) {
1346
+ for (var i = 0; i < results.length; ++i) {
1347
+ if ((results[i] != '.') && (results[i] != '..')) {
1348
var stat = null, p = obj.path.join(reqpath, results[i]);
1349
//if (process.platform == "win32") { p = p.split('/').join('\\'); }
1350
try { stat = fs.statSync(p); } catch (e) { } // TODO: Get file size/date
1535
- if ((stat != null) && (stat != undefined))
1536
- {
1537
- if (stat.isDirectory() == true)
1538
- {
1351
+ if ((stat != null) && (stat != undefined)) {
1352
+ if (stat.isDirectory() == true) {
1353
response.dir.push({ n: results[i], t: 2, d: stat.mtime });
1540
- } else
1541
- {
1354
+ } else {
1355
response.dir.push({ n: results[i], t: 3, s: stat.size, d: stat.mtime });
1356
}
1357
}
@@ -1550,19 +1363,16 @@ function getDirectoryInfo(reqpath)
1363
}
1364
1365
// Tunnel callback operations
1553
-function onTunnelUpgrade(response, s, head)
1554
-{
1366
+function onTunnelUpgrade(response, s, head) {
1367
this.s = s;
1368
s.httprequest = this;
1369
s.end = onTunnelClosed;
1370
s.tunnel = this;
1371
s.descriptorMetadata = "MeshAgent_relayTunnel";
1372
1561
- if (require('MeshAgent').idleTimeout != null)
1562
- {
1373
+ if (require('MeshAgent').idleTimeout != null) {
1374
s.setTimeout(require('MeshAgent').idleTimeout * 1000);
1564
- s.on('timeout', function ()
1565
- {
1375
+ s.on('timeout', function () {
1376
this.ping();
1377
this.setTimeout(require('MeshAgent').idleTimeout * 1000);
1378
});
@@ -1570,8 +1380,7 @@ function onTunnelUpgrade(response, s, head)
1380
1381
//sendConsoleText('onTunnelUpgrade - ' + this.tcpport + ' - ' + this.udpport);
1382
1573
- if (this.tcpport != null)
1574
- {
1383
+ if (this.tcpport != null) {
1384
// This is a TCP relay connection, pause now and try to connect to the target.
1385
s.pause();
1386
s.data = onTcpRelayServerTunnelData;
@@ -1581,14 +1390,12 @@ function onTunnelUpgrade(response, s, head)
1390
s.tcprelay.peerindex = this.index;
1391
1392
// Add the TCP session to the count and update the server
1584
- if (s.httprequest.userid != null)
1585
- {
1393
+ if (s.httprequest.userid != null) {
1394
if (tunnelUserCount.tcp[s.httprequest.userid] == null) { tunnelUserCount.tcp[s.httprequest.userid] = 1; } else { tunnelUserCount.tcp[s.httprequest.userid]++; }
1395
try { mesh.SendCommand({ action: 'sessions', type: 'tcp', value: tunnelUserCount.tcp }); } catch (e) { }
1396
broadcastSessionsToRegisteredApps();
1397
}
1590
- } if (this.udpport != null)
1591
- {
1398
+ } if (this.udpport != null) {
1399
// This is a UDP relay connection, get the UDP socket setup. // TODO: ***************
1400
s.data = onUdpRelayServerTunnelData;
1401
s.udprelay = require('dgram').createSocket({ type: 'udp4' });
@@ -1600,41 +1407,34 @@ function onTunnelUpgrade(response, s, head)
1407
s.udprelay.first = true;
1408
1409
// Add the UDP session to the count and update the server
1603
- if (s.httprequest.userid != null)
1604
- {
1410
+ if (s.httprequest.userid != null) {
1411
if (tunnelUserCount.udp[s.httprequest.userid] == null) { tunnelUserCount.udp[s.httprequest.userid] = 1; } else { tunnelUserCount.udp[s.httprequest.userid]++; }
1412
try { mesh.SendCommand({ action: 'sessions', type: 'udp', value: tunnelUserCount.tcp }); } catch (e) { }
1413
broadcastSessionsToRegisteredApps();
1414
}
1609
- } else
1610
- {
1415
+ } else {
1416
// This is a normal connect for KVM/Terminal/Files
1417
s.data = onTunnelData;
1418
}
1419
}
1420
1421
// Called when UDP relay data is received // TODO****
1617
-function onUdpRelayTargetTunnelConnect(data)
1618
-{
1422
+function onUdpRelayTargetTunnelConnect(data) {
1423
var peerTunnel = tunnels[this.peerindex];
1424
peerTunnel.s.write(data);
1425
}
1426
1427
// Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest)
1624
-function onUdpRelayServerTunnelData(data)
1625
-{
1626
- if (this.udprelay.first === true)
1627
- {
1428
+function onUdpRelayServerTunnelData(data) {
1429
+ if (this.udprelay.first === true) {
1430
delete this.udprelay.first; // Skip the first 'c' that is received.
1629
- } else
1630
- {
1431
+ } else {
1432
this.udprelay.send(data, parseInt(this.udprelay.udpport), this.udprelay.udpaddr ? this.udprelay.udpaddr : '127.0.0.1');
1433
}
1434
}
1435
1436
// Called when the TCP relay target is connected
1636
-function onTcpRelayTargetTunnelConnect()
1637
-{
1437
+function onTcpRelayTargetTunnelConnect() {
1438
var peerTunnel = tunnels[this.peerindex];
1439
this.pipe(peerTunnel.s); // Pipe Target --> Server
1440
peerTunnel.s.first = true;
@@ -1642,30 +1442,24 @@ function onTcpRelayTargetTunnelConnect()
1442
}
1443
1444
// Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest)
1645
-function onTcpRelayServerTunnelData(data)
1646
-{
1647
- if (this.first == true)
1648
- {
1445
+function onTcpRelayServerTunnelData(data) {
1446
+ if (this.first == true) {
1447
this.first = false;
1448
this.pipe(this.tcprelay, { dataTypeSkip: 1 }); // Pipe Server --> Target (don't pipe text type websocket frames)
1449
}
1450
}
1451
1654
-function onTunnelClosed()
1655
-{
1452
+function onTunnelClosed() {
1453
var tunnel = tunnels[this.httprequest.index];
1454
if (tunnel == null) return; // Stop duplicate calls.
1455
1456
// If this is a routing session, clean up and send the new session counts.
1660
- if (this.httprequest.userid != null)
1661
- {
1662
- if (this.httprequest.tcpport != null)
1663
- {
1457
+ if (this.httprequest.userid != null) {
1458
+ if (this.httprequest.tcpport != null) {
1459
if (tunnelUserCount.tcp[this.httprequest.userid] != null) { tunnelUserCount.tcp[this.httprequest.userid]--; if (tunnelUserCount.tcp[this.httprequest.userid] <= 0) { delete tunnelUserCount.tcp[this.httprequest.userid]; } }
1460
try { mesh.SendCommand({ action: 'sessions', type: 'tcp', value: tunnelUserCount.tcp }); } catch (e) { }
1461
broadcastSessionsToRegisteredApps();
1667
- } else if (this.httprequest.udpport != null)
1668
- {
1462
+ } else if (this.httprequest.udpport != null) {
1463
if (tunnelUserCount.udp[this.httprequest.userid] != null) { tunnelUserCount.udp[this.httprequest.userid]--; if (tunnelUserCount.udp[this.httprequest.userid] <= 0) { delete tunnelUserCount.udp[this.httprequest.userid]; } }
1464
try { mesh.SendCommand({ action: 'sessions', type: 'udp', value: tunnelUserCount.udp }); } catch (e) { }
1465
broadcastSessionsToRegisteredApps();
@@ -1673,8 +1467,7 @@ function onTunnelClosed()
1467
}
1468
1469
// Sent tunnel statistics to the server, only send this if compression was used.
1676
- if ((this.bytesSent_uncompressed) && (this.bytesSent_uncompressed.toString() != this.bytesSent_actual.toString()))
1677
- {
1470
+ if ((this.bytesSent_uncompressed) && (this.bytesSent_uncompressed.toString() != this.bytesSent_actual.toString())) {
1471
mesh.SendCommand({
1472
action: 'tunnelCloseStats',
1473
url: tunnel.url,
@@ -1707,8 +1500,7 @@ function onTunnelClosed()
1500
if (this.httprequest.downloadFile) { delete this.httprequest.downloadFile; }
1501
1502
// Clean up WebRTC
1710
- if (this.webrtc != null)
1711
- {
1503
+ if (this.webrtc != null) {
1504
if (this.webrtc.rtcchannel) { try { this.webrtc.rtcchannel.close(); } catch (e) { } this.webrtc.rtcchannel.removeAllListeners('data'); this.webrtc.rtcchannel.removeAllListeners('end'); delete this.webrtc.rtcchannel; }
1505
if (this.webrtc.websocket) { delete this.webrtc.websocket; }
1506
try { this.webrtc.close(); } catch (e) { }
@@ -1722,21 +1514,17 @@ function onTunnelClosed()
1514
this.removeAllListeners('data');
1515
}
1516
function onTunnelSendOk() { /*sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid);*/ }
1725
-function onTunnelData(data)
1726
-{
1517
+function onTunnelData(data) {
1518
//console.log("OnTunnelData");
1519
//sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
1520
1521
// If this is upload data, save it to file
1731
- if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123))
1732
- {
1522
+ if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123)) {
1523
// Save the data to file being uploaded.
1734
- if (data[0] == 0)
1735
- {
1524
+ if (data[0] == 0) {
1525
// If data starts with zero, skip the first byte. This is used to escape binary file data from JSON.
1526
try { fs.writeSync(this.httprequest.uploadFile, data, 1, data.length - 1); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1738
- } else
1739
- {
1527
+ } else {
1528
// If data does not start with zero, save as-is.
1529
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1530
}
@@ -1744,22 +1532,18 @@ function onTunnelData(data)
1532
return;
1533
}
1534
1747
- if (this.httprequest.state == 0)
1748
- {
1535
+ if (this.httprequest.state == 0) {
1536
// Check if this is a relay connection
1537
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ }
1538
}
1752
- else
1753
- {
1539
+ else {
1540
// Handle tunnel data
1755
- if (this.httprequest.protocol == 0)
1756
- { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
1541
+ if (this.httprequest.protocol == 0) { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
1542
// Take a look at the protocol
1543
if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; }
1544
this.httprequest.protocol = parseInt(data);
1545
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
1761
- if (this.httprequest.protocol == 10)
1762
- {
1546
+ if (this.httprequest.protocol == 10) {
1547
//
1548
// Basic file transfer
1549
//
@@ -1767,27 +1551,23 @@ function onTunnelData(data)
1551
if ((process.platform != 'win32') && (this.httprequest.xoptions.file.startsWith('/') == false)) { this.httprequest.xoptions.file = '/' + this.httprequest.xoptions.file; }
1552
try { stats = require('fs').statSync(this.httprequest.xoptions.file) } catch (e) { }
1553
try { if (stats) { this.httprequest.downloadFile = fs.createReadStream(this.httprequest.xoptions.file, { flags: 'rbN' }); } } catch (e) { }
1770
- if (this.httprequest.downloadFile)
1771
- {
1554
+ if (this.httprequest.downloadFile) {
1555
//sendConsoleText('BasicFileTransfer, ok, ' + this.httprequest.xoptions.file + ', ' + JSON.stringify(stats));
1556
this.write(JSON.stringify({ op: 'ok', size: stats.size }));
1557
this.httprequest.downloadFile.pipe(this);
1558
this.httprequest.downloadFile.end = function () { }
1776
- } else
1777
- {
1559
+ } else {
1560
//sendConsoleText('BasicFileTransfer, cancel, ' + this.httprequest.xoptions.file);
1561
this.write(JSON.stringify({ op: 'cancel' }));
1562
}
1563
}
1782
- else if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9))
1783
- {
1564
+ else if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6) || (this.httprequest.protocol == 8) || (this.httprequest.protocol == 9)) {
1565
//
1566
// Remote Terminal
1567
//
1568
1569
// Check user access rights for terminal
1789
- if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOTERMINAL) != 0)))
1790
- {
1570
+ if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOTERMINAL) != 0))) {
1571
// Disengage this tunnel, user does not have the rights to do this!!
1572
this.httprequest.protocol = 999999;
1573
this.httprequest.s.end();
@@ -1797,10 +1577,8 @@ function onTunnelData(data)
1577
1578
this.descriptorMetadata = "Remote Terminal";
1579
1800
- if (process.platform == 'win32')
1801
- {
1802
- if (!require('win-terminal').PowerShellCapable() && (this.httprequest.protocol == 6 || this.httprequest.protocol == 9))
1803
- {
1580
+ if (process.platform == 'win32') {
1581
+ if (!require('win-terminal').PowerShellCapable() && (this.httprequest.protocol == 6 || this.httprequest.protocol == 9)) {
1582
this.httprequest.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: 'PowerShell is not supported on this version of windows', msgid: 1 }));
1583
this.httprequest.s.end();
1584
return;
@@ -1812,28 +1590,24 @@ function onTunnelData(data)
1590
this.httprequest.tpromise.that = this;
1591
this.httprequest.tpromise.httprequest = this.httprequest;
1592
1815
- this.end = function ()
1816
- {
1593
+ this.end = function () {
1594
if (this.httprequest.tpromise._consent) { this.httprequest.tpromise._consent.close(); }
1595
if (this.httprequest.connectionPromise) { this.httprequest.connectionPromise._rej('Closed'); }
1596
1597
// Remove the terminal session to the count to update the server
1821
- if (this.httprequest.userid != null)
1822
- {
1598
+ if (this.httprequest.userid != null) {
1599
if (tunnelUserCount.terminal[this.httprequest.userid] != null) { tunnelUserCount.terminal[this.httprequest.userid]--; if (tunnelUserCount.terminal[this.httprequest.userid] <= 0) { delete tunnelUserCount.terminal[this.httprequest.userid]; } }
1600
try { mesh.SendCommand({ action: 'sessions', type: 'terminal', value: tunnelUserCount.terminal }); } catch (e) { }
1601
broadcastSessionsToRegisteredApps();
1602
}
1603
1828
- if (process.platform == 'win32')
1829
- {
1604
+ if (process.platform == 'win32') {
1605
// Unpipe the web socket
1606
this.unpipe(this.httprequest._term);
1607
if (this.httprequest._term) { this.httprequest._term.unpipe(this); }
1608
1609
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
1835
- if (this.rtcchannel)
1836
- {
1610
+ if (this.rtcchannel) {
1611
this.rtcchannel.unpipe(this.httprequest._term);
1612
if (this.httprequest._term) { this.httprequest._term.unpipe(this.rtcchannel); }
1613
}
@@ -1845,118 +1619,95 @@ function onTunnelData(data)
1619
};
1620
1621
// Perform User-Consent if needed.
1848
- if (this.httprequest.consent && (this.httprequest.consent & 16))
1849
- {
1622
+ if (this.httprequest.consent && (this.httprequest.consent & 16)) {
1623
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
1624
var consentMessage = this.httprequest.username + " requesting remote terminal access. Grant access?", consentTitle = 'MeshCentral';
1852
- if (this.httprequest.soptions != null)
1853
- {
1625
+ if (this.httprequest.soptions != null) {
1626
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
1627
if (this.httprequest.soptions.consentMsgTerminal != null) { consentMessage = this.httprequest.soptions.consentMsgTerminal.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
1628
}
1629
this.httprequest.tpromise._consent = require('message-box').create(consentTitle, consentMessage, 30);
1630
this.httprequest.tpromise._consent.retPromise = this.httprequest.tpromise;
1631
this.httprequest.tpromise._consent.then(
1860
- function ()
1861
- {
1632
+ function () {
1633
// Success
1634
MeshServerLogEx(27, null, "Local user accepted remote terminal request (" + this.retPromise.httprequest.remoteaddr + ")", this.retPromise.that.httprequest);
1635
this.retPromise.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null, msgid: 0 }));
1636
this.retPromise._consent = null;
1637
this.retPromise._res();
1638
},
1868
- function (e)
1869
- {
1639
+ function (e) {
1640
// Denied
1641
MeshServerLogEx(28, null, "Local user rejected remote terminal request (" + this.retPromise.that.httprequest.remoteaddr + ")", this.retPromise.that.httprequest);
1642
this.retPromise.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
1643
this.retPromise._rej(e.toString());
1644
});
1645
}
1876
- else
1877
- {
1646
+ else {
1647
// User-Consent is not required, so just resolve this promise
1648
this.httprequest.tpromise._res();
1649
}
1650
1651
1652
this.httprequest.tpromise.then(
1884
- function ()
1885
- {
1653
+ function () {
1654
this.httprequest.connectionPromise = new prom(function (res, rej) { this._res = res; this._rej = rej; });
1655
this.httprequest.connectionPromise.ws = this.that;
1656
1657
// Start Terminal
1890
- if (process.platform == 'win32')
1891
- {
1892
- try
1893
- {
1658
+ if (process.platform == 'win32') {
1659
+ try {
1660
var cols = 80, rows = 25;
1895
- if (this.httprequest.xoptions)
1896
- {
1661
+ if (this.httprequest.xoptions) {
1662
if (this.httprequest.xoptions.rows) { rows = this.httprequest.xoptions.rows; }
1663
if (this.httprequest.xoptions.cols) { cols = this.httprequest.xoptions.cols; }
1664
}
1665
1901
- if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6))
1902
- {
1666
+ if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6)) {
1667
// Admin Terminal
1904
- if (require('win-virtual-terminal').supported)
1905
- {
1668
+ if (require('win-virtual-terminal').supported) {
1669
// ConPTY PseudoTerminal
1670
// this.httprequest._term = require('win-virtual-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25);
1671
1672
// The above line is commented out, because there is a bug with ClosePseudoConsole() API, so this is the workaround
1673
this.httprequest._dispatcher = require('win-dispatcher').dispatch({ modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'), args: [cols, rows] } });
1674
this.httprequest._dispatcher.httprequest = this.httprequest;
1912
- this.httprequest._dispatcher.on('connection', function (c)
1913
- {
1914
- if (this.httprequest.connectionPromise.completed)
1915
- {
1675
+ this.httprequest._dispatcher.on('connection', function (c) {
1676
+ if (this.httprequest.connectionPromise.completed) {
1677
c.end();
1678
}
1918
- else
1919
- {
1679
+ else {
1680
this.httprequest.connectionPromise._res(c);
1681
}
1682
});
1683
}
1924
- else
1925
- {
1684
+ else {
1685
// Legacy Terminal
1686
this.httprequest.connectionPromise._res(require('win-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](cols, rows));
1687
}
1688
}
1930
- else
1931
- {
1689
+ else {
1690
// Logged in user
1691
var userPromise = require('user-sessions').enumerateUsers();
1692
userPromise.that = this;
1935
- userPromise.then(function (u)
1936
- {
1693
+ userPromise.then(function (u) {
1694
var that = this.that;
1938
- if (u.Active.length > 0)
1939
- {
1695
+ if (u.Active.length > 0) {
1696
var username = u.Active[0].Username;
1941
- if (require('win-virtual-terminal').supported)
1942
- {
1697
+ if (require('win-virtual-terminal').supported) {
1698
// ConPTY PseudoTerminal
1699
that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [cols, rows] } });
1700
}
1946
- else
1947
- {
1701
+ else {
1702
// Legacy Terminal
1703
that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [cols, rows] } });
1704
}
1705
that.httprequest._dispatcher.ws = that;
1952
- that.httprequest._dispatcher.on('connection', function (c)
1953
- {
1954
- if (this.ws.httprequest.connectionPromise.completed)
1955
- {
1706
+ that.httprequest._dispatcher.on('connection', function (c) {
1707
+ if (this.ws.httprequest.connectionPromise.completed) {
1708
c.end();
1709
}
1958
- else
1959
- {
1710
+ else {
1711
this.ws.httprequest.connectionPromise._res(c);
1712
}
1713
});
@@ -1964,70 +1715,58 @@ function onTunnelData(data)
1715
});
1716
}
1717
}
1967
- catch (e)
1968
- {
1718
+ catch (e) {
1719
this.httprequest.connectionPromise._rej('Failed to start remote terminal session, ' + e.toString());
1720
}
1721
}
1972
- else
1973
- {
1974
- try
1975
- {
1722
+ else {
1723
+ try {
1724
var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false;
1725
var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false;
1726
var login = process.platform == 'linux' ? '/bin/login' : '/usr/bin/login';
1727
1728
var env = { HISTCONTROL: 'ignoreboth' };
1981
- if (this.httprequest.xoptions)
1982
- {
1729
+ if (this.httprequest.xoptions) {
1730
if (this.httprequest.xoptions.rows) { env.LINES = ('' + this.httprequest.xoptions.rows); }
1731
if (this.httprequest.xoptions.cols) { env.COLUMNS = ('' + this.httprequest.xoptions.cols); }
1732
}
1733
var options = { type: childProcess.SpawnTypes.TERM, uid: (this.httprequest.protocol == 8) ? require('user-sessions').consoleUid() : null, env: env };
1987
- if (this.httprequest.xoptions && this.httprequest.xoptions.requireLogin)
1988
- {
1734
+ if (this.httprequest.xoptions && this.httprequest.xoptions.requireLogin) {
1735
if (!require('fs').existsSync(login)) { throw ('Unable to spawn login process'); }
1736
this.httprequest.connectionPromise._res(childProcess.execFile(login, ['login'], options)); // Start login shell
1737
}
1992
- else if (bash)
1993
- {
1738
+ else if (bash) {
1739
var p = childProcess.execFile(bash, ['bash'], options); // Start bash
1740
// Spaces at the beginning of lines are needed to hide commands from the command history
1741
if (process.platform == 'linux') { p.stdin.write(' alias ls=\'ls --color=auto\';clear\n'); }
1742
this.httprequest.connectionPromise._res(p);
1743
}
1999
- else if (sh)
2000
- {
1744
+ else if (sh) {
1745
var p = childProcess.execFile(sh, ['sh'], options); // Start sh
1746
// Spaces at the beginning of lines are needed to hide commands from the command history
1747
if (process.platform == 'linux') { p.stdin.write(' alias ls=\'ls --color=auto\';clear\n'); }
1748
this.httprequest.connectionPromise._res(p);
1749
}
2006
- else
2007
- {
1750
+ else {
1751
this.httprequest.connectionPromise._rej('Failed to start remote terminal session, no shell found');
1752
}
1753
}
2011
- catch (e)
2012
- {
1754
+ catch (e) {
1755
this.httprequest.connectionPromise._rej('Failed to start remote terminal session, ' + e.toString());
1756
}
1757
}
1758
1759
this.httprequest.connectionPromise.then(
2018
- function (term)
2019
- {
1760
+ function (term) {
1761
// SUCCESS
1762
var stdoutstream;
1763
var stdinstream;
2023
- if (process.platform == 'win32')
2024
- {
1764
+ if (process.platform == 'win32') {
1765
this.ws.httprequest._term = term;
1766
this.ws.httprequest._term.tunnel = this.ws;
1767
stdoutstream = stdinstream = term;
1768
}
2029
- else
2030
- {
1769
+ else {
1770
term.descriptorMetadata = 'Remote Terminal';
1771
this.ws.httprequest.process = term;
1772
this.ws.httprequest.process.tunnel = this.ws;
@@ -2046,49 +1785,42 @@ function onTunnelData(data)
1785
this.ws.pipe(stdinstream, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
1786
1787
// Add the terminal session to the count to update the server
2049
- if (this.ws.httprequest.userid != null)
2050
- {
1788
+ if (this.ws.httprequest.userid != null) {
1789
if (tunnelUserCount.terminal[this.ws.httprequest.userid] == null) { tunnelUserCount.terminal[this.ws.httprequest.userid] = 1; } else { tunnelUserCount.terminal[this.ws.httprequest.userid]++; }
1790
try { mesh.SendCommand({ action: 'sessions', type: 'terminal', value: tunnelUserCount.terminal }); } catch (e) { }
1791
broadcastSessionsToRegisteredApps();
1792
}
1793
1794
// Toast Notification, if required
2057
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 2))
2058
- {
1795
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 2)) {
1796
// User Notifications is required
1797
var notifyMessage = this.ws.httprequest.username + " started a remote terminal session.", notifyTitle = "MeshCentral";
2061
- if (this.ws.httprequest.soptions != null)
2062
- {
1798
+ if (this.ws.httprequest.soptions != null) {
1799
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
1800
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
1801
}
1802
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (e) { }
1803
}
1804
},
2069
- function (e)
2070
- {
1805
+ function (e) {
1806
// FAILED to connect terminal
1807
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
1808
this.ws.end();
1809
});
1810
},
2076
- function (e)
2077
- {
1811
+ function (e) {
1812
// DO NOT start terminal
1813
this.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
1814
this.that.end();
1815
});
1816
}
2083
- else if (this.httprequest.protocol == 2)
2084
- {
1817
+ else if (this.httprequest.protocol == 2) {
1818
//
1819
// Remote KVM
1820
//
1821
1822
// Check user access rights for desktop
2090
- if ((((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NODESKTOP) != 0)))
2091
- {
1823
+ if ((((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NODESKTOP) != 0))) {
1824
// Disengage this tunnel, user does not have the rights to do this!!
1825
this.httprequest.protocol = 999999;
1826
this.httprequest.s.end();
@@ -2114,8 +1846,7 @@ function onTunnelData(data)
1846
1847
// Send a metadata update to all desktop sessions
1848
var users = {};
2117
- if (this.httprequest.desktop.kvm.tunnels != null)
2118
- {
1849
+ if (this.httprequest.desktop.kvm.tunnels != null) {
1850
for (var i in this.httprequest.desktop.kvm.tunnels) { try { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } } catch (e) { } }
1851
for (var i in this.httprequest.desktop.kvm.tunnels) { try { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); } catch (e) { } }
1852
tunnelUserCount.desktop = users;
@@ -2123,8 +1854,7 @@ function onTunnelData(data)
1854
broadcastSessionsToRegisteredApps();
1855
}
1856
2126
- this.end = function ()
2127
- {
1857
+ this.end = function () {
1858
--this.desktop.kvm.connectionCount;
1859
1860
// Remove ourself from the list of remote desktop session
@@ -2133,8 +1863,7 @@ function onTunnelData(data)
1863
1864
// Send a metadata update to all desktop sessions
1865
var users = {};
2136
- if (this.httprequest.desktop.kvm.tunnels != null)
2137
- {
1866
+ if (this.httprequest.desktop.kvm.tunnels != null) {
1867
for (var i in this.httprequest.desktop.kvm.tunnels) { try { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } } catch (e) { } }
1868
for (var i in this.httprequest.desktop.kvm.tunnels) { try { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); } catch (e) { } }
1869
tunnelUserCount.desktop = users;
@@ -2143,18 +1872,15 @@ function onTunnelData(data)
1872
}
1873
1874
// Unpipe the web socket
2146
- try
2147
- {
1875
+ try {
1876
this.unpipe(this.httprequest.desktop.kvm);
1877
this.httprequest.desktop.kvm.unpipe(this);
1878
}
1879
catch (e) { }
1880
1881
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
2154
- if (this.rtcchannel)
2155
- {
2156
- try
2157
- {
1882
+ if (this.rtcchannel) {
1883
+ try {
1884
this.rtcchannel.unpipe(this.httprequest.desktop.kvm);
1885
this.httprequest.desktop.kvm.unpipe(this.rtcchannel);
1886
}
@@ -2164,35 +1890,28 @@ function onTunnelData(data)
1890
// Place wallpaper back if needed
1891
// TODO
1892
2167
- if (this.desktop.kvm.connectionCount == 0)
2168
- {
1893
+ if (this.desktop.kvm.connectionCount == 0) {
1894
// Display a toast message. This may not be supported on all platforms.
1895
// try { require('toaster').Toast('MeshCentral', 'Remote Desktop Control Ended.'); } catch (e) { }
1896
1897
this.httprequest.desktop.kvm.end();
2173
- if (this.httprequest.desktop.kvm.connectionBar)
2174
- {
1898
+ if (this.httprequest.desktop.kvm.connectionBar) {
1899
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
1900
this.httprequest.desktop.kvm.connectionBar.close();
1901
this.httprequest.desktop.kvm.connectionBar = null;
1902
}
2179
- } else
2180
- {
2181
- for (var i in this.httprequest.desktop.kvm.users)
2182
- {
2183
- if ((this.httprequest.desktop.kvm.users[i] == this.httprequest.username) && this.httprequest.desktop.kvm.connectionBar)
2184
- {
1903
+ } else {
1904
+ for (var i in this.httprequest.desktop.kvm.users) {
1905
+ if ((this.httprequest.desktop.kvm.users[i] == this.httprequest.username) && this.httprequest.desktop.kvm.connectionBar) {
1906
for (var j in this.httprequest.desktop.kvm.rusers) { if (this.httprequest.desktop.kvm.rusers[j] == this.httprequest.realname) { this.httprequest.desktop.kvm.rusers.splice(j, 1); break; } }
1907
this.httprequest.desktop.kvm.users.splice(i, 1);
1908
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
1909
this.httprequest.desktop.kvm.connectionBar.close();
1910
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.users.join(', ')).replace('{1}', this.httprequest.desktop.kvm.rusers.join(', ')), require('MeshAgent')._tsid);
1911
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
2191
- this.httprequest.desktop.kvm.connectionBar.on('close', function ()
2192
- {
1912
+ this.httprequest.desktop.kvm.connectionBar.on('close', function () {
1913
MeshServerLogEx(29, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
2194
- for (var i in this.httprequest.desktop.kvm._pipedStreams)
2195
- {
1914
+ for (var i in this.httprequest.desktop.kvm._pipedStreams) {
1915
this.httprequest.desktop.kvm._pipedStreams[i].end();
1916
}
1917
this.httprequest.desktop.kvm.end();
@@ -2202,40 +1921,34 @@ function onTunnelData(data)
1921
}
1922
}
1923
};
2205
- if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount'))
2206
- {
1924
+ if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount')) {
1925
this.httprequest.desktop.kvm.connectionCount++;
1926
this.httprequest.desktop.kvm.rusers.push(this.httprequest.realname);
1927
this.httprequest.desktop.kvm.users.push(this.httprequest.username);
1928
this.httprequest.desktop.kvm.rusers.sort();
1929
this.httprequest.desktop.kvm.users.sort();
2212
- } else
2213
- {
1930
+ } else {
1931
this.httprequest.desktop.kvm.connectionCount = 1;
1932
this.httprequest.desktop.kvm.rusers = [this.httprequest.realname];
1933
this.httprequest.desktop.kvm.users = [this.httprequest.username];
1934
}
1935
2219
- if ((this.httprequest.rights == 0xFFFFFFFF) || (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) != 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)))
2220
- {
1936
+ if ((this.httprequest.rights == 0xFFFFFFFF) || (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) != 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0))) {
1937
// If we have remote control rights, pipe the KVM input
1938
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. Pipe the Browser --> KVM input.
2223
- } else
2224
- {
1939
+ } else {
1940
// We need to only pipe non-mouse & non-keyboard inputs.
1941
//sendConsoleText('Warning: No Remote Desktop Input Rights.');
1942
// TODO!!!
1943
}
1944
1945
// Perform notification if needed. Toast messages may not be supported on all platforms.
2231
- if (this.httprequest.consent && (this.httprequest.consent & 8))
2232
- {
1946
+ if (this.httprequest.consent && (this.httprequest.consent & 8)) {
1947
// User Consent Prompt is required
1948
// Send a console message back using the console channel, "\n" is supported.
1949
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
1950
var consentMessage = this.httprequest.realname + " requesting remote desktop access. Grant access?", consentTitle = 'MeshCentral';
2237
- if (this.httprequest.soptions != null)
2238
- {
1951
+ if (this.httprequest.soptions != null) {
1952
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
1953
if (this.httprequest.soptions.consentMsgDesktop != null) { consentMessage = this.httprequest.soptions.consentMsgDesktop.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
1954
}
@@ -2245,51 +1958,40 @@ function onTunnelData(data)
1958
this._consentpromise = pr;
1959
this.prependOnceListener('end', function () { if (this._consentpromise && this._consentpromise.close) { this._consentpromise.close(); } });
1960
pr.then(
2248
- function ()
2249
- {
1961
+ function () {
1962
// Success
1963
this.ws._consentpromise = null;
1964
MeshServerLogEx(30, null, "Starting remote desktop after local user accepted (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
1965
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null, msgid: 0 }));
2254
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1))
2255
- {
1966
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1)) {
1967
// User Notifications is required
1968
var notifyMessage = this.ws.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
2258
- if (this.ws.httprequest.soptions != null)
2259
- {
1969
+ if (this.ws.httprequest.soptions != null) {
1970
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
1971
if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
1972
}
1973
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (e) { }
1974
}
2265
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 0x40))
2266
- {
1975
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 0x40)) {
1976
// Connection Bar is required
2268
- if (this.ws.httprequest.desktop.kvm.connectionBar)
2269
- {
1977
+ if (this.ws.httprequest.desktop.kvm.connectionBar) {
1978
this.ws.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
1979
this.ws.httprequest.desktop.kvm.connectionBar.close();
1980
}
2273
- try
2274
- {
1981
+ try {
1982
this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replace('{0}', this.ws.httprequest.desktop.kvm.users.join(', ')).replace('{1}', this.ws.httprequest.desktop.kvm.rusers.join(', ')), require('MeshAgent')._tsid);
1983
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
1984
}
2278
- catch (e)
2279
- {
2280
- if (process.platform != 'darwin')
2281
- {
1985
+ catch (e) {
1986
+ if (process.platform != 'darwin') {
1987
MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or Not Supported (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
1988
}
1989
}
2285
- if (this.ws.httprequest.desktop.kvm.connectionBar)
2286
- {
1990
+ if (this.ws.httprequest.desktop.kvm.connectionBar) {
1991
this.ws.httprequest.desktop.kvm.connectionBar.httprequest = this.ws.httprequest;
2288
- this.ws.httprequest.desktop.kvm.connectionBar.on('close', function ()
2289
- {
1992
+ this.ws.httprequest.desktop.kvm.connectionBar.on('close', function () {
1993
MeshServerLogEx(33, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
2291
- for (var i in this.httprequest.desktop.kvm._pipedStreams)
2292
- {
1994
+ for (var i in this.httprequest.desktop.kvm._pipedStreams) {
1995
this.httprequest.desktop.kvm._pipedStreams[i].end();
1996
}
1997
this.httprequest.desktop.kvm.end();
@@ -2299,56 +2001,44 @@ function onTunnelData(data)
2001
this.ws.httprequest.desktop.kvm.pipe(this.ws, { dataTypeSkip: 1 });
2002
this.ws.resume();
2003
},
2302
- function (e)
2303
- {
2004
+ function (e) {
2005
// User Consent Denied/Failed
2006
this.ws._consentpromise = null;
2007
MeshServerLogEx(34, null, "Failed to start remote desktop after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2008
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
2009
});
2309
- } else
2310
- {
2010
+ } else {
2011
// User Consent Prompt is not required
2312
- if (this.httprequest.consent && (this.httprequest.consent & 1))
2313
- {
2012
+ if (this.httprequest.consent && (this.httprequest.consent & 1)) {
2013
// User Notifications is required
2014
MeshServerLogEx(35, null, "Started remote desktop with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2015
var notifyMessage = this.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
2317
- if (this.httprequest.soptions != null)
2318
- {
2016
+ if (this.httprequest.soptions != null) {
2017
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
2018
if (this.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2019
}
2020
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (e) { }
2323
- } else
2324
- {
2021
+ } else {
2022
MeshServerLogEx(36, null, "Started remote desktop without notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2023
}
2327
- if (this.httprequest.consent && (this.httprequest.consent & 0x40))
2328
- {
2024
+ if (this.httprequest.consent && (this.httprequest.consent & 0x40)) {
2025
// Connection Bar is required
2330
- if (this.httprequest.desktop.kvm.connectionBar)
2331
- {
2026
+ if (this.httprequest.desktop.kvm.connectionBar) {
2027
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
2028
this.httprequest.desktop.kvm.connectionBar.close();
2029
}
2335
- try
2336
- {
2030
+ try {
2031
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replace('{1}', this.httprequest.desktop.kvm.users.join(', ')), require('MeshAgent')._tsid);
2032
MeshServerLogEx(37, null, "Remote Desktop Connection Bar Activated/Updated (" + this.httprequest.remoteaddr + ")", this.httprequest);
2033
}
2340
- catch (e)
2341
- {
2034
+ catch (e) {
2035
MeshServerLogEx(38, null, "Remote Desktop Connection Bar Failed or not Supported (" + this.httprequest.remoteaddr + ")", this.httprequest);
2036
}
2344
- if (this.httprequest.desktop.kvm.connectionBar)
2345
- {
2037
+ if (this.httprequest.desktop.kvm.connectionBar) {
2038
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
2347
- this.httprequest.desktop.kvm.connectionBar.on('close', function ()
2348
- {
2039
+ this.httprequest.desktop.kvm.connectionBar.on('close', function () {
2040
MeshServerLogEx(39, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
2350
- for (var i in this.httprequest.desktop.kvm._pipedStreams)
2351
- {
2041
+ for (var i in this.httprequest.desktop.kvm._pipedStreams) {
2042
this.httprequest.desktop.kvm._pipedStreams[i].end();
2043
}
2044
this.httprequest.desktop.kvm.end();
@@ -2362,15 +2052,13 @@ function onTunnelData(data)
2052
this.on('data', onTunnelControlData);
2053
//this.write('MeshCore KVM Hello!1');
2054
2365
- } else if (this.httprequest.protocol == 5)
2366
- {
2055
+ } else if (this.httprequest.protocol == 5) {
2056
//
2057
// Remote Files
2058
//
2059
2060
// Check user access rights for files
2372
- if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOFILES) != 0)))
2373
- {
2061
+ if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOFILES) != 0))) {
2062
// Disengage this tunnel, user does not have the rights to do this!!
2063
this.httprequest.protocol = 999999;
2064
this.httprequest.s.end();
@@ -2381,18 +2069,15 @@ function onTunnelData(data)
2069
this.descriptorMetadata = "Remote Files";
2070
2071
// Add the files session to the count to update the server
2384
- if (this.httprequest.userid != null)
2385
- {
2072
+ if (this.httprequest.userid != null) {
2073
if (tunnelUserCount.files[this.httprequest.userid] == null) { tunnelUserCount.files[this.httprequest.userid] = 1; } else { tunnelUserCount.files[this.httprequest.userid]++; }
2074
try { mesh.SendCommand({ action: 'sessions', type: 'files', value: tunnelUserCount.files }); } catch (e) { }
2075
broadcastSessionsToRegisteredApps();
2076
}
2077
2391
- this.end = function ()
2392
- {
2078
+ this.end = function () {
2079
// Remove the files session from the count to update the server
2394
- if (this.httprequest.userid != null)
2395
- {
2080
+ if (this.httprequest.userid != null) {
2081
if (tunnelUserCount.files[this.httprequest.userid] != null) { tunnelUserCount.files[this.httprequest.userid]--; if (tunnelUserCount.files[this.httprequest.userid] <= 0) { delete tunnelUserCount.files[this.httprequest.userid]; } }
2082
try { mesh.SendCommand({ action: 'sessions', type: 'files', value: tunnelUserCount.files }); } catch (e) { }
2083
broadcastSessionsToRegisteredApps();
@@ -2400,14 +2085,12 @@ function onTunnelData(data)
2085
};
2086
2087
// Perform notification if needed. Toast messages may not be supported on all platforms.
2403
- if (this.httprequest.consent && (this.httprequest.consent & 32))
2404
- {
2088
+ if (this.httprequest.consent && (this.httprequest.consent & 32)) {
2089
// User Consent Prompt is required
2090
// Send a console message back using the console channel, "\n" is supported.
2091
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
2092
var consentMessage = this.httprequest.realname + " requesting remote file Access. Grant access?", consentTitle = 'MeshCentral';
2409
- if (this.httprequest.soptions != null)
2410
- {
2093
+ if (this.httprequest.soptions != null) {
2094
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
2095
if (this.httprequest.soptions.consentMsgFiles != null) { consentMessage = this.httprequest.soptions.consentMsgFiles.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2096
}
@@ -2417,18 +2100,15 @@ function onTunnelData(data)
2100
this._consentpromise = pr;
2101
this.prependOnceListener('end', function () { if (this._consentpromise && this._consentpromise.close) { this._consentpromise.close(); } });
2102
pr.then(
2420
- function ()
2421
- {
2103
+ function () {
2104
// Success
2105
this.ws._consentpromise = null;
2106
MeshServerLogEx(40, null, "Starting remote files after local user accepted (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2107
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null }));
2426
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4))
2427
- {
2108
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4)) {
2109
// User Notifications is required
2110
var notifyMessage = this.ws.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
2430
- if (this.ws.httprequest.soptions != null)
2431
- {
2111
+ if (this.ws.httprequest.soptions != null) {
2112
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
2113
if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
2114
}
@@ -2436,29 +2116,24 @@ function onTunnelData(data)
2116
}
2117
this.ws.resume();
2118
},
2439
- function (e)
2440
- {
2119
+ function (e) {
2120
// User Consent Denied/Failed
2121
this.ws._consentpromise = null;
2122
MeshServerLogEx(41, null, "Failed to start remote files after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2123
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
2124
});
2446
- } else
2447
- {
2125
+ } else {
2126
// User Consent Prompt is not required
2449
- if (this.httprequest.consent && (this.httprequest.consent & 4))
2450
- {
2127
+ if (this.httprequest.consent && (this.httprequest.consent & 4)) {
2128
// User Notifications is required
2129
MeshServerLogEx(42, null, "Started remote files with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2130
var notifyMessage = this.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
2454
- if (this.httprequest.soptions != null)
2455
- {
2131
+ if (this.httprequest.soptions != null) {
2132
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
2133
if (this.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.httprequest.soptions.notifyMsgFiles.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2134
}
2135
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (e) { }
2460
- } else
2461
- {
2136
+ } else {
2137
MeshServerLogEx(43, null, "Started remote files without notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2138
}
2139
this.resume();
@@ -2467,23 +2142,18 @@ function onTunnelData(data)
2142
// Setup files
2143
// NOP
2144
}
2470
- } else if (this.httprequest.protocol == 1)
2471
- {
2145
+ } else if (this.httprequest.protocol == 1) {
2146
// Send data into terminal stdin
2147
//this.write(data); // Echo back the keys (Does not seem to be a good idea)
2474
- } else if (this.httprequest.protocol == 2)
2475
- {
2148
+ } else if (this.httprequest.protocol == 2) {
2149
// Send data into remote desktop
2477
- if (this.httprequest.desktop.state == 0)
2478
- {
2150
+ if (this.httprequest.desktop.state == 0) {
2151
this.write(Buffer.from(String.fromCharCode(0x11, 0xFE, 0x00, 0x00, 0x4D, 0x45, 0x53, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02)));
2152
this.httprequest.desktop.state = 1;
2481
- } else
2482
- {
2153
+ } else {
2154
this.httprequest.desktop.write(data);
2155
}
2485
- } else if (this.httprequest.protocol == 5)
2486
- {
2156
+ } else if (this.httprequest.protocol == 5) {
2157
// Process files commands
2158
var cmd = null;
2159
try { cmd = JSON.parse(data); } catch (e) { };
@@ -2494,8 +2164,7 @@ function onTunnelData(data)
2164
2165
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
2166
//console.log(objToString(cmd, 0, ' '));
2497
- switch (cmd.action)
2498
- {
2167
+ switch (cmd.action) {
2168
case 'ls': {
2169
/*
2170
// Close the watcher if required
@@ -2532,20 +2201,15 @@ function onTunnelData(data)
2201
}
2202
case 'rm': {
2203
// Delete, possibly recursive delete
2535
- for (var i in cmd.delfiles)
2536
- {
2204
+ for (var i in cmd.delfiles) {
2205
var p = obj.path.join(cmd.path, cmd.delfiles[i]), delcount = 0;
2206
try { delcount = deleteFolderRecursive(p, cmd.rec); } catch (e) { }
2539
- if ((delcount == 1) && !cmd.rec)
2540
- {
2207
+ if ((delcount == 1) && !cmd.rec) {
2208
MeshServerLogEx(45, [p], "Delete: \"" + p + "\"", this.httprequest);
2542
- } else
2543
- {
2544
- if (cmd.rec)
2545
- {
2209
+ } else {
2210
+ if (cmd.rec) {
2211
MeshServerLogEx(46, [p, delcount], "Delete recursive: \"" + p + "\", " + delcount + " element(s) removed", this.httprequest);
2547
- } else
2548
- {
2212
+ } else {
2213
MeshServerLogEx(47, [p, delcount], "Delete: \"" + p + "\", " + delcount + " element(s) removed", this.httprequest);
2214
}
2215
}
@@ -2555,11 +2219,9 @@ function onTunnelData(data)
2219
case 'markcoredump': {
2220
// If we are asking for the coredump file, set the right path.
2221
var coreDumpPath = null;
2558
- if (process.platform == 'win32')
2559
- {
2222
+ if (process.platform == 'win32') {
2223
if (fs.existsSync(process.coreDumpLocation)) { coreDumpPath = process.coreDumpLocation; }
2561
- } else
2562
- {
2224
+ } else {
2225
if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { coreDumpPath = process.cwd() + 'core'; }
2226
}
2227
if (coreDumpPath != null) { db.Put('CoreDumpTime', require('fs').statSync(coreDumpPath).mtime); }
@@ -2596,15 +2258,11 @@ function onTunnelData(data)
2258
{
2259
// Download a file
2260
var sendNextBlock = 0;
2599
- if (cmd.sub == 'start')
2600
- { // Setup the download
2601
- if ((cmd.path == null) && (cmd.ask == 'coredump'))
2602
- { // If we are asking for the coredump file, set the right path.
2603
- if (process.platform == 'win32')
2604
- {
2261
+ if (cmd.sub == 'start') { // Setup the download
2262
+ if ((cmd.path == null) && (cmd.ask == 'coredump')) { // If we are asking for the coredump file, set the right path.
2263
+ if (process.platform == 'win32') {
2264
if (fs.existsSync(process.coreDumpLocation)) { cmd.path = process.coreDumpLocation; }
2606
- } else
2607
- {
2265
+ } else {
2266
if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { cmd.path = process.cwd() + 'core'; }
2267
}
2268
}
@@ -2613,13 +2271,11 @@ function onTunnelData(data)
2271
this.filedownload = { id: cmd.id, path: cmd.path, ptr: 0 }
2272
try { this.filedownload.f = fs.openSync(this.filedownload.path, 'rbN'); } catch (e) { this.write({ action: 'download', sub: 'cancel', id: this.filedownload.id }); delete this.filedownload; }
2273
if (this.filedownload) { this.write({ action: 'download', sub: 'start', id: cmd.id }); }
2616
- } else if ((this.filedownload != null) && (cmd.id == this.filedownload.id))
2617
- { // Download commands
2274
+ } else if ((this.filedownload != null) && (cmd.id == this.filedownload.id)) { // Download commands
2275
if (cmd.sub == 'startack') { sendNextBlock = ((typeof cmd.ack == 'number') ? cmd.ack : 8); } else if (cmd.sub == 'stop') { delete this.filedownload; } else if (cmd.sub == 'ack') { sendNextBlock = 1; }
2276
}
2277
// Send the next download block(s)
2621
- while (sendNextBlock > 0)
2622
- {
2278
+ while (sendNextBlock > 0) {
2279
sendNextBlock--;
2280
var buf = Buffer.alloc(16384);
2281
var len = fs.readSync(this.filedownload.f, buf, 4, 16380, null);
@@ -2645,8 +2301,7 @@ function onTunnelData(data)
2301
case 'uploaddone':
2302
{
2303
// Indicates that an upload is done
2648
- if (this.httprequest.uploadFile)
2649
- {
2304
+ if (this.httprequest.uploadFile) {
2305
fs.closeSync(this.httprequest.uploadFile);
2306
this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
2307
delete this.httprequest.uploadFile;
@@ -2658,8 +2313,7 @@ function onTunnelData(data)
2313
case 'uploadcancel':
2314
{
2315
// Indicates that an upload is canceled
2661
- if (this.httprequest.uploadFile)
2662
- {
2316
+ if (this.httprequest.uploadFile) {
2317
fs.closeSync(this.httprequest.uploadFile);
2318
fs.unlinkSync(this.httprequest.uploadFilePath);
2319
this.write(Buffer.from(JSON.stringify({ action: 'uploadcancel', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
@@ -2672,8 +2326,7 @@ function onTunnelData(data)
2326
case 'copy':
2327
{
2328
// Copy a bunch of files from scpath to dspath
2675
- for (var i in cmd.names)
2676
- {
2329
+ for (var i in cmd.names) {
2330
var sc = obj.path.join(cmd.scpath, cmd.names[i]), ds = obj.path.join(cmd.dspath, cmd.names[i]);
2331
MeshServerLogEx(51, [sc, ds], 'Copy: \"' + sc + '\" to \"' + ds + '\"', this.httprequest);
2332
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
@@ -2683,8 +2336,7 @@ function onTunnelData(data)
2336
case 'move':
2337
{
2338
// Move a bunch of files from scpath to dspath
2686
- for (var i in cmd.names)
2687
- {
2339
+ for (var i in cmd.names) {
2340
var sc = obj.path.join(cmd.scpath, cmd.names[i]), ds = obj.path.join(cmd.dspath, cmd.names[i]);
2341
MeshServerLogEx(52, [sc, ds], 'Move: \"' + sc + '\" to \"' + ds + '\"', this.httprequest);
2342
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
@@ -2707,8 +2359,7 @@ function onTunnelData(data)
2359
delete this.zipcancel;
2360
var out = require('fs').createWriteStream(ofile, { flags: 'wb' });
2361
out.xws = this;
2710
- out.on('close', function ()
2711
- {
2362
+ out.on('close', function () {
2363
this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: null })));
2364
this.xws.write(Buffer.from(JSON.stringify({ action: 'refresh' })));
2365
if (this.xws.zipcancel === true) { fs.unlinkSync(this.xws.zipfile); } // Delete the complete file.
@@ -2730,16 +2381,14 @@ function onTunnelData(data)
2381
// Unknown action, ignore it.
2382
break;
2383
}
2733
- } else if (this.httprequest.protocol == 7)
2734
- { // Plugin data exchange
2384
+ } else if (this.httprequest.protocol == 7) { // Plugin data exchange
2385
var cmd = null;
2386
try { cmd = JSON.parse(data); } catch (e) { };
2387
if (cmd == null) { return; }
2388
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { onTunnelControlData(cmd, this); return; } // If this is control data, handle it now.
2389
if (cmd.action == undefined) return;
2390
2741
- switch (cmd.action)
2742
- {
2391
+ switch (cmd.action) {
2392
case 'plugin': {
2393
try { require(cmd.plugin).consoleaction(cmd, null, null, this); } catch (e) { throw e; }
2394
break;
@@ -2755,21 +2404,15 @@ function onTunnelData(data)
2404
}
2405
2406
// Delete a directory with a files and directories within it
2758
-function deleteFolderRecursive(path, rec)
2759
-{
2407
+function deleteFolderRecursive(path, rec) {
2408
var count = 0;
2761
- if (fs.existsSync(path))
2762
- {
2763
- if (rec == true)
2764
- {
2765
- fs.readdirSync(obj.path.join(path, '*')).forEach(function (file, index)
2766
- {
2409
+ if (fs.existsSync(path)) {
2410
+ if (rec == true) {
2411
+ fs.readdirSync(obj.path.join(path, '*')).forEach(function (file, index) {
2412
var curPath = obj.path.join(path, file);
2768
- if (fs.statSync(curPath).isDirectory())
2769
- { // recurse
2413
+ if (fs.statSync(curPath).isDirectory()) { // recurse
2414
count += deleteFolderRecursive(curPath, true);
2771
- } else
2772
- { // delete file
2415
+ } else { // delete file
2416
fs.unlinkSync(curPath);
2417
count++;
2418
}
@@ -2782,13 +2425,11 @@ function deleteFolderRecursive(path, rec)
2425
}
2426
2427
// Called when receiving control data on WebRTC
2785
-function onTunnelWebRTCControlData(data)
2786
-{
2428
+function onTunnelWebRTCControlData(data) {
2429
if (typeof data != 'string') return;
2430
var obj;
2431
try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON on WebRTC: ' + data); return; }
2790
- if (obj.type == 'close')
2791
- {
2432
+ if (obj.type == 'close') {
2433
//sendConsoleText('Tunnel #' + this.xrtc.websocket.tunnel.index + ' WebRTC control close');
2434
try { this.close(); } catch (e) { }
2435
try { this.xrtc.close(); } catch (e) { }
@@ -2796,8 +2437,7 @@ function onTunnelWebRTCControlData(data)
2437
}
2438
2439
// Called when receiving control data on websocket
2799
-function onTunnelControlData(data, ws)
2800
-{
2440
+function onTunnelControlData(data, ws) {
2441
var obj;
2442
if (ws == null) { ws = this; }
2443
if (typeof data == 'string') { try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON: ' + data); return; } }
@@ -2805,16 +2445,12 @@ function onTunnelControlData(data, ws)
2445
//sendConsoleText('onTunnelControlData(' + ws.httprequest.protocol + '): ' + JSON.stringify(data));
2446
//console.log('onTunnelControlData: ' + JSON.stringify(data));
2447
2808
- if (obj.action)
2809
- {
2810
- switch (obj.action)
2811
- {
2448
+ if (obj.action) {
2449
+ switch (obj.action) {
2450
case 'lock': {
2451
// Lock the current user out of the desktop
2814
- try
2815
- {
2816
- if (process.platform == 'win32')
2817
- {
2452
+ try {
2453
+ if (process.platform == 'win32') {
2454
MeshServerLogEx(53, null, "Locking remote user out of desktop", ws.httprequest);
2455
var child = require('child_process');
2456
child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'RunDll32.exe user32.dll,LockWorkStation'], { type: 1 });
@@ -2829,8 +2465,7 @@ function onTunnelControlData(data, ws)
2465
return;
2466
}
2467
2832
- switch (obj.type)
2833
- {
2468
+ switch (obj.type) {
2469
case 'options': {
2470
// These are additional connection options passed in the control channel.
2471
//sendConsoleText('options: ' + JSON.stringify(obj));
@@ -2850,13 +2485,11 @@ function onTunnelControlData(data, ws)
2485
}
2486
case 'termsize': {
2487
// Indicates a change in terminal size
2853
- if (process.platform == 'win32')
2854
- {
2488
+ if (process.platform == 'win32') {
2489
if (ws.httprequest._dispatcher == null) return;
2490
//sendConsoleText('Win32-TermSize: ' + obj.cols + 'x' + obj.rows);
2491
if (ws.httprequest._dispatcher.invoke) { ws.httprequest._dispatcher.invoke('resizeTerminal', [obj.cols, obj.rows]); }
2858
- } else
2859
- {
2492
+ } else {
2493
if (ws.httprequest.process == null || ws.httprequest.process.pty == 0) return;
2494
//sendConsoleText('Linux Resize: ' + obj.cols + 'x' + obj.rows);
2495
@@ -2865,23 +2498,18 @@ function onTunnelControlData(data, ws)
2498
break;
2499
}
2500
case 'webrtc0': { // Browser indicates we can start WebRTC switch-over.
2868
- if (ws.httprequest.protocol == 1)
2869
- { // Terminal
2501
+ if (ws.httprequest.protocol == 1) { // Terminal
2502
// This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket
2871
- if (process.platform == 'win32')
2872
- {
2503
+ if (process.platform == 'win32') {
2504
ws.httprequest._term.unpipe(ws);
2874
- } else
2875
- {
2505
+ } else {
2506
ws.httprequest.process.stdout.unpipe(ws);
2507
ws.httprequest.process.stderr.unpipe(ws);
2508
}
2879
- } else if (ws.httprequest.protocol == 2)
2880
- { // Desktop
2509
+ } else if (ws.httprequest.protocol == 2) { // Desktop
2510
// This is a KVM data stream, unpipe the KVM now and indicate to the other side that KVM data will no longer be received over WebSocket
2511
ws.httprequest.desktop.kvm.unpipe(ws);
2883
- } else
2884
- {
2512
+ } else {
2513
// Switch things around so all WebRTC data goes to onTunnelData().
2514
ws.rtcchannel.httprequest = ws.httprequest;
2515
ws.rtcchannel.removeAllListeners('data');
@@ -2891,21 +2519,17 @@ function onTunnelControlData(data, ws)
2519
break;
2520
}
2521
case 'webrtc1': {
2894
- if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6))
2895
- { // Terminal
2522
+ if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
2523
// Switch the user input from websocket to webrtc at this point.
2897
- if (process.platform == 'win32')
2898
- {
2524
+ if (process.platform == 'win32') {
2525
ws.unpipe(ws.httprequest._term);
2526
ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2901
- } else
2902
- {
2527
+ } else {
2528
ws.unpipe(ws.httprequest.process.stdin);
2529
ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2530
}
2531
ws.resume(); // Resume the websocket to keep receiving control data
2907
- } else if (ws.httprequest.protocol == 2)
2908
- { // Desktop
2532
+ } else if (ws.httprequest.protocol == 2) { // Desktop
2533
// Switch the user input from websocket to webrtc at this point.
2534
ws.unpipe(ws.httprequest.desktop.kvm);
2535
try { ws.webrtc.rtcchannel.pipe(ws.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); } catch (e) { sendConsoleText('EX2'); } // 0 = Binary, 1 = Text.
@@ -2916,18 +2540,14 @@ function onTunnelControlData(data, ws)
2540
}
2541
case 'webrtc2': {
2542
// Other side received websocket end of data marker, start sending data on WebRTC channel
2919
- if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6))
2920
- { // Terminal
2921
- if (process.platform == 'win32')
2922
- {
2543
+ if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
2544
+ if (process.platform == 'win32') {
2545
ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2924
- } else
2925
- {
2546
+ } else {
2547
ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2548
ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2549
}
2929
- } else if (ws.httprequest.protocol == 2)
2930
- { // Desktop
2550
+ } else if (ws.httprequest.protocol == 2) { // Desktop
2551
ws.httprequest.desktop.kvm.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2552
}
2553
break;
@@ -2939,8 +2559,7 @@ function onTunnelControlData(data, ws)
2559
ws.webrtc.websocket = ws;
2560
ws.webrtc.on('connected', function () { /*sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC connected');*/ });
2561
ws.webrtc.on('disconnected', function () { /*sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC disconnected');*/ });
2942
- ws.webrtc.on('dataChannel', function (rtcchannel)
2943
- {
2562
+ ws.webrtc.on('dataChannel', function (rtcchannel) {
2563
//sendConsoleText('WebRTC Datachannel open, protocol: ' + this.websocket.httprequest.protocol);
2564
rtcchannel.maxFragmentSize = 32768;
2565
rtcchannel.xrtc = this;
@@ -2948,14 +2567,11 @@ function onTunnelControlData(data, ws)
2567
this.rtcchannel = rtcchannel;
2568
this.websocket.rtcchannel = rtcchannel;
2569
this.websocket.rtcchannel.on('data', onTunnelWebRTCControlData);
2951
- this.websocket.rtcchannel.on('end', function ()
2952
- {
2570
+ this.websocket.rtcchannel.on('end', function () {
2571
// The WebRTC channel closed, unpipe the KVM now. This is also done when the web socket closes.
2572
//sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC data channel closed');
2955
- if (this.websocket.desktop && this.websocket.desktop.kvm)
2956
- {
2957
- try
2958
- {
2573
+ if (this.websocket.desktop && this.websocket.desktop.kvm) {
2574
+ try {
2575
this.unpipe(this.websocket.desktop.kvm);
2576
this.websocket.httprequest.desktop.kvm.unpipe(this);
2577
}
@@ -2988,21 +2604,17 @@ var consoleWebSockets = {};
2604
var consoleHttpRequest = null;
2605
2606
// Console HTTP response
2991
-function consoleHttpResponse(response)
2992
-{
2607
+function consoleHttpResponse(response) {
2608
response.data = function (data) { sendConsoleText(rstr2hex(buf2rstr(data)), this.sessionid); consoleHttpRequest = null; }
2609
response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; }
2610
}
2611
2612
// Open a web browser to a specified URL on current user's desktop
2998
-function openUserDesktopUrl(url)
2999
-{
2613
+function openUserDesktopUrl(url) {
2614
if ((url.toLowerCase().startsWith('http://') == false) && (url.toLowerCase().startsWith('https://') == false)) { return null; }
2615
var child = null;
3002
- try
3003
- {
3004
- switch (process.platform)
3005
- {
2616
+ try {
2617
+ switch (process.platform) {
2618
case 'win32':
2619
var user = require('user-sessions').getUsername(require('user-sessions').consoleUid());
2620
child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
@@ -3029,13 +2641,10 @@ function openUserDesktopUrl(url)
2641
}
2642
2643
// Process a mesh agent console command
3032
-function processConsoleCommand(cmd, args, rights, sessionid)
3033
-{
3034
- try
3035
- {
2644
+function processConsoleCommand(cmd, args, rights, sessionid) {
2645
+ try {
2646
var response = null;
3037
- switch (cmd)
3038
- {
2647
+ switch (cmd) {
2648
case 'help': { // Displays available commands
2649
var fin = '', f = '', availcommands = 'agentupdate,msh,timerinfo,coreinfo,coredump,service,fdsnapshot,fdcount,startupoptions,alert,agentsize,versions,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,openurl,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,wallpaper,agentmsg';
2650
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration,uac'; }
@@ -3045,8 +2654,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2654
try { require('zip-reader'); availcommands += ',zip,unzip'; } catch (e) { }
2655
2656
availcommands = availcommands.split(',').sort();
3048
- while (availcommands.length > 0)
3049
- {
2657
+ while (availcommands.length > 0) {
2658
if (f.length > 90) { fin += (f + ',\r\n'); f = ''; }
2659
f += (((f != '') ? ', ' : ' ') + availcommands.shift());
2660
}
@@ -3068,12 +2676,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2676
response = require('ChainViewer').getTimerInfo();
2677
break;
2678
case 'find':
3071
- if (args['_'].length <= 1)
3072
- {
2679
+ if (args['_'].length <= 1) {
2680
response = "Proper usage:\r\n find root criteria [criteria2] [criteria n...]";
2681
}
3075
- else
3076
- {
2682
+ else {
2683
var root = args['_'][0];
2684
var p = args['_'].slice(1);
2685
var r = require('file-search').find(root, p);
@@ -3092,26 +2698,21 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2698
break;
2699
}
2700
case 'agentmsg': {
3095
- if (args['_'].length == 0)
3096
- {
2701
+ if (args['_'].length == 0) {
2702
response = "Proper usage:\r\n agentmsg add \"[message]\" [iconIndex]\r\n agentmsg remove [index]\r\n agentmsg list"; // Display usage
3098
- } else
3099
- {
3100
- if ((args['_'][0] == 'add') && (args['_'].length > 1))
3101
- {
2703
+ } else {
2704
+ if ((args['_'][0] == 'add') && (args['_'].length > 1)) {
2705
var msgIndex = 1, iconIndex = 0;
2706
while (tunnelUserCount.msg[msgIndex] != null) { msgIndex++; }
2707
if (args['_'].length >= 3) { try { iconIndex = parseInt(args['_'][2]); } catch (e) { } }
2708
if (typeof iconIndex != 'number') { iconIndex = 0; }
2709
tunnelUserCount.msg[msgIndex] = { msg: args['_'][1], icon: iconIndex };
2710
response = 'Agent message ' + msgIndex + ' added.';
3108
- } else if ((args['_'][0] == 'remove') && (args['_'].length > 1))
3109
- {
2711
+ } else if ((args['_'][0] == 'remove') && (args['_'].length > 1)) {
2712
var msgIndex = 0;
2713
try { msgIndex = parseInt(args['_'][1]); } catch (x) { }
2714
if (tunnelUserCount.msg[msgIndex] == null) { response = "Message not found."; } else { delete tunnelUserCount.msg[msgIndex]; response = "Message removed."; }
3113
- } else if (args['_'][0] == 'list')
3114
- {
2715
+ } else if (args['_'][0] == 'list') {
2716
response = JSON.stringify(tunnelUserCount.msg, null, 2);
2717
}
2718
try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (x) { }
@@ -3126,13 +2727,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2727
break;
2728
}
2729
case 'coredump':
3129
- if (args['_'].length != 1)
3130
- {
2730
+ if (args['_'].length != 1) {
2731
response = "Proper usage: coredump on|off|status|clear"; // Display usage
3132
- } else
3133
- {
3134
- switch (args['_'][0].toLowerCase())
3135
- {
2732
+ } else {
2733
+ switch (args['_'][0].toLowerCase()) {
2734
case 'on':
2735
process.coreDumpLocation = (process.platform == 'win32') ? (process.execPath.replace('.exe', '.dmp')) : (process.execPath + '.dmp');
2736
response = 'coredump is now on';
@@ -3143,20 +2741,15 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2741
break;
2742
case 'status':
2743
response = 'coredump is: ' + ((process.coreDumpLocation == null) ? 'off' : 'on');
3146
- if (process.coreDumpLocation != null)
3147
- {
3148
- if (process.platform == 'win32')
3149
- {
3150
- if (fs.existsSync(process.coreDumpLocation))
3151
- {
2744
+ if (process.coreDumpLocation != null) {
2745
+ if (process.platform == 'win32') {
2746
+ if (fs.existsSync(process.coreDumpLocation)) {
2747
response += '\r\n CoreDump present at: ' + process.coreDumpLocation;
2748
response += '\r\n CoreDump Time: ' + new Date(fs.statSync(process.coreDumpLocation).mtime).getTime();
2749
response += '\r\n Agent Time : ' + new Date(fs.statSync(process.execPath).mtime).getTime();
2750
}
3156
- } else
3157
- {
3158
- if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core'))
3159
- {
2751
+ } else {
2752
+ if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) {
2753
response += '\r\n CoreDump present at: ' + process.cwd() + 'core';
2754
response += '\r\n CoreDump Time: ' + new Date(fs.statSync(process.cwd() + 'core').mtime).getTime();
2755
response += '\r\n Agent Time : ' + new Date(fs.statSync(process.execPath).mtime).getTime();
@@ -3175,33 +2768,26 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2768
}
2769
break;
2770
case 'service':
3178
- if (args['_'].length != 1)
3179
- {
2771
+ if (args['_'].length != 1) {
2772
response = "Proper usage: service status|restart"; // Display usage
2773
}
3182
- else
3183
- {
2774
+ else {
2775
var svcname = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
3185
- try
3186
- {
2776
+ try {
2777
svcname = require('MeshAgent').serviceName;
2778
}
3189
- catch (x)
3190
- {
2779
+ catch (x) {
2780
}
2781
var s = require('service-manager').manager.getService(svcname);
3193
- switch (args['_'][0].toLowerCase())
3194
- {
2782
+ switch (args['_'][0].toLowerCase()) {
2783
case 'status':
2784
response = 'Service ' + (s.isRunning() ? (s.isMe() ? '[SELF]' : '[RUNNING]') : ('[NOT RUNNING]'));
2785
break;
2786
case 'restart':
3199
- if (s.isMe())
3200
- {
2787
+ if (s.isMe()) {
2788
s.restart();
2789
}
3203
- else
3204
- {
2790
+ else {
2791
response = 'Restarting another agent instance is not allowed';
2792
}
2793
break;
@@ -3213,11 +2799,9 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2799
}
2800
break;
2801
case 'zip':
3216
- if (args['_'].length == 0)
3217
- {
2802
+ if (args['_'].length == 0) {
2803
response = "Proper usage: zip (output file name), input1 [, input n]"; // Display usage
3219
- } else
3220
- {
2804
+ } else {
2805
var p = args['_'].join(' ').split(',');
2806
var ofile = p.shift();
2807
sendConsoleText('Writing ' + ofile + '...');
@@ -3230,19 +2814,16 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2814
}
2815
break;
2816
case 'unzip':
3233
- if (args['_'].length == 0)
3234
- {
2817
+ if (args['_'].length == 0) {
2818
response = "Proper usage: unzip input, destination"; // Display usage
3236
- } else
3237
- {
2819
+ } else {
2820
var p = args['_'].join(' ').split(',');
2821
if (p.length != 2) { response = "Proper usage: unzip input, destination"; break; } // Display usage
2822
var prom = require('zip-reader').read(p[0]);
2823
prom._dest = p[1];
2824
prom.self = this;
2825
prom.sessionid = sessionid;
3244
- prom.then(function (zipped)
3245
- {
2826
+ prom.then(function (zipped) {
2827
sendConsoleText('Extracting to ' + this._dest + '...', this.sessionid);
2828
zipped.extractAll(this._dest).then(function () { sendConsoleText('finished unzipping', this.sessionid); }, function (e) { sendConsoleText('Error unzipping: ' + e, this.sessionid); }).parentPromise.sessionid = this.sessionid;
2829
}, function (e) { sendConsoleText('Error unzipping: ' + e, this.sessionid); });
@@ -3250,13 +2831,11 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2831
break;
2832
case 'setbattery':
2833
// require('MeshAgent').SendCommand({ action: 'battery', state: 'dc', level: 55 });
3253
- if ((args['_'].length > 0) && ((args['_'][0] == 'ac') || (args['_'][0] == 'dc')))
3254
- {
2834
+ if ((args['_'].length > 0) && ((args['_'][0] == 'ac') || (args['_'][0] == 'dc'))) {
2835
var b = { action: 'battery', state: args['_'][0] };
2836
if (args['_'].length == 2) { b.level = parseInt(args['_'][1]); }
2837
require('MeshAgent').SendCommand(b);
3258
- } else
3259
- {
2838
+ } else {
2839
require('MeshAgent').SendCommand({ action: 'battery' });
2840
}
2841
break;
@@ -3265,51 +2844,41 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2844
break;
2845
case 'fdcount':
2846
require('DescriptorEvents').getDescriptorCount().then(
3268
- function (c)
3269
- {
2847
+ function (c) {
2848
sendConsoleText('Descriptor Count: ' + c, this.sessionid);
3271
- }, function (e)
3272
- {
2849
+ }, function (e) {
2850
sendConsoleText('Error fetching descriptor count: ' + e, this.sessionid);
2851
}).parentPromise.sessionid = sessionid;
2852
break;
2853
case 'uac':
3277
- if (process.platform != 'win32')
3278
- {
2854
+ if (process.platform != 'win32') {
2855
response = 'Unknown command "uac", type "help" for list of avaialble commands.';
2856
break;
2857
}
3282
- if (args['_'].length != 1)
3283
- {
2858
+ if (args['_'].length != 1) {
2859
response = 'Proper usage: uac [get|interactive|secure]';
2860
}
3286
- else
3287
- {
3288
- switch (args['_'][0].toUpperCase())
3289
- {
2861
+ else {
2862
+ switch (args['_'][0].toUpperCase()) {
2863
case 'GET':
2864
var secd = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 'PromptOnSecureDesktop');
2865
response = "UAC mode: " + (secd == 0 ? "Interactive Desktop" : "Secure Desktop");
2866
break;
2867
case 'INTERACTIVE':
3295
- try
3296
- {
2868
+ try {
2869
require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 'PromptOnSecureDesktop', 0);
2870
response = 'UAC mode changed to: Interactive Desktop';
2871
}
3300
- catch (e)
3301
- {
2872
+ catch (e) {
2873
response = "Unable to change UAC Mode";
2874
}
2875
break;
2876
case 'SECURE':
3306
- try
3307
- {
2877
+ try {
2878
require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 'PromptOnSecureDesktop', 1);
2879
response = 'UAC mode changed to: Secure Desktop';
2880
}
3311
- catch (e)
3312
- {
2881
+ catch (e) {
2882
response = "Unable to change UAC Mode";
2883
}
2884
break;
@@ -3326,50 +2895,40 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2895
response = JSON.stringify(require('MeshAgent').getStartupOptions());
2896
break;
2897
case 'kvmmode':
3329
- if (require('MeshAgent').maxKvmTileSize == null)
3330
- {
2898
+ if (require('MeshAgent').maxKvmTileSize == null) {
2899
response = "Unknown command \"kvmmode\", type \"help\" for list of avaialble commands.";
2900
}
3333
- else
3334
- {
3335
- if (require('MeshAgent').maxKvmTileSize == 0)
3336
- {
2901
+ else {
2902
+ if (require('MeshAgent').maxKvmTileSize == 0) {
2903
response = 'KVM Mode: Full JUMBO';
2904
}
3339
- else
3340
- {
2905
+ else {
2906
response = 'KVM Mode: ' + (require('MeshAgent').maxKvmTileSize <= 65500 ? 'NO JUMBO' : 'Partial JUMBO');
2907
response += (', TileLimit: ' + (require('MeshAgent').maxKvmTileSize < 1024 ? (require('MeshAgent').maxKvmTileSize + ' bytes') : (Math.round(require('MeshAgent').maxKvmTileSize / 1024) + ' Kbytes')));
2908
}
2909
}
2910
break;
2911
case 'alert':
3347
- if (args['_'].length == 0)
3348
- {
2912
+ if (args['_'].length == 0) {
2913
response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage
2914
}
3351
- else
3352
- {
2915
+ else {
2916
var p = args['_'].join(' ').split(',');
3354
- if (p.length < 2)
3355
- {
2917
+ if (p.length < 2) {
2918
response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage
2919
}
3358
- else
3359
- {
2920
+ else {
2921
this._alert = require('message-box').create(p[0], p[1], p.length == 3 ? parseInt(p[2]) : 9999, 1);
2922
}
2923
}
2924
break;
2925
case 'agentsize':
2926
var actualSize = Math.floor(require('fs').statSync(process.execPath).size / 1024);
3366
- if (process.platform == 'win32')
3367
- {
2927
+ if (process.platform == 'win32') {
2928
// Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
2929
var writtenSize = 0;
2930
try { writtenSize = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize'); } catch (e) { response = e; }
3371
- if (writtenSize != actualSize)
3372
- {
2931
+ if (writtenSize != actualSize) {
2932
response = "Size updated from: " + writtenSize + " to: " + actualSize;
2933
try { require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize', actualSize); } catch (e) { response = e; }
2934
} else
@@ -3382,31 +2941,26 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2941
break;
2942
case 'wpfhwacceleration':
2943
if (process.platform != 'win32') { throw ("wpfhwacceleration setting is only supported on Windows"); }
3385
- if (args['_'].length != 1)
3386
- {
2944
+ if (args['_'].length != 1) {
2945
response = "Proper usage: wpfhwacceleration (ON|OFF|STATUS)"; // Display usage
2946
}
3389
- else
3390
- {
2947
+ else {
2948
var reg = require('win-registry');
2949
var uname = require('user-sessions').getUsername(require('user-sessions').consoleUid());
2950
var key = reg.usernameToUserKey(uname);
2951
3395
- switch (args['_'][0].toUpperCase())
3396
- {
2952
+ switch (args['_'][0].toUpperCase()) {
2953
default:
2954
response = "Proper usage: wpfhwacceleration (ON|OFF|STATUS|DEFAULT)"; // Display usage
2955
break;
2956
case 'ON':
3401
- try
3402
- {
2957
+ try {
2958
reg.WriteKey(reg.HKEY.Users, key + '\\SOFTWARE\\Microsoft\\Avalon.Graphics', 'DisableHWAcceleration', 0);
2959
response = "OK";
2960
} catch (e) { response = "FAILED"; }
2961
break;
2962
case 'OFF':
3408
- try
3409
- {
2963
+ try {
2964
reg.WriteKey(reg.HKEY.Users, key + '\\SOFTWARE\\Microsoft\\Avalon.Graphics', 'DisableHWAcceleration', 1);
2965
response = 'OK';
2966
} catch (e) { response = 'FAILED'; }
@@ -3424,13 +2978,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2978
}
2979
break;
2980
case 'tsid':
3427
- if (process.platform == 'win32')
3428
- {
3429
- if (args['_'].length != 1)
3430
- {
2981
+ if (process.platform == 'win32') {
2982
+ if (args['_'].length != 1) {
2983
response = "TSID: " + (require('MeshAgent')._tsid == null ? "console" : require('MeshAgent')._tsid);
3432
- } else
3433
- {
2984
+ } else {
2985
var i = parseInt(args['_'][0]);
2986
require('MeshAgent')._tsid = (isNaN(i) ? null : i);
2987
response = "TSID set to: " + (require('MeshAgent')._tsid == null ? "console" : require('MeshAgent')._tsid);
@@ -3439,15 +2990,12 @@ function processConsoleCommand(cmd, args, rights, sessionid)
2990
{ response = "TSID command only supported on Windows"; }
2991
break;
2992
case 'activeusers':
3442
- if (process.platform == 'win32')
3443
- {
2993
+ if (process.platform == 'win32') {
2994
var p = require('user-sessions').enumerateUsers();
2995
p.sessionid = sessionid;
3446
- p.then(function (u)
3447
- {
2996
+ p.then(function (u) {
2997
var v = [];
3449
- for (var i in u)
3450
- {
2998
+ for (var i in u) {
2999
if (u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
3000
}
3001
sendConsoleText(JSON.stringify(v, null, 1), this.sessionid);
@@ -3456,44 +3004,35 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3004
{ response = "activeusers command only supported on Windows"; }
3005
break;
3006
case 'wallpaper':
3459
- if (process.platform != 'win32' && !(process.platform == 'linux' && require('linux-gnome-helpers').available))
3460
- {
3007
+ if (process.platform != 'win32' && !(process.platform == 'linux' && require('linux-gnome-helpers').available)) {
3008
response = "wallpaper command not supported on this platform";
3009
}
3463
- else
3464
- {
3465
- if (args['_'].length != 1)
3466
- {
3010
+ else {
3011
+ if (args['_'].length != 1) {
3012
response = 'Proper usage: wallpaper (GET|TOGGLE)'; // Display usage
3013
}
3469
- else
3470
- {
3471
- switch (args['_'][0].toUpperCase())
3472
- {
3014
+ else {
3015
+ switch (args['_'][0].toUpperCase()) {
3016
default:
3017
response = 'Proper usage: wallpaper (GET|TOGGLE)'; // Display usage
3018
break;
3019
case 'GET':
3020
case 'TOGGLE':
3478
- if (process.platform == 'win32')
3479
- {
3021
+ if (process.platform == 'win32') {
3022
var id = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
3023
var child = require('child_process').execFile(process.execPath, [process.execPath.split('\\').pop(), '-b64exec', 'dmFyIFNQSV9HRVRERVNLV0FMTFBBUEVSID0gMHgwMDczOwp2YXIgU1BJX1NFVERFU0tXQUxMUEFQRVIgPSAweDAwMTQ7CnZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOwp2YXIgdXNlcjMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ3VzZXIzMi5kbGwnKTsKdXNlcjMyLkNyZWF0ZU1ldGhvZCgnU3lzdGVtUGFyYW1ldGVyc0luZm9BJyk7CgppZiAocHJvY2Vzcy5hcmd2Lmxlbmd0aCA9PSAzKQp7CiAgICB2YXIgdiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDEwMjQpOwogICAgdXNlcjMyLlN5c3RlbVBhcmFtZXRlcnNJbmZvQShTUElfR0VUREVTS1dBTExQQVBFUiwgdi5fc2l6ZSwgdiwgMCk7CiAgICBjb25zb2xlLmxvZyh2LlN0cmluZyk7CiAgICBwcm9jZXNzLmV4aXQoKTsKfQplbHNlCnsKICAgIHZhciBuYiA9IEdNLkNyZWF0ZVZhcmlhYmxlKHByb2Nlc3MuYXJndlszXSk7CiAgICB1c2VyMzIuU3lzdGVtUGFyYW1ldGVyc0luZm9BKFNQSV9TRVRERVNLV0FMTFBBUEVSLCBuYi5fc2l6ZSwgbmIsIDApOwogICAgcHJvY2Vzcy5leGl0KCk7Cn0='], { type: id });
3024
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3025
child.stderr.on('data', function () { });
3026
child.waitExit();
3027
var current = child.stdout.str.trim();
3486
- if (args['_'][0].toUpperCase() == 'GET')
3487
- {
3028
+ if (args['_'][0].toUpperCase() == 'GET') {
3029
response = current;
3030
break;
3031
}
3491
- if (current != '')
3492
- {
3032
+ if (current != '') {
3033
require('MeshAgent')._wallpaper = current;
3034
response = 'Wallpaper cleared';
3495
- } else
3496
- {
3035
+ } else {
3036
response = 'Wallpaper restored';
3037
}
3038
child = require('child_process').execFile(process.execPath, [process.execPath.split('\\').pop(), '-b64exec', 'dmFyIFNQSV9HRVRERVNLV0FMTFBBUEVSID0gMHgwMDczOwp2YXIgU1BJX1NFVERFU0tXQUxMUEFQRVIgPSAweDAwMTQ7CnZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOwp2YXIgdXNlcjMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ3VzZXIzMi5kbGwnKTsKdXNlcjMyLkNyZWF0ZU1ldGhvZCgnU3lzdGVtUGFyYW1ldGVyc0luZm9BJyk7CgppZiAocHJvY2Vzcy5hcmd2Lmxlbmd0aCA9PSAzKQp7CiAgICB2YXIgdiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDEwMjQpOwogICAgdXNlcjMyLlN5c3RlbVBhcmFtZXRlcnNJbmZvQShTUElfR0VUREVTS1dBTExQQVBFUiwgdi5fc2l6ZSwgdiwgMCk7CiAgICBjb25zb2xlLmxvZyh2LlN0cmluZyk7CiAgICBwcm9jZXNzLmV4aXQoKTsKfQplbHNlCnsKICAgIHZhciBuYiA9IEdNLkNyZWF0ZVZhcmlhYmxlKHByb2Nlc3MuYXJndlszXSk7CiAgICB1c2VyMzIuU3lzdGVtUGFyYW1ldGVyc0luZm9BKFNQSV9TRVRERVNLV0FMTFBBUEVSLCBuYi5fc2l6ZSwgbmIsIDApOwogICAgcHJvY2Vzcy5leGl0KCk7Cn0=', current != '' ? '""' : require('MeshAgent')._wallpaper], { type: id });
@@ -3501,21 +3040,17 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3040
child.stderr.on('data', function () { });
3041
child.waitExit();
3042
}
3504
- else
3505
- {
3043
+ else {
3044
var id = require('user-sessions').consoleUid();
3045
var current = require('linux-gnome-helpers').getDesktopWallpaper(id);
3508
- if (args['_'][0].toUpperCase() == 'GET')
3509
- {
3046
+ if (args['_'][0].toUpperCase() == 'GET') {
3047
response = current;
3048
break;
3049
}
3513
- if (current != '/dev/null')
3514
- {
3050
+ if (current != '/dev/null') {
3051
require('MeshAgent')._wallpaper = current;
3052
response = 'Wallpaper cleared';
3517
- } else
3518
- {
3053
+ } else {
3054
response = 'Wallpaper restored';
3055
}
3056
require('linux-gnome-helpers').setDesktopWallpaper(id, current != '/dev/null' ? undefined : require('MeshAgent')._wallpaper);
@@ -3526,29 +3061,22 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3061
}
3062
break;
3063
case 'safemode':
3529
- if (process.platform != 'win32')
3530
- {
3064
+ if (process.platform != 'win32') {
3065
response = 'safemode only supported on Windows Platforms'
3066
}
3533
- else
3534
- {
3535
- if (args['_'].length != 1)
3536
- {
3067
+ else {
3068
+ if (args['_'].length != 1) {
3069
response = 'Proper usage: safemode (ON|OFF|STATUS)'; // Display usage
3070
}
3539
- else
3540
- {
3071
+ else {
3072
var svcname = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
3542
- try
3543
- {
3073
+ try {
3074
svcname = require('MeshAgent').serviceName;
3075
}
3546
- catch (x)
3547
- {
3076
+ catch (x) {
3077
}
3078
3550
- switch (args['_'][0].toUpperCase())
3551
- {
3079
+ switch (args['_'][0].toUpperCase()) {
3080
default:
3081
response = 'Proper usage: safemode (ON|OFF|STATUS)'; // Display usage
3082
break;
@@ -3561,10 +3089,8 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3089
break;
3090
case 'STATUS':
3091
var nextboot = require('win-bcd').getKey('safeboot');
3564
- if (nextboot)
3565
- {
3566
- switch (nextboot)
3567
- {
3092
+ if (nextboot) {
3093
+ switch (nextboot) {
3094
case 'Network':
3095
case 'network':
3096
nextboot = 'SAFE_MODE_NETWORK';
@@ -3580,32 +3106,30 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3106
}
3107
}
3108
break;
3583
- /*
3584
- case 'border':
3585
- {
3586
- if ((args['_'].length == 1) && (args['_'][0] == 'on')) {
3587
- if (meshCoreObj.users.length > 0) {
3588
- obj.borderManager.Start(meshCoreObj.users[0]);
3589
- response = 'Border blinking is on.';
3590
- } else {
3591
- response = 'Cannot turn on border blinking, no logged in users.';
3592
- }
3593
- } else if ((args['_'].length == 1) && (args['_'][0] == 'off')) {
3594
- obj.borderManager.Stop();
3595
- response = 'Border blinking is off.';
3109
+ /*
3110
+ case 'border':
3111
+ {
3112
+ if ((args['_'].length == 1) && (args['_'][0] == 'on')) {
3113
+ if (meshCoreObj.users.length > 0) {
3114
+ obj.borderManager.Start(meshCoreObj.users[0]);
3115
+ response = 'Border blinking is on.';
3116
} else {
3597
- response = 'Proper usage: border "on|off"'; // Display correct command usage
3117
+ response = 'Cannot turn on border blinking, no logged in users.';
3118
}
3119
+ } else if ((args['_'].length == 1) && (args['_'][0] == 'off')) {
3120
+ obj.borderManager.Stop();
3121
+ response = 'Border blinking is off.';
3122
+ } else {
3123
+ response = 'Proper usage: border "on|off"'; // Display correct command usage
3124
}
3600
- break;
3601
- */
3125
+ }
3126
+ break;
3127
+ */
3128
case 'av':
3603
- if (process.platform == 'win32')
3604
- {
3129
+ if (process.platform == 'win32') {
3130
// Windows Command: "wmic /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct get /FORMAT:CSV"
3131
response = JSON.stringify(require('win-info').av(), null, 1);
3607
- } else
3608
- {
3132
+ } else {
3133
response = 'Not supported on the platform';
3134
}
3135
break;
@@ -3613,27 +3137,21 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3137
if (args['_'].length != 1) { response = 'Proper usage: log "sample text"'; } else { MeshServerLog(args['_'][0]); response = 'ok'; }
3138
break;
3139
case 'getclip':
3616
- if (require('MeshAgent').isService)
3617
- {
3140
+ if (require('MeshAgent').isService) {
3141
require('clipboard').dispatchRead().then(function (str) { sendConsoleText(str, sessionid); });
3619
- } else
3620
- {
3142
+ } else {
3143
require("clipboard").read().then(function (str) { sendConsoleText(str, sessionid); });
3144
}
3145
break;
3146
case 'setclip': {
3625
- if (args['_'].length != 1)
3626
- {
3147
+ if (args['_'].length != 1) {
3148
response = 'Proper usage: setclip "sample text"';
3628
- } else
3629
- {
3630
- if (require('MeshAgent').isService)
3631
- {
3149
+ } else {
3150
+ if (require('MeshAgent').isService) {
3151
require('clipboard').dispatchWrite(args['_'][0]);
3152
response = 'Setting clipboard to: "' + args['_'][0] + '"';
3153
}
3635
- else
3636
- {
3154
+ else {
3155
require("clipboard")(args['_'][0]); response = 'Setting clipboard to: "' + args['_'][0] + '"';
3156
}
3157
}
@@ -3651,12 +3169,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3169
}
3170
case 'toast': {
3171
if (args['_'].length < 1) { response = 'Proper usage: toast "message"'; } else {
3654
- if (require('MeshAgent')._tsid == null)
3655
- {
3172
+ if (require('MeshAgent')._tsid == null) {
3173
require('toaster').Toast('MeshCentral', args['_'][0]).then(sendConsoleText, sendConsoleText);
3174
}
3658
- else
3659
- {
3175
+ else {
3176
require('toaster').Toast('MeshCentral', args['_'][0], require('MeshAgent')._tsid).then(sendConsoleText, sendConsoleText);
3177
}
3178
}
@@ -3668,8 +3184,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3184
break;
3185
}
3186
case 'ps': {
3671
- processManager.getProcesses(function (plist)
3672
- {
3187
+ processManager.getProcesses(function (plist) {
3188
var x = '';
3189
for (var i in plist) { x += i + ((plist[i].user) ? (', ' + plist[i].user) : '') + ', ' + plist[i].cmd + '\r\n'; }
3190
sendConsoleText(x, sessionid);
@@ -3677,11 +3192,9 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3192
break;
3193
}
3194
case 'kill': {
3680
- if ((args['_'].length < 1))
3681
- {
3195
+ if ((args['_'].length < 1)) {
3196
response = 'Proper usage: kill [pid]'; // Display correct command usage
3683
- } else
3684
- {
3197
+ } else {
3198
process.kill(parseInt(args['_'][0]));
3199
response = 'Killed process ' + args['_'][0] + '.';
3200
}
@@ -3694,13 +3207,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3207
case 'rawsmbios': {
3208
if (SMBiosTablesRaw == null) { response = 'SMBios tables not available.'; } else {
3209
response = '';
3697
- for (var i in SMBiosTablesRaw)
3698
- {
3210
+ for (var i in SMBiosTablesRaw) {
3211
var header = false;
3700
- for (var j in SMBiosTablesRaw[i])
3701
- {
3702
- if (SMBiosTablesRaw[i][j].length > 0)
3703
- {
3212
+ for (var j in SMBiosTablesRaw[i]) {
3213
+ if (SMBiosTablesRaw[i][j].length > 0) {
3214
if (header == false) { response += ('Table type #' + i + ((require('smbios').smTableTypes[i] == null) ? '' : (', ' + require('smbios').smTableTypes[i]))) + '\r\n'; header = true; }
3215
response += (' ' + SMBiosTablesRaw[i][j].toString('hex')) + '\r\n';
3216
}
@@ -3710,41 +3220,33 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3220
break;
3221
}
3222
case 'eval': { // Eval JavaScript
3713
- if (args['_'].length < 1)
3714
- {
3223
+ if (args['_'].length < 1) {
3224
response = 'Proper usage: eval "JavaScript code"'; // Display correct command usage
3716
- } else
3717
- {
3225
+ } else {
3226
response = JSON.stringify(mesh.eval(args['_'][0])); // This can only be run by trusted administrator.
3227
}
3228
break;
3229
}
3230
case 'uninstallagent': // Uninstall this agent
3231
var agentName = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent';
3724
- try
3725
- {
3232
+ try {
3233
agentName = require('MeshAgent').serviceName;
3234
}
3728
- catch (x)
3729
- {
3235
+ catch (x) {
3236
}
3237
3732
- if (!require('service-manager').manager.getService(agentName).isMe())
3733
- {
3238
+ if (!require('service-manager').manager.getService(agentName).isMe()) {
3239
response = 'Uininstall failed, this instance is not the service instance';
3735
- } else
3736
- {
3240
+ } else {
3241
try { diagnosticAgent_uninstall(); } catch (e) { }
3242
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
3243
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 });
3244
}
3245
break;
3246
case 'notify': { // Send a notification message to the mesh
3743
- if (args['_'].length != 1)
3744
- {
3247
+ if (args['_'].length != 1) {
3248
response = 'Proper usage: notify "message" [--session]'; // Display correct command usage
3746
- } else
3747
- {
3249
+ } else {
3250
var notification = { action: 'msg', type: 'notify', value: args['_'][0], tag: 'console' };
3251
if (args.session) { notification.sessionid = sessionid; } // If "--session" is specified, notify only this session, if not, the server will notify the mesh
3252
mesh.SendCommand(notification); // no sessionid or userid specified, notification will go to the entire mesh
@@ -3756,23 +3258,20 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3258
// CPU & memory utilization
3259
pr = require('sysinfo').cpuUtilization();
3260
pr.sessionid = sessionid;
3759
- pr.then(function (data)
3760
- {
3261
+ pr.then(function (data) {
3262
sendConsoleText(JSON.stringify(
3263
{
3264
cpu: data,
3265
memory: require('sysinfo').memUtilization(),
3266
thermals: require('sysinfo').thermals == null ? [] : require('sysinfo').thermals()
3267
}, null, 1), this.sessionid);
3767
- }, function (e)
3768
- {
3769
- sendConsoleText(e);
3770
- });
3268
+ }, function (e) {
3269
+ sendConsoleText(e);
3270
+ });
3271
break;
3272
}
3273
case 'sysinfo': { // Return system information
3774
- getSystemInformation(function (results, err)
3775
- {
3274
+ getSystemInformation(function (results, err) {
3275
if (results == null) { sendConsoleText(err, this.sessionid); } else {
3276
sendConsoleText(JSON.stringify(results, null, 1), this.sessionid);
3277
}
@@ -3794,12 +3293,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3293
case 'osinfo': { // Return the operating system information
3294
var i = 1;
3295
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
3797
- for (var j = 0; j < i; j++)
3798
- {
3296
+ for (var j = 0; j < i; j++) {
3297
var pr = require('os').name();
3298
pr.sessionid = sessionid;
3801
- pr.then(function (v)
3802
- {
3299
+ pr.then(function (v) {
3300
sendConsoleText("OS: " + v + (process.platform == 'win32' ? (require('win-virtual-terminal').supported ? ' [ConPTY: YES]' : ' [ConPTY: NO]') : ''), this.sessionid);
3301
});
3302
}
@@ -3817,11 +3314,9 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3314
break;
3315
}
3316
case 'type': { // Returns the content of a file
3820
- if (args['_'].length == 0)
3821
- {
3317
+ if (args['_'].length == 0) {
3318
response = 'Proper usage: type (filepath) [maxlength]'; // Display correct command usage
3823
- } else
3824
- {
3319
+ } else {
3320
var max = 4096;
3321
if ((args['_'].length > 1) && (typeof args['_'][1] == 'number')) { max = args['_'][1]; }
3322
if (max > 4096) max = 4096;
@@ -3840,22 +3335,18 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3335
}
3336
case 'dbget': { // Return the data store value for a given key
3337
if (db == null) { response = 'Database not accessible.'; break; }
3843
- if (args['_'].length != 1)
3844
- {
3338
+ if (args['_'].length != 1) {
3339
response = 'Proper usage: dbget (key)'; // Display the value for a given database key
3846
- } else
3847
- {
3340
+ } else {
3341
response = db.Get(args['_'][0]);
3342
}
3343
break;
3344
}
3345
case 'dbset': { // Set a data store key and value pair
3346
if (db == null) { response = 'Database not accessible.'; break; }
3854
- if (args['_'].length != 2)
3855
- {
3347
+ if (args['_'].length != 2) {
3348
response = 'Proper usage: dbset (key) (value)'; // Set a database key
3857
- } else
3858
- {
3349
+ } else {
3350
var r = db.Put(args['_'][0], args['_'][1]);
3351
response = 'Key set: ' + r;
3352
}
@@ -3868,27 +3359,20 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3359
break;
3360
}
3361
case 'httpget': {
3871
- if (consoleHttpRequest != null)
3872
- {
3362
+ if (consoleHttpRequest != null) {
3363
response = 'HTTP operation already in progress.';
3874
- } else
3875
- {
3876
- if (args['_'].length != 1)
3877
- {
3364
+ } else {
3365
+ if (args['_'].length != 1) {
3366
response = 'Proper usage: httpget (url)';
3879
- } else
3880
- {
3367
+ } else {
3368
var options = http.parseUri(args['_'][0]);
3369
options.method = 'GET';
3883
- if (options == null)
3884
- {
3370
+ if (options == null) {
3371
response = 'Invalid url.';
3886
- } else
3887
- {
3372
+ } else {
3373
try { consoleHttpRequest = http.request(options, consoleHttpResponse); } catch (e) { response = 'Invalid HTTP GET request'; }
3374
consoleHttpRequest.sessionid = sessionid;
3890
- if (consoleHttpRequest != null)
3891
- {
3375
+ if (consoleHttpRequest != null) {
3376
consoleHttpRequest.end();
3377
response = 'HTTPGET ' + options.protocol + '//' + options.host + ':' + options.port + options.path;
3378
}
@@ -3899,8 +3383,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3383
}
3384
case 'wslist': { // List all web sockets
3385
response = '';
3902
- for (var i in consoleWebSockets)
3903
- {
3386
+ for (var i in consoleWebSockets) {
3387
var httprequest = consoleWebSockets[i];
3388
response += 'Websocket #' + i + ', ' + httprequest.url + '\r\n';
3389
}
@@ -3908,20 +3391,16 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3391
break;
3392
}
3393
case 'wsconnect': { // Setup a web socket
3911
- if (args['_'].length == 0)
3912
- {
3394
+ if (args['_'].length == 0) {
3395
response = 'Proper usage: wsconnect (url)\r\nFor example: wsconnect wss://localhost:443/meshrelay.ashx?id=abc'; // Display correct command usage
3914
- } else
3915
- {
3396
+ } else {
3397
var httprequest = null;
3917
- try
3918
- {
3398
+ try {
3399
var options = http.parseUri(args['_'][0].split('$').join('%24').split('@').join('%40')); // Escape the $ and @ characters in the URL
3400
options.rejectUnauthorized = 0;
3401
httprequest = http.request(options);
3402
} catch (e) { response = 'Invalid HTTP websocket request'; }
3923
- if (httprequest != null)
3924
- {
3403
+ if (httprequest != null) {
3404
httprequest.upgrade = onWebSocketUpgrade;
3405
httprequest.on('error', function (e) { sendConsoleText("ERROR: Unable to connect to: " + this.url + ", " + JSON.stringify(e)); });
3406
@@ -3937,43 +3416,34 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3416
break;
3417
}
3418
case 'wssend': { // Send data on a web socket
3940
- if (args['_'].length == 0)
3941
- {
3419
+ if (args['_'].length == 0) {
3420
response = 'Proper usage: wssend (socketnumber)\r\n'; // Display correct command usage
3943
- for (var i in consoleWebSockets)
3944
- {
3421
+ for (var i in consoleWebSockets) {
3422
var httprequest = consoleWebSockets[i];
3423
response += 'Websocket #' + i + ', ' + httprequest.url + '\r\n';
3424
}
3948
- } else
3949
- {
3425
+ } else {
3426
var i = parseInt(args['_'][0]);
3427
var httprequest = consoleWebSockets[i];
3952
- if (httprequest != undefined)
3953
- {
3428
+ if (httprequest != undefined) {
3429
httprequest.s.write(args['_'][1]);
3430
response = 'ok';
3956
- } else
3957
- {
3431
+ } else {
3432
response = 'Invalid web socket number';
3433
}
3434
}
3435
break;
3436
}
3437
case 'wsclose': { // Close a websocket
3964
- if (args['_'].length == 0)
3965
- {
3438
+ if (args['_'].length == 0) {
3439
response = 'Proper usage: wsclose (socketnumber)'; // Display correct command usage
3967
- } else
3968
- {
3440
+ } else {
3441
var i = parseInt(args['_'][0]);
3442
var httprequest = consoleWebSockets[i];
3971
- if (httprequest != undefined)
3972
- {
3443
+ if (httprequest != undefined) {
3444
if (httprequest.s != null) { httprequest.s.end(); } else { httprequest.end(); }
3445
response = 'ok';
3975
- } else
3976
- {
3446
+ } else {
3447
response = 'Invalid web socket number';
3448
}
3449
}
@@ -3991,15 +3461,12 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3461
if (args['_'].length > 0) { xpath = obj.path.join(args['_'][0], '*'); }
3462
response = 'List of ' + xpath + '\r\n';
3463
var results = fs.readdirSync(xpath);
3994
- for (var i = 0; i < results.length; ++i)
3995
- {
3464
+ for (var i = 0; i < results.length; ++i) {
3465
var stat = null, p = obj.path.join(args['_'][0], results[i]);
3466
try { stat = fs.statSync(p); } catch (e) { }
3998
- if ((stat == null) || (stat == undefined))
3999
- {
3467
+ if ((stat == null) || (stat == undefined)) {
3468
response += (results[i] + "\r\n");
4001
- } else
4002
- {
3469
+ } else {
3470
response += (results[i] + " " + ((stat.isDirectory()) ? "(Folder)" : "(File)") + "\r\n");
3471
}
3472
}
@@ -4015,16 +3482,13 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3482
break;
3483
}
3484
case 'amt': { // Show Intel AMT status
4018
- if (amt != null)
4019
- {
4020
- amt.getMeiState(9, function (state)
4021
- {
3485
+ if (amt != null) {
3486
+ amt.getMeiState(9, function (state) {
3487
var resp = "Intel AMT not detected.";
3488
if (state != null) { resp = objToString(state, 0, ' ', true); }
3489
sendConsoleText(resp, sessionid);
3490
});
4026
- } else
4027
- {
3491
+ } else {
3492
response = "Intel AMT not detected.";
3493
}
3494
break;
@@ -4035,11 +3499,9 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3499
break;
3500
}
3501
case 'wakeonlan': { // Send wake-on-lan
4038
- if ((args['_'].length != 1) || (args['_'][0].length != 12))
4039
- {
3502
+ if ((args['_'].length != 1) || (args['_'][0].length != 12)) {
3503
response = 'Proper usage: wakeonlan [mac], for example "wakeonlan 010203040506".';
4041
- } else
4042
- {
3504
+ } else {
3505
var count = sendWakeOnLan(args['_'][0]);
3506
response = 'Sent wake-on-lan on ' + count + ' interface(s).';
3507
}
@@ -4050,16 +3512,12 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3512
break;
3513
}
3514
case 'power': { // Execute a power action on this computer
4053
- if (mesh.ExecPowerState == undefined)
4054
- {
3515
+ if (mesh.ExecPowerState == undefined) {
3516
response = 'Power command not supported on this agent.';
4056
- } else
4057
- {
4058
- if ((args['_'].length == 0) || isNaN(Number(args['_'][0])))
4059
- {
3517
+ } else {
3518
+ if ((args['_'].length == 0) || isNaN(Number(args['_'][0]))) {
3519
response = 'Proper usage: power (actionNumber), where actionNumber is:\r\n LOGOFF = 1\r\n SHUTDOWN = 2\r\n REBOOT = 3\r\n SLEEP = 4\r\n HIBERNATE = 5\r\n DISPLAYON = 6\r\n KEEPAWAKE = 7\r\n BEEP = 8\r\n CTRLALTDEL = 9\r\n VIBRATE = 13\r\n FLASH = 14'; // Display correct command usage
4061
- } else
4062
- {
3520
+ } else {
3521
var r = mesh.ExecPowerState(Number(args['_'][0]), Number(args['_'][1]));
3522
response = 'Power action executed with return code: ' + r + '.';
3523
}
@@ -4067,8 +3525,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3525
break;
3526
}
3527
case 'location': {
4070
- getIpLocationData(function (location)
4071
- {
3528
+ getIpLocationData(function (location) {
3529
sendConsoleText(objToString({ action: 'iplocation', type: 'publicip', value: location }, 0, ' '));
3530
});
3531
break;
@@ -4078,8 +3535,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3535
break;
3536
}
3537
case 'scanwifi': {
4081
- if (wifiScanner != null)
4082
- {
3538
+ if (wifiScanner != null) {
3539
var wifiPresent = wifiScanner.hasWireless;
3540
if (wifiPresent) { response = "Perfoming Wifi scan..."; wifiScanner.Scan(); } else { response = "Wifi absent."; }
3541
} else
@@ -4096,51 +3552,40 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3552
break;
3553
}
3554
case 'getscript': {
4099
- if (args['_'].length != 1)
4100
- {
3555
+ if (args['_'].length != 1) {
3556
response = "Proper usage: getscript [scriptNumber].";
4102
- } else
4103
- {
3557
+ } else {
3558
mesh.SendCommand({ action: 'getScript', type: args['_'][0] });
3559
}
3560
break;
3561
}
3562
case 'diagnostic':
3563
{
4110
- if (!mesh.DAIPC.listening)
4111
- {
3564
+ if (!mesh.DAIPC.listening) {
3565
response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system';
3566
break;
3567
}
3568
var diag = diagnosticAgent_installCheck();
4116
- if (diag)
4117
- {
4118
- if (args['_'].length == 1 && args['_'][0] == 'uninstall')
4119
- {
3569
+ if (diag) {
3570
+ if (args['_'].length == 1 && args['_'][0] == 'uninstall') {
3571
diagnosticAgent_uninstall();
3572
response = 'Diagnostic Agent uninstalled';
3573
}
4123
- else
4124
- {
3574
+ else {
3575
response = 'Diagnostic Agent installed at: ' + diag.appLocation();
3576
}
3577
}
4128
- else
4129
- {
4130
- if (args['_'].length == 1 && args['_'][0] == 'install')
4131
- {
3578
+ else {
3579
+ if (args['_'].length == 1 && args['_'][0] == 'install') {
3580
diag = diagnosticAgent_installCheck(true);
4133
- if (diag)
4134
- {
3581
+ if (diag) {
3582
response = 'Diagnostic agent was installed at: ' + diag.appLocation();
3583
}
4137
- else
4138
- {
3584
+ else {
3585
response = 'Diagnostic agent installation failed';
3586
}
3587
}
4142
- else
4143
- {
3588
+ else {
3589
response = 'Diagnostic Agent Not installed. To install: diagnostic install';
3590
}
3591
}
@@ -4154,8 +3599,7 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3599
case 'amtconfig': {
3600
if (amt == null) { response = "Intel AMT not detected."; break; }
3601
if (apftunnel != null) { response = "Intel AMT server tunnel already active"; break; }
4157
- amt.getMeiState(15, function (state)
4158
- {
3602
+ amt.getMeiState(15, function (state) {
3603
var rx = '';
3604
if ((state == null) || (state.ProvisioningState == null)) { rx = "Intel AMT not ready for configuration."; } else {
3605
var apfarg = {
@@ -4169,19 +3613,15 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3613
conntype: 2, // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
3614
meiState: state // MEI state will be passed to MPS server
3615
};
4172
- if ((state.UUID == null) || (state.UUID.length != 36))
4173
- {
3616
+ if ((state.UUID == null) || (state.UUID.length != 36)) {
3617
rx = "Unable to get Intel AMT UUID";
4175
- } else
4176
- {
3618
+ } else {
3619
addAmtEvent('User LMS tunnel start.');
3620
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
4179
- apftunnel.onJsonControl = function (data)
4180
- {
3621
+ apftunnel.onJsonControl = function (data) {
3622
if (data.action == 'console') { addAmtEvent(data.msg); require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message
3623
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
4183
- if (data.action == 'deactivate')
4184
- { // Request CCM deactivation
3624
+ if (data.action == 'deactivate') { // Request CCM deactivation
3625
var amtMeiModule, amtMei;
3626
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { apftunnel.sendMeiDeactivationState(1); return; }
3627
amtMei.on('error', function (e) { apftunnel.sendMeiDeactivationState(1); });
@@ -4190,12 +3630,10 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3630
if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; } // Close the CIRA-LMS connection
3631
}
3632
apftunnel.onChannelClosed = function () { addAmtEvent('User LMS tunnel closed.'); apftunnel = null; }
4193
- try
4194
- {
3633
+ try {
3634
apftunnel.connect();
3635
rx = "Started Intel AMT configuration";
4197
- } catch (ex)
4198
- {
3636
+ } catch (ex) {
3637
rx = JSON.stringify(ex);
3638
}
3639
}
@@ -4205,17 +3643,14 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3643
break;
3644
}
3645
case 'apf': {
4208
- if (meshCoreObj.intelamt !== null)
4209
- {
4210
- if (args['_'].length == 1)
4211
- {
3646
+ if (meshCoreObj.intelamt !== null) {
3647
+ if (args['_'].length == 1) {
3648
var connType = -1, connTypeStr = args['_'][0].toLowerCase();
3649
if (connTypeStr == 'lms') { connType = 2; }
3650
if (connTypeStr == 'relay') { connType = 1; }
3651
if (connTypeStr == 'cira') { connType = 0; }
3652
if (connTypeStr == 'off') { connType = -2; }
4217
- if (connType >= 0)
4218
- { // Connect
3653
+ if (connType >= 0) { // Connect
3654
var apfarg = {
3655
mpsurl: mesh.ServerUrl.replace('agent.ashx', 'apf.ashx'),
3656
mpsuser: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
@@ -4226,67 +3661,52 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3661
clientuuid: meshCoreObj.intelamt.uuid,
3662
conntype: connType // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
3663
};
4229
- if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36))
4230
- {
3664
+ if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
3665
response = "Unable to get Intel AMT UUID: " + apfarg.clientuuid;
4232
- } else
4233
- {
3666
+ } else {
3667
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
4235
- apftunnel.onJsonControl = function (data)
4236
- {
3668
+ apftunnel.onJsonControl = function (data) {
3669
if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); }
3670
if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; }
3671
}
3672
apftunnel.onChannelClosed = function () { apftunnel = null; }
4241
- try
4242
- {
3673
+ try {
3674
apftunnel.connect();
3675
response = "Started APF tunnel";
4245
- } catch (e)
4246
- {
3676
+ } catch (e) {
3677
response = JSON.stringify(e);
3678
}
3679
}
4250
- } else if (connType == -2)
4251
- { // Disconnect
4252
- try
4253
- {
3680
+ } else if (connType == -2) { // Disconnect
3681
+ try {
3682
apftunnel.disconnect();
3683
response = "Stopped APF tunnel";
4256
- } catch (e)
4257
- {
3684
+ } catch (e) {
3685
response = JSON.stringify(e);
3686
}
3687
apftunnel = null;
4261
- } else
4262
- {
3688
+ } else {
3689
response = "Invalid command.\r\nUse: apf lms|relay|cira|off";
3690
}
4265
- } else
4266
- {
3691
+ } else {
3692
response = "APF tunnel is " + (apftunnel == null ? "off" : "on") + "\r\nUse: apf lms|relay|cira|off";
3693
}
4269
- } else
4270
- {
3694
+ } else {
3695
response = "APF tunnel requires Intel AMT";
3696
}
3697
break;
3698
}
3699
case 'plugin': {
4276
- if (typeof args['_'][0] == 'string')
4277
- {
4278
- try
4279
- {
3700
+ if (typeof args['_'][0] == 'string') {
3701
+ try {
3702
// Pass off the action to the plugin
3703
// for plugin creators, you'll want to have a plugindir/modules_meshcore/plugin.js
3704
// to control the output / actions here.
3705
response = require(args['_'][0]).consoleaction(args, rights, sessionid, mesh);
4284
- } catch (e)
4285
- {
3706
+ } catch (e) {
3707
response = "There was an error in the plugin (" + e + ")";
3708
}
4288
- } else
4289
- {
3709
+ } else {
3710
response = "Proper usage: plugin [pluginName] [args].";
3711
}
3712
break;
@@ -4301,18 +3721,15 @@ function processConsoleCommand(cmd, args, rights, sessionid)
3721
}
3722
3723
// Send a mesh agent console command
4304
-function sendConsoleText(text, sessionid)
4305
-{
3724
+function sendConsoleText(text, sessionid) {
3725
if (typeof text == 'object') { text = JSON.stringify(text); }
3726
if (debugConsole && ((sessionid == null) || (sessionid == 'pipe'))) { broadcastToRegisteredApps({ cmd: 'console', value: text }); }
3727
if (sessionid != 'pipe') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: text, sessionid: sessionid }); }
3728
}
3729
3730
// Send a mesh agent message to server, placing a bubble/badge on the agent device
4312
-function sendAgentMessage(msg, icon)
4313
-{
4314
- if (sendAgentMessage.messages == null)
4315
- {
3731
+function sendAgentMessage(msg, icon) {
3732
+ if (sendAgentMessage.messages == null) {
3733
sendAgentMessage.messages = {};
3734
sendAgentMessage.nextid = 1;
3735
}
@@ -4320,48 +3737,38 @@ function sendAgentMessage(msg, icon)
3737
require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
3738
}
3739
4323
-function linux_execv(name, agentfilename, sessionid)
4324
-{
3740
+function linux_execv(name, agentfilename, sessionid) {
3741
var libs = require('monitor-info').getLibInfo('libc');
3742
var libc = null;
3743
4328
- while (libs.length > 0)
4329
- {
4330
- try
4331
- {
3744
+ while (libs.length > 0) {
3745
+ try {
3746
libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path);
3747
break;
3748
}
4335
- catch (e)
4336
- {
3749
+ catch (e) {
3750
libc = null;
3751
continue;
3752
}
3753
}
4341
- if (libc != null)
4342
- {
4343
- try
4344
- {
3754
+ if (libc != null) {
3755
+ try {
3756
libc.CreateMethod('execv');
3757
}
4347
- catch (e)
4348
- {
3758
+ catch (e) {
3759
libc = null;
3760
}
3761
}
3762
4353
- if (libc == null)
4354
- {
3763
+ if (libc == null) {
3764
// Couldn't find libc.so, fallback to using service manager to restart agent
3765
if (sessionid != null) { sendConsoleText('Restarting service via service-manager...', sessionid) }
4357
- try
4358
- {
3766
+ try {
3767
// restart service
3768
var s = require('service-manager').manager.getService(name);
3769
s.restart();
3770
}
4363
- catch (zz)
4364
- {
3771
+ catch (zz) {
3772
sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
3773
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
3774
}
@@ -4375,18 +3782,15 @@ function linux_execv(name, agentfilename, sessionid)
3782
var argarr = [];
3783
var path = require('_GenericMarshal').CreateVariable(process.execPath);
3784
4378
- if (require('MeshAgent').getStartupOptions != null)
4379
- {
3785
+ if (require('MeshAgent').getStartupOptions != null) {
3786
var options = require('MeshAgent').getStartupOptions();
4381
- for (i in options)
4382
- {
3787
+ for (i in options) {
3788
argarr.push('--' + i + '="' + options[i] + '"');
3789
}
3790
}
3791
3792
args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
4388
- for (i = 0; i < argarr.length; ++i)
4389
- {
3793
+ for (i = 0; i < argarr.length; ++i) {
3794
var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
3795
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
3796
}
@@ -4396,8 +3800,7 @@ function linux_execv(name, agentfilename, sessionid)
3800
sendAgentMessage('Self Update failed because execv() failed', 3);
3801
}
3802
4399
-function bsd_execv(name, agentfilename, sessionid)
4400
-{
3803
+function bsd_execv(name, agentfilename, sessionid) {
3804
var child = require('child_process').execFile('/bin/sh', ['sh']);
3805
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3806
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
@@ -4412,21 +3815,18 @@ function bsd_execv(name, agentfilename, sessionid)
3815
child.stdin.write(' }');
3816
child.stdin.write("}'\nexit\n");
3817
child.waitExit();
4415
- if (child.stdout.str.trim() == '')
4416
- {
3818
+ if (child.stdout.str.trim() == '') {
3819
if (sessionid != null) { sendConsoleText('Self Update failed because cannot find libc.so', sessionid) }
3820
sendAgentMessage('Self Update failed because cannot find libc.so', 3);
3821
return;
3822
}
3823
3824
var libc = null;
4423
- try
4424
- {
3825
+ try {
3826
libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim());
3827
libc.CreateMethod('execv');
3828
}
4428
- catch (e)
4429
- {
3829
+ catch (e) {
3830
if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) }
3831
sendAgentMessage('Self Update failed: ' + e.toString(), 3);
3832
return;
@@ -4437,13 +3837,11 @@ function bsd_execv(name, agentfilename, sessionid)
3837
var argarr = [];
3838
var args;
3839
var options = require('MeshAgent').getStartupOptions();
4440
- for (i in options)
4441
- {
3840
+ for (i in options) {
3841
argarr.push('--' + i + '="' + options[i] + '"');
3842
}
3843
args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
4445
- for (i = 0; i < argarr.length; ++i)
4446
- {
3844
+ for (i = 0; i < argarr.length; ++i) {
3845
var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
3846
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
3847
}
@@ -4454,16 +3852,13 @@ function bsd_execv(name, agentfilename, sessionid)
3852
sendAgentMessage('Self Update failed because execv() failed', 3);
3853
}
3854
4457
-function windows_execve(name, agentfilename, sessionid)
4458
-{
3855
+function windows_execve(name, agentfilename, sessionid) {
3856
var libc;
4460
- try
4461
- {
3857
+ try {
3858
libc = require('_GenericMarshal').CreateNativeProxy('msvcrt.dll');
3859
libc.CreateMethod('_wexecve');
3860
}
4465
- catch (xx)
4466
- {
3861
+ catch (xx) {
3862
sendConsoleText('Self Update failed because msvcrt.dll is missing', sessionid);
3863
sendAgentMessage('Self Update failed because msvcrt.dll is missing', 3);
3864
return;
@@ -4481,42 +3876,34 @@ function windows_execve(name, agentfilename, sessionid)
3876
}
3877
3878
// Start a JavaScript based Agent Self-Update
4484
-function agentUpdate_Start(updateurl, updateoptions)
4485
-{
3879
+function agentUpdate_Start(updateurl, updateoptions) {
3880
// If this value is null
3881
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
3882
4489
- if (agentUpdate_Start._selfupdate != null)
4490
- {
3883
+ if (agentUpdate_Start._selfupdate != null) {
3884
// We were already called, so we will ignore this duplicate request
3885
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
3886
}
4494
- else
4495
- {
3887
+ else {
3888
if (agentUpdate_Start._retryCount == null) { agentUpdate_Start._retryCount = 0; }
4497
- if (require('MeshAgent').ARCHID == null && updateurl == null)
4498
- {
3889
+ if (require('MeshAgent').ARCHID == null && updateurl == null) {
3890
// This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
3891
sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
3892
}
4502
- else
4503
- {
3893
+ else {
3894
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
3895
var name = require('MeshAgent').serviceName;
3896
if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; } // This is an older agent that doesn't expose the service name, so use the default
4507
- try
4508
- {
3897
+ try {
3898
var s = require('service-manager').manager.getService(name);
4510
- if (!s.isMe())
4511
- {
3899
+ if (!s.isMe()) {
3900
if (process.platform == 'win32') { s.close(); }
3901
sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
3902
return;
3903
}
3904
if (process.platform == 'win32') { s.close(); }
3905
}
4518
- catch (zz)
4519
- {
3906
+ catch (zz) {
3907
sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
3908
sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
3909
return;
@@ -4527,15 +3914,13 @@ function agentUpdate_Start(updateurl, updateoptions)
3914
options.protocol = 'https:';
3915
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
3916
options.rejectUnauthorized = false;
4530
- options.checkServerIdentity = function checkServerIdentity(certs)
4531
- {
3917
+ options.checkServerIdentity = function checkServerIdentity(certs) {
3918
// If the tunnel certificate matches the control channel certificate, accept the connection
3919
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
3920
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
3921
3922
// Check that the certificate is the one expected by the server, fail if not.
4537
- if (checkServerIdentity.servertlshash == null)
4538
- {
3923
+ if (checkServerIdentity.servertlshash == null) {
3924
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
3925
3926
sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
@@ -4543,8 +3928,7 @@ function agentUpdate_Start(updateurl, updateoptions)
3928
throw new Error('BadCert');
3929
}
3930
if (certs[0].digest == null) { return; }
4546
- if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
4547
- {
3931
+ if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) {
3932
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
3933
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
3934
throw new Error('BadCert')
@@ -4552,46 +3936,37 @@ function agentUpdate_Start(updateurl, updateoptions)
3936
}
3937
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
3938
agentUpdate_Start._selfupdate = require('https').get(options);
4555
- agentUpdate_Start._selfupdate.on('error', function (e)
4556
- {
3939
+ agentUpdate_Start._selfupdate.on('error', function (e) {
3940
sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
3941
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
3942
});
4560
- agentUpdate_Start._selfupdate.on('response', function (img)
4561
- {
3943
+ agentUpdate_Start._selfupdate.on('response', function (img) {
3944
this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
3945
this._filehash = require('SHA384Stream').create();
4564
- this._filehash.on('hash', function (h)
4565
- {
4566
- if (updateoptions != null && updateoptions.hash != null)
4567
- {
4568
- if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
4569
- {
3946
+ this._filehash.on('hash', function (h) {
3947
+ if (updateoptions != null && updateoptions.hash != null) {
3948
+ if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) {
3949
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
3950
}
4572
- else
4573
- {
3951
+ else {
3952
agentUpdate_Start._retryCount++;
3953
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', sessionid);
3954
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', 3);
3955
agentUpdate_Start._selfupdate = null;
3956
4579
- if (agentUpdate_Start._retryCount < 4)
4580
- {
3957
+ if (agentUpdate_Start._retryCount < 4) {
3958
// Retry the download again
3959
sendConsoleText('Self Update will try again in 60 seconds...', sessionid);
3960
agentUpdate_Start._timeout = setTimeout(agentUpdate_Start, 60000, updateurl, updateoptions);
3961
}
4585
- else
4586
- {
3962
+ else {
3963
sendConsoleText('Self Update giving up, too many failures...', sessionid);
3964
sendAgentMessage('Self Update giving up, too many failures...', 3);
3965
}
3966
return;
3967
}
3968
}
4593
- else
4594
- {
3969
+ else {
3970
sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
3971
}
3972
@@ -4599,13 +3974,11 @@ function agentUpdate_Start(updateurl, updateoptions)
3974
try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
3975
3976
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
4602
- if (process.platform == 'win32')
4603
- {
3977
+ if (process.platform == 'win32') {
3978
// Use _wexecve() equivalent to perform the update
3979
windows_execve(name, agentfilename, sessionid);
3980
}
4607
- else
4608
- {
3981
+ else {
3982
var m = require('fs').statSync(process.execPath).mode;
3983
require('fs').chmodSync(process.cwd() + agentfilename + '.update', m);
3984
@@ -4619,8 +3992,7 @@ function agentUpdate_Start(updateurl, updateoptions)
3992
// erase update
3993
require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
3994
4622
- switch (process.platform)
4623
- {
3995
+ switch (process.platform) {
3996
case 'freebsd':
3997
bsd_execv(name, agentfilename, sessionid);
3998
break;
@@ -4628,14 +4000,12 @@ function agentUpdate_Start(updateurl, updateoptions)
4000
linux_execv(name, agentfilename, sessionid);
4001
break;
4002
default:
4631
- try
4632
- {
4003
+ try {
4004
// restart service
4005
var s = require('service-manager').manager.getService(name);
4006
s.restart();
4007
}
4637
- catch (zz)
4638
- {
4008
+ catch (zz) {
4009
sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
4010
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
4011
}
@@ -4657,16 +4027,13 @@ function agentUpdate_Start(updateurl, updateoptions)
4027
//process.exit = function (code) { console.log("Exit with code: " + code.toString()); }
4028
4029
// Called when the server connection state changes
4660
-function handleServerConnection(state)
4661
-{
4030
+function handleServerConnection(state) {
4031
meshServerConnectionState = state;
4663
- if (meshServerConnectionState == 0)
4664
- {
4032
+ if (meshServerConnectionState == 0) {
4033
// Server disconnected
4034
if (selfInfoUpdateTimer != null) { clearInterval(selfInfoUpdateTimer); selfInfoUpdateTimer = null; }
4035
lastSelfInfo = null;
4668
- } else
4669
- {
4036
+ } else {
4037
// Server connected, send mesh core information
4038
var oldNodeId = db.Get('OldNodeId');
4039
if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: oldNodeId }); }
@@ -4677,15 +4044,13 @@ function handleServerConnection(state)
4044
// Update the server on with basic info, logged in users and more advanced stuff, like Intel ME and Network Settings
4045
meInfoStr = null;
4046
sendPeriodicServerUpdate(null, true);
4680
- if (selfInfoUpdateTimer == null)
4681
- {
4047
+ if (selfInfoUpdateTimer == null) {
4048
selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 1200000); // 20 minutes
4049
selfInfoUpdateTimer.metadata = 'meshcore (InfoUpdate Timer)';
4050
}
4051
4052
// Send any state messages
4687
- if (Object.keys(tunnelUserCount.msg).length > 0)
4688
- {
4053
+ if (Object.keys(tunnelUserCount.msg).length > 0) {
4054
try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (e) { }
4055
broadcastSessionsToRegisteredApps();
4056
}
@@ -4701,14 +4066,12 @@ function handleServerConnection(state)
4066
// Update the server with the latest network interface information
4067
var sendNetworkUpdateNagleTimer = null;
4068
function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); }
4704
-function sendNetworkUpdate(force)
4705
-{
4069
+function sendNetworkUpdate(force) {
4070
sendNetworkUpdateNagleTimer = null;
4071
4072
// Update the network interfaces information data
4073
var netInfo = { netif2: require('os').networkInterfaces() };
4710
- if (netInfo.netif2)
4711
- {
4074
+ if (netInfo.netif2) {
4075
netInfo.action = 'netinfo';
4076
var netInfoStr = JSON.stringify(netInfo);
4077
if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
@@ -4716,17 +4079,14 @@ function sendNetworkUpdate(force)
4079
}
4080
4081
// Called periodically to check if we need to send updates to the server
4719
-function sendPeriodicServerUpdate(flags, force)
4720
-{
4082
+function sendPeriodicServerUpdate(flags, force) {
4083
if (meshServerConnectionState == 0) return; // Not connected to server, do nothing.
4084
if (!flags) { flags = 0xFFFFFFFF; }
4085
4086
// If we have a connected MEI, get Intel ME information
4725
- if ((flags & 1) && (amt != null) && (amt.state == 2))
4726
- {
4087
+ if ((flags & 1) && (amt != null) && (amt.state == 2)) {
4088
delete meshCoreObj.intelamt;
4728
- amt.getMeiState(9, function (meinfo)
4729
- {
4089
+ amt.getMeiState(9, function (meinfo) {
4090
meshCoreObj.intelamt = meinfo;
4091
meshCoreObj.intelamt.microlms = amt.lmsstate;
4092
meshCoreObjChanged();
@@ -4737,40 +4097,30 @@ function sendPeriodicServerUpdate(flags, force)
4097
if (flags & 2) { sendNetworkUpdateNagle(false); }
4098
4099
// Update anti-virus information
4740
- if ((flags & 4) && (process.platform == 'win32'))
4741
- {
4100
+ if ((flags & 4) && (process.platform == 'win32')) {
4101
// Windows Command: "wmic /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct get /FORMAT:CSV"
4102
try { meshCoreObj.av = require('win-info').av(); meshCoreObjChanged(); } catch (e) { av = null; } // Antivirus
4103
//if (process.platform == 'win32') { try { meshCoreObj.pr = require('win-info').pendingReboot(); meshCoreObjChanged(); } catch (e) { meshCoreObj.pr = null; } } // Pending reboot
4104
}
4746
- if (process.platform == 'win32')
4747
- {
4748
- if (require('MeshAgent')._securitycenter == null)
4749
- {
4750
- try
4751
- {
4105
+ if (process.platform == 'win32') {
4106
+ if (require('MeshAgent')._securitycenter == null) {
4107
+ try {
4108
require('MeshAgent')._securitycenter = require('win-securitycenter').status();
4753
- meshCoreObj['windowsSecurityCenter'] = require('MeshAgent')._securitycenter;
4754
- require('win-securitycenter').on('changed', function ()
4755
- {
4109
+ meshCoreObj['wsc'] = require('MeshAgent')._securitycenter; // Windows Security Central (WSC)
4110
+ require('win-securitycenter').on('changed', function () {
4111
require('MeshAgent')._securitycenter = require('win-securitycenter').status();
4757
- meshCoreObj['windowsSecurityCenter'] = require('MeshAgent')._securitycenter;
4758
- require('MeshAgent').SendCommand({ action: 'coreinfo', windowsSecurityCenter: require('MeshAgent')._securitycenter });
4112
+ meshCoreObj['wsc'] = require('MeshAgent')._securitycenter; // Windows Security Central (WSC)
4113
+ require('MeshAgent').SendCommand({ action: 'coreinfo', wsc: require('MeshAgent')._securitycenter });
4114
});
4760
- }
4761
- catch (e)
4762
- {
4763
- }
4115
+ } catch (e) { }
4116
}
4117
}
4118
4119
// Send available data right now
4768
- if (force)
4769
- {
4120
+ if (force) {
4121
meshCoreObj = sortObjRec(meshCoreObj);
4122
var x = JSON.stringify(meshCoreObj);
4772
- if (x != LastPeriodicServerUpdate)
4773
- {
4123
+ if (x != LastPeriodicServerUpdate) {
4124
LastPeriodicServerUpdate = x;
4125
mesh.SendCommand(meshCoreObj);
4126
}
@@ -4780,20 +4130,16 @@ function sendPeriodicServerUpdate(flags, force)
4130
// Once we are done collecting all the data, send to server if needed
4131
var LastPeriodicServerUpdate = null;
4132
var PeriodicServerUpdateNagleTimer = null;
4783
-function meshCoreObjChanged()
4784
-{
4785
- if (PeriodicServerUpdateNagleTimer == null)
4786
- {
4133
+function meshCoreObjChanged() {
4134
+ if (PeriodicServerUpdateNagleTimer == null) {
4135
PeriodicServerUpdateNagleTimer = setTimeout(meshCoreObjChangedEx, 500);
4136
}
4137
}
4790
-function meshCoreObjChangedEx()
4791
-{
4138
+function meshCoreObjChangedEx() {
4139
PeriodicServerUpdateNagleTimer = null;
4140
meshCoreObj = sortObjRec(meshCoreObj);
4141
var x = JSON.stringify(meshCoreObj);
4795
- if (x != LastPeriodicServerUpdate)
4796
- {
4142
+ if (x != LastPeriodicServerUpdate) {
4143
try { LastPeriodicServerUpdate = x; mesh.SendCommand(meshCoreObj); } catch (ex) { }
4144
}
4145
}
@@ -4805,8 +4151,7 @@ function onWebSocketClosed() { sendConsoleText("WebSocket #" + this.httprequest.
4151
function onWebSocketData(data) { sendConsoleText("Got WebSocket #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); }
4152
function onWebSocketSendOk() { sendConsoleText("WebSocket #" + this.index + " SendOK.", this.sessionid); }
4153
4808
-function onWebSocketUpgrade(response, s, head)
4809
-{
4154
+function onWebSocketUpgrade(response, s, head) {
4155
sendConsoleText("WebSocket #" + this.index + " connected.", this.sessionid);
4156
this.s = s;
4157
s.httprequest = this;
meshagent.js
+6
-2
@@ -1576,9 +1576,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1576
}
1577
if ((command.intelamt.UUID != null) && (typeof command.intelamt.UUID == 'string') && (device.intelamt.uuid != command.intelamt.UUID)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.UUID; change = 1; log = 1; }
1578
}
1579
- if (command.av) {
1579
+ if (command.av != null) { // Antivirus
1580
if (!device.av) { device.av = []; }
1581
- if ((command.av != null) && (JSON.stringify(device.av) != JSON.stringify(command.av))) { /*changes.push('AV status');*/ device.av = command.av; change = 1; log = 1; }
1581
+ if (JSON.stringify(device.av) != JSON.stringify(command.av)) { /*changes.push('AV status');*/ device.av = command.av; change = 1; log = 1; }
1582
+ }
1583
+ if (command.wsc != null) { // Windows Security Center
1584
+ if (!device.wsc) { device.wsc = {}; }
1585
+ if (JSON.stringify(device.wsc) != JSON.stringify(command.wsc)) { /*changes.push('Windows Security Center status');*/ device.wsc = command.wsc; change = 1; log = 1; }
1586
}
1587
1588
if ((command.users != null) && (Array.isArray(command.users)) && (device.users != command.users)) { device.users = command.users; change = 1; } // Don't save this to the db.
translate/translate.json
+1883
-1823
@@ -17,8 +17,8 @@
17
"zh-chs": " + CIRA",
18
"zh-cht": " + CIRA",
19
"xloc": [
20
- "default.handlebars->31->1430",
21
- "default.handlebars->31->1432"
20
+ "default.handlebars->31->1443",
21
+ "default.handlebars->31->1445"
22
]
23
},
24
{
@@ -204,7 +204,7 @@
204
"zh-chs": " 可以使用密码提示,但不建议使用。",
205
"zh-cht": " 可以使用密碼提示,但不建議使用。",
206
"xloc": [
207
- "default.handlebars->31->1343"
207
+ "default.handlebars->31->1356"
208
]
209
},
210
{
@@ -224,8 +224,8 @@
224
"zh-chs": " 用户需要先登录到该服务器一次,然后才能将其添加到设备组。",
225
"zh-cht": " 用戶需要先登入到該伺服器一次,然後才能將其新增到裝置群。",
226
"xloc": [
227
- "default.handlebars->31->1507",
228
- "default.handlebars->31->1971"
227
+ "default.handlebars->31->1520",
228
+ "default.handlebars->31->1984"
229
]
230
},
231
{
@@ -432,7 +432,7 @@
432
"zh-chs": "* 8个字符,1个大写,1个小写,1个数字,1个非字母数字。",
433
"zh-cht": "* 8個字符,1個大寫,1個小寫,1個數字,1個非字母數字。",
434
"xloc": [
435
- "default.handlebars->31->1476",
435
+ "default.handlebars->31->1489",
436
"default.handlebars->31->323"
437
]
438
},
@@ -507,8 +507,8 @@
507
"zh-chs": ",",
508
"zh-cht": ",",
509
"xloc": [
510
- "default-mobile.handlebars->11->515",
511
- "default.handlebars->31->1577"
510
+ "default-mobile.handlebars->11->532",
511
+ "default.handlebars->31->1590"
512
]
513
},
514
{
@@ -549,7 +549,7 @@
549
"zh-chs": ",MQTT在线",
550
"zh-cht": ",MQTT在線",
551
"xloc": [
552
- "default.handlebars->31->1084"
552
+ "default.handlebars->31->1097"
553
]
554
},
555
{
@@ -557,7 +557,7 @@
557
"fr": ", Pas de consentement",
558
"nl": ", Geen toestemming",
559
"xloc": [
560
- "default.handlebars->31->697"
560
+ "default.handlebars->31->710"
561
]
562
},
563
{
@@ -577,7 +577,7 @@
577
"zh-chs": ",提示同意",
578
"zh-cht": ",提示同意",
579
"xloc": [
580
- "default.handlebars->31->698"
580
+ "default.handlebars->31->711"
581
]
582
},
583
{
@@ -597,7 +597,7 @@
597
"zh-chs": ",软体KVM",
598
"zh-cht": ",軟體KVM",
599
"xloc": [
600
- "default.handlebars->31->870",
600
+ "default.handlebars->31->883",
601
"desktop.handlebars->3->12"
602
]
603
},
@@ -606,14 +606,14 @@
606
"fr": ", barre d'outils",
607
"nl": ", Werkbalk",
608
"xloc": [
609
- "default.handlebars->31->699"
609
+ "default.handlebars->31->712"
610
]
611
},
612
{
613
"en": ", View only",
614
"nl": ", Alleen kijken",
615
"xloc": [
616
- "default.handlebars->31->696"
616
+ "default.handlebars->31->709"
617
]
618
},
619
{
@@ -635,9 +635,9 @@
635
"xloc": [
636
"default-mobile.handlebars->11->314",
637
"default-mobile.handlebars->11->347",
638
- "default.handlebars->31->877",
639
- "default.handlebars->31->936",
640
- "default.handlebars->31->948",
638
+ "default.handlebars->31->890",
639
+ "default.handlebars->31->949",
640
+ "default.handlebars->31->961",
641
"desktop.handlebars->3->19",
642
"terminal.handlebars->3->9",
643
"xterm.handlebars->9->6"
@@ -760,7 +760,7 @@
760
"zh-chs": ",{0}观看",
761
"zh-cht": ",{0}觀看",
762
"xloc": [
763
- "default.handlebars->31->871",
763
+ "default.handlebars->31->884",
764
"desktop.handlebars->3->13"
765
]
766
},
@@ -825,9 +825,9 @@
825
"xloc": [
826
"default-mobile.handlebars->11->119",
827
"default-mobile.handlebars->11->349",
828
- "default.handlebars->31->1618",
829
- "default.handlebars->31->2130",
830
- "default.handlebars->31->954"
828
+ "default.handlebars->31->1631",
829
+ "default.handlebars->31->2143",
830
+ "default.handlebars->31->967"
831
]
832
},
833
{
@@ -884,7 +884,7 @@
884
"zh-chs": "1个活跃时段",
885
"zh-cht": "1個活躍時段",
886
"xloc": [
887
- "default.handlebars->31->2042"
887
+ "default.handlebars->31->2055"
888
]
889
},
890
{
@@ -905,8 +905,8 @@
905
"zh-cht": "1個位元組",
906
"xloc": [
907
"default-mobile.handlebars->11->129",
908
- "default-mobile.handlebars->11->558",
909
- "default.handlebars->31->1642",
908
+ "default-mobile.handlebars->11->575",
909
+ "default.handlebars->31->1655",
910
"download.handlebars->3->1",
911
"download2.handlebars->5->1"
912
]
@@ -928,7 +928,7 @@
928
"zh-chs": "1条连接",
929
"zh-cht": "1位聯絡文",
930
"xloc": [
931
- "default.handlebars->31->873",
931
+ "default.handlebars->31->886",
932
"desktop.handlebars->3->15"
933
]
934
},
@@ -971,7 +971,7 @@
971
"zh-chs": "1组",
972
"zh-cht": "1群",
973
"xloc": [
974
- "default.handlebars->31->2005"
974
+ "default.handlebars->31->2018"
975
]
976
},
977
{
@@ -1013,7 +1013,7 @@
1013
"zh-chs": "1分钟",
1014
"zh-cht": "1分鐘",
1015
"xloc": [
1016
- "default.handlebars->31->753"
1016
+ "default.handlebars->31->766"
1017
]
1018
},
1019
{
@@ -1075,7 +1075,7 @@
1075
"zh-chs": "有1个用户没有显示,请使用搜索框查找用户...",
1076
"zh-cht": "有1個用戶沒有顯示,請使用搜尋框搜尋用戶...",
1077
"xloc": [
1078
- "default.handlebars->31->1795"
1078
+ "default.handlebars->31->1808"
1079
]
1080
},
1081
{
@@ -1141,7 +1141,7 @@
1141
"default-mobile.handlebars->11->183",
1142
"default-mobile.handlebars->11->186",
1143
"default-mobile.handlebars->11->189",
1144
- "default.handlebars->31->1799",
1144
+ "default.handlebars->31->1812",
1145
"default.handlebars->31->268",
1146
"default.handlebars->31->271",
1147
"default.handlebars->31->274",
@@ -1273,7 +1273,7 @@
1273
"zh-chs": "10分钟",
1274
"zh-cht": "10分鐘",
1275
"xloc": [
1276
- "default.handlebars->31->755"
1276
+ "default.handlebars->31->768"
1277
]
1278
},
1279
{
@@ -1356,7 +1356,7 @@
1356
"zh-chs": "12小时",
1357
"zh-cht": "12小時",
1358
"xloc": [
1359
- "default.handlebars->31->763"
1359
+ "default.handlebars->31->776"
1360
]
1361
},
1362
{
@@ -1398,7 +1398,7 @@
1398
"zh-chs": "15分钟",
1399
"zh-cht": "15分鐘",
1400
"xloc": [
1401
- "default.handlebars->31->756"
1401
+ "default.handlebars->31->769"
1402
]
1403
},
1404
{
@@ -1418,7 +1418,7 @@
1418
"zh-chs": "16小时",
1419
"zh-cht": "16小時",
1420
"xloc": [
1421
- "default.handlebars->31->764"
1421
+ "default.handlebars->31->777"
1422
]
1423
},
1424
{
@@ -1438,7 +1438,7 @@
1438
"zh-chs": "2天",
1439
"zh-cht": "2天",
1440
"xloc": [
1441
- "default.handlebars->31->766"
1441
+ "default.handlebars->31->779"
1442
]
1443
},
1444
{
@@ -1458,7 +1458,7 @@
1458
"zh-chs": "2小时",
1459
"zh-cht": "2小時",
1460
"xloc": [
1461
- "default.handlebars->31->760"
1461
+ "default.handlebars->31->773"
1462
]
1463
},
1464
{
@@ -1562,7 +1562,7 @@
1562
"zh-chs": "24小时",
1563
"zh-cht": "24小時",
1564
"xloc": [
1565
- "default.handlebars->31->765"
1565
+ "default.handlebars->31->778"
1566
]
1567
},
1568
{
@@ -1624,7 +1624,7 @@
1624
"zh-chs": "2FA备份代码已清除",
1625
"zh-cht": "2FA備份代碼已清除",
1626
"xloc": [
1627
- "default.handlebars->31->1753"
1627
+ "default.handlebars->31->1766"
1628
]
1629
},
1630
{
@@ -1644,8 +1644,8 @@
1644
"zh-chs": "启用第二因素身份验证",
1645
"zh-cht": "啟用第二因素身份驗證",
1646
"xloc": [
1647
- "default.handlebars->31->1812",
1648
- "default.handlebars->31->2027"
1647
+ "default.handlebars->31->1825",
1648
+ "default.handlebars->31->2040"
1649
]
1650
},
1651
{
@@ -1764,7 +1764,7 @@
1764
"zh-chs": "30分钟",
1765
"zh-cht": "30分鐘",
1766
"xloc": [
1767
- "default.handlebars->31->757"
1767
+ "default.handlebars->31->770"
1768
]
1769
},
1770
{
@@ -1827,7 +1827,7 @@
1827
"zh-chs": "4天",
1828
"zh-cht": "4天",
1829
"xloc": [
1830
- "default.handlebars->31->767"
1830
+ "default.handlebars->31->780"
1831
]
1832
},
1833
{
@@ -1847,7 +1847,7 @@
1847
"zh-chs": "4个小时",
1848
"zh-cht": "4個小時",
1849
"xloc": [
1850
- "default.handlebars->31->761"
1850
+ "default.handlebars->31->774"
1851
]
1852
},
1853
{
@@ -1930,7 +1930,7 @@
1930
"zh-chs": "45分钟",
1931
"zh-cht": "45分鐘",
1932
"xloc": [
1933
- "default.handlebars->31->758"
1933
+ "default.handlebars->31->771"
1934
]
1935
},
1936
{
@@ -1970,7 +1970,7 @@
1970
"zh-chs": "5分钟",
1971
"zh-cht": "5分鐘",
1972
"xloc": [
1973
- "default.handlebars->31->754"
1973
+ "default.handlebars->31->767"
1974
]
1975
},
1976
{
@@ -2096,7 +2096,7 @@
2096
"zh-chs": "60分钟",
2097
"zh-cht": "60分鐘",
2098
"xloc": [
2099
- "default.handlebars->31->759"
2099
+ "default.handlebars->31->772"
2100
]
2101
},
2102
{
@@ -2216,7 +2216,7 @@
2216
"zh-chs": "7天电源状态",
2217
"zh-cht": "7天電源狀態",
2218
"xloc": [
2219
- "default.handlebars->31->798"
2219
+ "default.handlebars->31->811"
2220
]
2221
},
2222
{
@@ -2281,7 +2281,7 @@
2281
"xloc": [
2282
"default.handlebars->31->347",
2283
"default.handlebars->31->361",
2284
- "default.handlebars->31->762"
2284
+ "default.handlebars->31->775"
2285
]
2286
},
2287
{
@@ -2513,7 +2513,7 @@
2513
"zh-cht": "ACM",
2514
"xloc": [
2515
"default-mobile.handlebars->11->247",
2516
- "default.handlebars->31->1446",
2516
+ "default.handlebars->31->1459",
2517
"default.handlebars->31->588"
2518
]
2519
},
@@ -2677,6 +2677,15 @@
2677
"default.handlebars->31->39"
2678
]
2679
},
2680
+ {
2681
+ "en": "AV",
2682
+ "xloc": [
2683
+ "default-mobile.handlebars->11->385",
2684
+ "default-mobile.handlebars->11->387",
2685
+ "default.handlebars->31->607",
2686
+ "default.handlebars->31->609"
2687
+ ]
2688
+ },
2689
{
2690
"cs": "Přístup odepřen",
2691
"de": "Zugriff verweigert",
@@ -2694,7 +2703,7 @@
2703
"zh-chs": "拒绝访问",
2704
"zh-cht": "拒絕存取",
2705
"xloc": [
2697
- "default.handlebars->31->1085"
2706
+ "default.handlebars->31->1098"
2707
]
2708
},
2709
{
@@ -2736,7 +2745,7 @@
2745
"zh-chs": "访问服务器档案",
2746
"zh-cht": "存取伺服器檔案",
2747
"xloc": [
2739
- "default.handlebars->31->1977"
2748
+ "default.handlebars->31->1990"
2749
]
2750
},
2751
{
@@ -2825,9 +2834,9 @@
2834
"default-mobile.handlebars->11->222",
2835
"default-mobile.handlebars->11->224",
2836
"default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->1->0",
2828
- "default.handlebars->31->1352",
2829
- "default.handlebars->31->1354",
2830
- "default.handlebars->31->2244",
2837
+ "default.handlebars->31->1365",
2838
+ "default.handlebars->31->1367",
2839
+ "default.handlebars->31->2257",
2840
"default.handlebars->31->557",
2841
"default.handlebars->31->559"
2842
]
@@ -2837,8 +2846,8 @@
2846
"nl": "Account instellingen",
2847
"fr": "Paramètres du compte",
2848
"xloc": [
2840
- "default-mobile.handlebars->11->526",
2841
- "default.handlebars->31->2138"
2849
+ "default-mobile.handlebars->11->543",
2850
+ "default.handlebars->31->2151"
2851
]
2852
},
2853
{
@@ -2899,7 +2908,7 @@
2908
"zh-chs": "帐户已更改:{0}",
2909
"zh-cht": "帳戶已更改:{0}",
2910
"xloc": [
2902
- "default.handlebars->31->1726"
2911
+ "default.handlebars->31->1739"
2912
]
2913
},
2914
{
@@ -2919,7 +2928,7 @@
2928
"zh-chs": "创建帐户,电子邮件为{0}",
2929
"zh-cht": "創建帳戶,電子郵件為{0}",
2930
"xloc": [
2922
- "default.handlebars->31->1725"
2931
+ "default.handlebars->31->1738"
2932
]
2933
},
2934
{
@@ -2939,7 +2948,7 @@
2948
"zh-chs": "创建帐户,用户名是{0}",
2949
"zh-cht": "帳戶已創建,用戶名是{0}",
2950
"xloc": [
2942
- "default.handlebars->31->1724"
2951
+ "default.handlebars->31->1737"
2952
]
2953
},
2954
{
@@ -2959,8 +2968,8 @@
2968
"zh-chs": "帐户已被锁定",
2969
"zh-cht": "帳戶已被鎖定",
2970
"xloc": [
2962
- "default.handlebars->31->1814",
2963
- "default.handlebars->31->1974"
2971
+ "default.handlebars->31->1827",
2972
+ "default.handlebars->31->1987"
2973
]
2974
},
2975
{
@@ -2980,8 +2989,8 @@
2989
"zh-chs": "达到帐户限制。",
2990
"zh-cht": "達到帳戶限制。",
2991
"xloc": [
2983
- "default-mobile.handlebars->11->538",
2984
- "default.handlebars->31->2150",
2992
+ "default-mobile.handlebars->11->555",
2993
+ "default.handlebars->31->2163",
2994
"login-mobile.handlebars->5->6",
2995
"login.handlebars->5->6",
2996
"login2.handlebars->7->7"
@@ -3026,7 +3035,7 @@
3035
"zh-chs": "帐号登录",
3036
"zh-cht": "帳號登錄",
3037
"xloc": [
3029
- "default.handlebars->31->1661"
3038
+ "default.handlebars->31->1674"
3039
]
3040
},
3041
{
@@ -3046,7 +3055,7 @@
3055
"zh-chs": "帐户登出",
3056
"zh-cht": "帳戶登出",
3057
"xloc": [
3049
- "default.handlebars->31->1662"
3058
+ "default.handlebars->31->1675"
3059
]
3060
},
3061
{
@@ -3088,7 +3097,7 @@
3097
"zh-chs": "帐户密码已更改:{0}",
3098
"zh-cht": "帳戶密碼已更改:{0}",
3099
"xloc": [
3091
- "default.handlebars->31->1734"
3100
+ "default.handlebars->31->1747"
3101
]
3102
},
3103
{
@@ -3108,7 +3117,7 @@
3117
"zh-chs": "帐户已删除",
3118
"zh-cht": "帳戶已刪除",
3119
"xloc": [
3111
- "default.handlebars->31->1723"
3120
+ "default.handlebars->31->1736"
3121
]
3122
},
3123
{
@@ -3148,7 +3157,7 @@
3157
"zh-chs": "指令",
3158
"zh-cht": "指令",
3159
"xloc": [
3151
- "default.handlebars->31->1090",
3160
+ "default.handlebars->31->1103",
3161
"default.handlebars->container->column_l->p42->p42tbl->1->0->8"
3162
]
3163
},
@@ -3169,8 +3178,8 @@
3178
"zh-chs": "动作档案",
3179
"zh-cht": "動作檔案",
3180
"xloc": [
3172
- "default.handlebars->31->844",
3173
- "default.handlebars->31->846"
3181
+ "default.handlebars->31->857",
3182
+ "default.handlebars->31->859"
3183
]
3184
},
3185
{
@@ -3193,7 +3202,7 @@
3202
"default-mobile.handlebars->11->270",
3203
"default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3",
3204
"default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->1",
3196
- "default.handlebars->31->637",
3205
+ "default.handlebars->31->650",
3206
"default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
3207
"default.handlebars->container->column_l->p12->termTable->1->1->0->1->1",
3208
"default.handlebars->container->column_l->p13->p13toolbar->1->0->1->1"
@@ -3276,7 +3285,7 @@
3285
"zh-chs": "如果ACM失败,则激活到CCM",
3286
"zh-cht": "如果ACM失敗,則激活到CCM",
3287
"xloc": [
3279
- "default.handlebars->31->1467"
3288
+ "default.handlebars->31->1480"
3289
]
3290
},
3291
{
@@ -3298,8 +3307,8 @@
3307
"xloc": [
3308
"default-mobile.handlebars->11->242",
3309
"default-mobile.handlebars->11->244",
3301
- "default-mobile.handlebars->11->418",
3302
- "default.handlebars->31->1046",
3310
+ "default-mobile.handlebars->11->435",
3311
+ "default.handlebars->31->1059",
3312
"default.handlebars->31->581",
3313
"default.handlebars->31->583"
3314
]
@@ -3341,7 +3350,7 @@
3350
"zh-chs": "主动设备共享",
3351
"zh-cht": "主動設備共享",
3352
"xloc": [
3344
- "default.handlebars->31->690"
3353
+ "default.handlebars->31->703"
3354
]
3355
},
3356
{
@@ -3367,7 +3376,7 @@
3376
"nl": "Toevoegen",
3377
"xloc": [
3378
"default-mobile.handlebars->11->340",
3370
- "default.handlebars->31->907"
3379
+ "default.handlebars->31->920"
3380
]
3381
},
3382
{
@@ -3387,7 +3396,7 @@
3396
"zh-chs": "添加代理",
3397
"zh-cht": "新增代理",
3398
"xloc": [
3390
- "default.handlebars->31->1442",
3399
+ "default.handlebars->31->1455",
3400
"default.handlebars->31->301"
3401
]
3402
},
@@ -3425,8 +3434,8 @@
3434
"zh-chs": "添加设备",
3435
"zh-cht": "新增裝置",
3436
"xloc": [
3428
- "default.handlebars->31->1951",
3429
- "default.handlebars->31->2077"
3437
+ "default.handlebars->31->1964",
3438
+ "default.handlebars->31->2090"
3439
]
3440
},
3441
{
@@ -3446,7 +3455,7 @@
3455
"zh-chs": "添加设备日志",
3456
"zh-cht": "新增裝置日誌",
3457
"xloc": [
3449
- "default.handlebars->31->739"
3458
+ "default.handlebars->31->752"
3459
]
3460
},
3461
{
@@ -3466,9 +3475,9 @@
3475
"zh-chs": "添加设备组",
3476
"zh-cht": "新增裝置群",
3477
"xloc": [
3469
- "default.handlebars->31->1541",
3470
- "default.handlebars->31->1945",
3471
- "default.handlebars->31->2065",
3478
+ "default.handlebars->31->1554",
3479
+ "default.handlebars->31->1958",
3480
+ "default.handlebars->31->2078",
3481
"default.handlebars->31->238"
3482
]
3483
},
@@ -3489,7 +3498,7 @@
3498
"zh-chs": "添加设备组权限",
3499
"zh-cht": "新增裝置群權限",
3500
"xloc": [
3492
- "default.handlebars->31->1538"
3501
+ "default.handlebars->31->1551"
3502
]
3503
},
3504
{
@@ -3509,8 +3518,8 @@
3518
"zh-chs": "添加设备权限",
3519
"zh-cht": "新增裝置權限",
3520
"xloc": [
3512
- "default.handlebars->31->1543",
3513
- "default.handlebars->31->1545"
3521
+ "default.handlebars->31->1556",
3522
+ "default.handlebars->31->1558"
3523
]
3524
},
3525
{
@@ -3607,7 +3616,7 @@
3616
"zh-chs": "添加成员身份",
3617
"zh-cht": "新增成員身份",
3618
"xloc": [
3610
- "default.handlebars->31->2097"
3619
+ "default.handlebars->31->2110"
3620
]
3621
},
3622
{
@@ -3647,8 +3656,8 @@
3656
"zh-chs": "添加安全密钥",
3657
"zh-cht": "新增安全密鑰",
3658
"xloc": [
3650
- "default.handlebars->31->1119",
3651
- "default.handlebars->31->1120",
3659
+ "default.handlebars->31->1132",
3660
+ "default.handlebars->31->1133",
3661
"default.handlebars->31->160",
3662
"default.handlebars->31->162",
3663
"default.handlebars->31->165",
@@ -3672,8 +3681,8 @@
3681
"zh-chs": "添加用户",
3682
"zh-cht": "新增用戶",
3683
"xloc": [
3675
- "default-mobile.handlebars->11->460",
3676
- "default.handlebars->31->682"
3684
+ "default-mobile.handlebars->11->477",
3685
+ "default.handlebars->31->695"
3686
]
3687
},
3688
{
@@ -3693,7 +3702,7 @@
3702
"zh-chs": "添加用户设备权限",
3703
"zh-cht": "新增用戶裝置權限",
3704
"xloc": [
3696
- "default.handlebars->31->1548"
3705
+ "default.handlebars->31->1561"
3706
]
3707
},
3708
{
@@ -3713,10 +3722,10 @@
3722
"zh-chs": "添加用户组",
3723
"zh-cht": "新增用戶群",
3724
"xloc": [
3716
- "default.handlebars->31->1438",
3717
- "default.handlebars->31->1540",
3718
- "default.handlebars->31->2071",
3719
- "default.handlebars->31->683"
3725
+ "default.handlebars->31->1451",
3726
+ "default.handlebars->31->1553",
3727
+ "default.handlebars->31->2084",
3728
+ "default.handlebars->31->696"
3729
]
3730
},
3731
{
@@ -3736,7 +3745,7 @@
3745
"zh-chs": "添加用户组设备权限",
3746
"zh-cht": "新增用戶群裝置權限",
3747
"xloc": [
3739
- "default.handlebars->31->1550"
3748
+ "default.handlebars->31->1563"
3749
]
3750
},
3751
{
@@ -3756,7 +3765,7 @@
3765
"zh-chs": "将用户添加到设备组",
3766
"zh-cht": "將用戶新增到裝置群",
3767
"xloc": [
3759
- "default-mobile.handlebars->11->491"
3768
+ "default-mobile.handlebars->11->508"
3769
]
3770
},
3771
{
@@ -3793,8 +3802,8 @@
3802
"zh-chs": "添加用户",
3803
"zh-cht": "新增用戶",
3804
"xloc": [
3796
- "default.handlebars->31->1437",
3797
- "default.handlebars->31->1940"
3805
+ "default.handlebars->31->1450",
3806
+ "default.handlebars->31->1953"
3807
]
3808
},
3809
{
@@ -3814,7 +3823,7 @@
3823
"zh-chs": "将用户添加到设备组",
3824
"zh-cht": "將用戶新增到裝置群",
3825
"xloc": [
3817
- "default.handlebars->31->1537"
3826
+ "default.handlebars->31->1550"
3827
]
3828
},
3829
{
@@ -3834,7 +3843,7 @@
3843
"zh-chs": "将用户添加到用户组",
3844
"zh-cht": "將用戶新增到用戶群",
3845
"xloc": [
3837
- "default.handlebars->31->1973"
3846
+ "default.handlebars->31->1986"
3847
]
3848
},
3849
{
@@ -3951,7 +3960,7 @@
3960
"zh-chs": "通过安装Mesh Agent将新计算机添加到该设备组。",
3961
"zh-cht": "通過安裝Mesh Agent將新電腦新增到該裝置群。",
3962
"xloc": [
3954
- "default.handlebars->31->1441",
3963
+ "default.handlebars->31->1454",
3964
"default.handlebars->31->300"
3965
]
3966
},
@@ -4012,7 +4021,7 @@
4021
"zh-chs": "添加了身份验证应用程序",
4022
"zh-cht": "添加了身份驗證應用程序",
4023
"xloc": [
4015
- "default.handlebars->31->1750"
4024
+ "default.handlebars->31->1763"
4025
]
4026
},
4027
{
@@ -4032,7 +4041,7 @@
4041
"zh-chs": "已将设备共享{0}从{1}添加到{2}",
4042
"zh-cht": "已將設備共享{0}從{1}添加到{2}",
4043
"xloc": [
4035
- "default.handlebars->31->1761"
4044
+ "default.handlebars->31->1774"
4045
]
4046
},
4047
{
@@ -4052,8 +4061,8 @@
4061
"zh-chs": "已将设备{0}添加到设备组{1}",
4062
"zh-cht": "已將設備{0}添加到設備組{1}",
4063
"xloc": [
4055
- "default.handlebars->31->1717",
4056
- "default.handlebars->31->1744"
4064
+ "default.handlebars->31->1730",
4065
+ "default.handlebars->31->1757"
4066
]
4067
},
4068
{
@@ -4073,7 +4082,7 @@
4082
"zh-chs": "添加了安全密钥",
4083
"zh-cht": "添加了安全密鑰",
4084
"xloc": [
4076
- "default.handlebars->31->1755"
4085
+ "default.handlebars->31->1768"
4086
]
4087
},
4088
{
@@ -4093,7 +4102,7 @@
4102
"zh-chs": "已将用户组{0}添加到设备组{1}",
4103
"zh-cht": "已將用戶組{0}添加到設備組{1}",
4104
"xloc": [
4096
- "default.handlebars->31->1728"
4105
+ "default.handlebars->31->1741"
4106
]
4107
},
4108
{
@@ -4113,8 +4122,8 @@
4122
"zh-chs": "已将用户{0}添加到用户组{1}",
4123
"zh-cht": "已將用戶{0}添加到用戶組{1}",
4124
"xloc": [
4116
- "default.handlebars->31->1731",
4117
- "default.handlebars->31->1740"
4125
+ "default.handlebars->31->1744",
4126
+ "default.handlebars->31->1753"
4127
]
4128
},
4129
{
@@ -4174,8 +4183,8 @@
4183
"zh-chs": "管理员控制模式(ACM)",
4184
"zh-cht": "管理員控制模式(ACM)",
4185
"xloc": [
4177
- "default-mobile.handlebars->11->420",
4178
- "default.handlebars->31->1048"
4186
+ "default-mobile.handlebars->11->437",
4187
+ "default.handlebars->31->1061"
4188
]
4189
},
4190
{
@@ -4195,8 +4204,8 @@
4204
"zh-chs": "管理员凭证",
4205
"zh-cht": "管理員憑證",
4206
"xloc": [
4198
- "default-mobile.handlebars->11->426",
4199
- "default.handlebars->31->1054"
4207
+ "default-mobile.handlebars->11->443",
4208
+ "default.handlebars->31->1067"
4209
]
4210
},
4211
{
@@ -4237,7 +4246,7 @@
4246
"zh-chs": "管理领域",
4247
"zh-cht": "管理領域",
4248
"xloc": [
4240
- "default.handlebars->31->2009"
4249
+ "default.handlebars->31->2022"
4250
]
4251
},
4252
{
@@ -4278,7 +4287,7 @@
4287
"zh-chs": "管理领域",
4288
"zh-cht": "管理領域",
4289
"xloc": [
4281
- "default.handlebars->31->1877"
4290
+ "default.handlebars->31->1890"
4291
]
4292
},
4293
{
@@ -4298,7 +4307,7 @@
4307
"zh-chs": "管理员",
4308
"zh-cht": "管理員",
4309
"xloc": [
4301
- "default.handlebars->31->1806"
4310
+ "default.handlebars->31->1819"
4311
]
4312
},
4313
{
@@ -4318,7 +4327,7 @@
4327
"zh-chs": "南非文",
4328
"zh-cht": "南非文",
4329
"xloc": [
4321
- "default.handlebars->31->1122"
4330
+ "default.handlebars->31->1135"
4331
]
4332
},
4333
{
@@ -4342,8 +4351,8 @@
4351
"default-mobile.handlebars->11->214",
4352
"default-mobile.handlebars->11->239",
4353
"default-mobile.handlebars->11->261",
4345
- "default.handlebars->31->1604",
4346
- "default.handlebars->31->1612",
4354
+ "default.handlebars->31->1617",
4355
+ "default.handlebars->31->1625",
4356
"default.handlebars->31->254",
4357
"default.handlebars->31->443",
4358
"default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->p15outputselecttd->p15outputselect->1"
@@ -4366,8 +4375,8 @@
4375
"zh-chs": "代理+英特尔AMT",
4376
"zh-cht": "代理+Intel® AMT",
4377
"xloc": [
4369
- "default.handlebars->31->1606",
4370
- "default.handlebars->31->1614"
4378
+ "default.handlebars->31->1619",
4379
+ "default.handlebars->31->1627"
4380
]
4381
},
4382
{
@@ -4407,8 +4416,8 @@
4416
"zh-chs": "代理控制台",
4417
"zh-cht": "代理控制台",
4418
"xloc": [
4410
- "default-mobile.handlebars->11->497",
4411
- "default.handlebars->31->1558"
4419
+ "default-mobile.handlebars->11->514",
4420
+ "default.handlebars->31->1571"
4421
]
4422
},
4423
{
@@ -4428,7 +4437,7 @@
4437
"zh-chs": "代理错误计数器",
4438
"zh-cht": "代理錯誤計數器",
4439
"xloc": [
4431
- "default.handlebars->31->2175"
4440
+ "default.handlebars->31->2188"
4441
]
4442
},
4443
{
@@ -4531,7 +4540,7 @@
4540
"zh-chs": "代理时段",
4541
"zh-cht": "代理時段",
4542
"xloc": [
4534
- "default.handlebars->31->2191"
4543
+ "default.handlebars->31->2204"
4544
]
4545
},
4546
{
@@ -4572,7 +4581,7 @@
4581
"zh-chs": "代理类型",
4582
"zh-cht": "代理類型",
4583
"xloc": [
4575
- "default.handlebars->31->1610",
4584
+ "default.handlebars->31->1623",
4585
"default.handlebars->container->column_l->p21->3->1->meshOsChartDiv->1"
4586
]
4587
},
@@ -4593,7 +4602,7 @@
4602
"zh-chs": "代理关闭了与服务器压缩的{0}%代理会话。已发送:{1},已压缩:{2}",
4603
"zh-cht": "代理關閉了與{0}%代理到服務器壓縮的會話。已發送:{1},已壓縮:{2}",
4604
"xloc": [
4596
- "default.handlebars->31->1714"
4605
+ "default.handlebars->31->1727"
4606
]
4607
},
4608
{
@@ -4614,8 +4623,8 @@
4623
"zh-cht": "代理已連接",
4624
"xloc": [
4625
"default.handlebars->31->174",
4617
- "default.handlebars->31->673",
4618
- "default.handlebars->31->674"
4626
+ "default.handlebars->31->686",
4627
+ "default.handlebars->31->687"
4628
]
4629
},
4630
{
@@ -4655,7 +4664,7 @@
4664
"zh-chs": "代理离线",
4665
"zh-cht": "代理離線",
4666
"xloc": [
4658
- "default.handlebars->31->1083"
4667
+ "default.handlebars->31->1096"
4668
]
4669
},
4670
{
@@ -4675,7 +4684,7 @@
4684
"zh-chs": "代理在线",
4685
"zh-cht": "代理在線",
4686
"xloc": [
4678
- "default.handlebars->31->1082"
4687
+ "default.handlebars->31->1095"
4688
]
4689
},
4690
{
@@ -4696,7 +4705,7 @@
4705
"zh-cht": "代理在特權降低的遠程設備上運行。",
4706
"xloc": [
4707
"default.handlebars->31->172",
4699
- "default.handlebars->31->671"
4708
+ "default.handlebars->31->684"
4709
]
4710
},
4711
{
@@ -4716,7 +4725,7 @@
4725
"zh-chs": "代理",
4726
"zh-cht": "代理",
4727
"xloc": [
4719
- "default.handlebars->31->2207"
4728
+ "default.handlebars->31->2220"
4729
]
4730
},
4731
{
@@ -4736,7 +4745,7 @@
4745
"zh-chs": "阿尔巴尼亚文",
4746
"zh-cht": "阿爾巴尼亞文",
4747
"xloc": [
4739
- "default.handlebars->31->1123"
4748
+ "default.handlebars->31->1136"
4749
]
4750
},
4751
{
@@ -4779,7 +4788,7 @@
4788
"zh-chs": "全部可用",
4789
"zh-cht": "全部可用",
4790
"xloc": [
4782
- "default.handlebars->31->1769"
4791
+ "default.handlebars->31->1782"
4792
]
4793
},
4794
{
@@ -4816,7 +4825,7 @@
4825
"zh-chs": "所有事件",
4826
"zh-cht": "所有事件",
4827
"xloc": [
4819
- "default.handlebars->31->1767"
4828
+ "default.handlebars->31->1780"
4829
]
4830
},
4831
{
@@ -4836,9 +4845,9 @@
4845
"zh-chs": "全部聚焦",
4846
"zh-cht": "全部聚焦",
4847
"xloc": [
4839
- "default.handlebars->31->878",
4840
- "default.handlebars->31->880",
4841
- "default.handlebars->31->881"
4848
+ "default.handlebars->31->891",
4849
+ "default.handlebars->31->893",
4850
+ "default.handlebars->31->894"
4851
]
4852
},
4853
{
@@ -4858,8 +4867,8 @@
4867
"zh-chs": "允许用户管理此设备组和该组中的设备。",
4868
"zh-cht": "允許用戶管理此裝置群和該群中的裝置。",
4869
"xloc": [
4861
- "default.handlebars->31->1505",
4862
- "default.handlebars->31->1970"
4870
+ "default.handlebars->31->1518",
4871
+ "default.handlebars->31->1983"
4872
]
4873
},
4874
{
@@ -4879,7 +4888,7 @@
4888
"zh-chs": "允许用户管理此设备。",
4889
"zh-cht": "允許用戶管理此裝置。",
4890
"xloc": [
4882
- "default.handlebars->31->1506"
4891
+ "default.handlebars->31->1519"
4892
]
4893
},
4894
{
@@ -4896,8 +4905,8 @@
4905
"xloc": [
4906
"default-mobile.handlebars->11->333",
4907
"default-mobile.handlebars->11->337",
4899
- "default.handlebars->31->900",
4900
- "default.handlebars->31->904"
4908
+ "default.handlebars->31->913",
4909
+ "default.handlebars->31->917"
4910
]
4911
},
4912
{
@@ -4959,7 +4968,7 @@
4968
"zh-chs": "备用(F10 = ESC + 0)",
4969
"zh-cht": "備用(F10 = ESC + 0)",
4970
"xloc": [
4962
- "default.handlebars->31->941",
4971
+ "default.handlebars->31->954",
4972
"terminal.handlebars->3->19"
4973
]
4974
},
@@ -5001,10 +5010,10 @@
5010
"zh-chs": "一直通知",
5011
"zh-cht": "一直通知",
5012
"xloc": [
5004
- "default.handlebars->31->1417",
5005
- "default.handlebars->31->1931",
5006
- "default.handlebars->31->2018",
5007
- "default.handlebars->31->619"
5013
+ "default.handlebars->31->1430",
5014
+ "default.handlebars->31->1944",
5015
+ "default.handlebars->31->2031",
5016
+ "default.handlebars->31->632"
5017
]
5018
},
5019
{
@@ -5024,10 +5033,10 @@
5033
"zh-chs": "一直提示",
5034
"zh-cht": "一直提示",
5035
"xloc": [
5027
- "default.handlebars->31->1418",
5028
- "default.handlebars->31->1932",
5029
- "default.handlebars->31->2019",
5030
- "default.handlebars->31->620"
5036
+ "default.handlebars->31->1431",
5037
+ "default.handlebars->31->1945",
5038
+ "default.handlebars->31->2032",
5039
+ "default.handlebars->31->633"
5040
]
5041
},
5042
{
@@ -5167,7 +5176,8 @@
5176
"zh-chs": "杀毒软件",
5177
"zh-cht": "防毒軟體",
5178
"xloc": [
5170
- "default.handlebars->31->610"
5179
+ "default-mobile.handlebars->11->401",
5180
+ "default.handlebars->31->623"
5181
]
5182
},
5183
{
@@ -5288,7 +5298,7 @@
5298
"zh-chs": "阿拉伯文(阿尔及利亚)",
5299
"zh-cht": "阿拉伯文(阿爾及利亞)",
5300
"xloc": [
5291
- "default.handlebars->31->1125"
5301
+ "default.handlebars->31->1138"
5302
]
5303
},
5304
{
@@ -5308,7 +5318,7 @@
5318
"zh-chs": "阿拉伯文(巴林)",
5319
"zh-cht": "阿拉伯文(巴林)",
5320
"xloc": [
5311
- "default.handlebars->31->1126"
5321
+ "default.handlebars->31->1139"
5322
]
5323
},
5324
{
@@ -5328,7 +5338,7 @@
5338
"zh-chs": "阿拉伯文(埃及)",
5339
"zh-cht": "阿拉伯文(埃及)",
5340
"xloc": [
5331
- "default.handlebars->31->1127"
5341
+ "default.handlebars->31->1140"
5342
]
5343
},
5344
{
@@ -5348,7 +5358,7 @@
5358
"zh-chs": "阿拉伯文(伊拉克)",
5359
"zh-cht": "阿拉伯文(伊拉克)",
5360
"xloc": [
5351
- "default.handlebars->31->1128"
5361
+ "default.handlebars->31->1141"
5362
]
5363
},
5364
{
@@ -5368,7 +5378,7 @@
5378
"zh-chs": "阿拉伯文(约旦)",
5379
"zh-cht": "阿拉伯文(約旦)",
5380
"xloc": [
5371
- "default.handlebars->31->1129"
5381
+ "default.handlebars->31->1142"
5382
]
5383
},
5384
{
@@ -5388,7 +5398,7 @@
5398
"zh-chs": "阿拉伯文(科威特)",
5399
"zh-cht": "阿拉伯文(科威特)",
5400
"xloc": [
5391
- "default.handlebars->31->1130"
5401
+ "default.handlebars->31->1143"
5402
]
5403
},
5404
{
@@ -5408,7 +5418,7 @@
5418
"zh-chs": "阿拉伯文(黎巴嫩)",
5419
"zh-cht": "阿拉伯文(黎巴嫩)",
5420
"xloc": [
5411
- "default.handlebars->31->1131"
5421
+ "default.handlebars->31->1144"
5422
]
5423
},
5424
{
@@ -5428,7 +5438,7 @@
5438
"zh-chs": "阿拉伯文(利比亚)",
5439
"zh-cht": "阿拉伯文(利比亞)",
5440
"xloc": [
5431
- "default.handlebars->31->1132"
5441
+ "default.handlebars->31->1145"
5442
]
5443
},
5444
{
@@ -5448,7 +5458,7 @@
5458
"zh-chs": "阿拉伯文(摩洛哥)",
5459
"zh-cht": "阿拉伯文(摩洛哥)",
5460
"xloc": [
5451
- "default.handlebars->31->1133"
5461
+ "default.handlebars->31->1146"
5462
]
5463
},
5464
{
@@ -5468,7 +5478,7 @@
5478
"zh-chs": "阿拉伯文(阿曼)",
5479
"zh-cht": "阿拉伯文(阿曼)",
5480
"xloc": [
5471
- "default.handlebars->31->1134"
5481
+ "default.handlebars->31->1147"
5482
]
5483
},
5484
{
@@ -5488,7 +5498,7 @@
5498
"zh-chs": "阿拉伯文(卡塔尔)",
5499
"zh-cht": "阿拉伯文(卡塔爾)",
5500
"xloc": [
5491
- "default.handlebars->31->1135"
5501
+ "default.handlebars->31->1148"
5502
]
5503
},
5504
{
@@ -5508,7 +5518,7 @@
5518
"zh-chs": "阿拉伯文(沙特阿拉伯)",
5519
"zh-cht": "阿拉伯文(沙特阿拉伯)",
5520
"xloc": [
5511
- "default.handlebars->31->1136"
5521
+ "default.handlebars->31->1149"
5522
]
5523
},
5524
{
@@ -5528,7 +5538,7 @@
5538
"zh-chs": "阿拉伯文(标准)",
5539
"zh-cht": "阿拉伯文(標準)",
5540
"xloc": [
5531
- "default.handlebars->31->1124"
5541
+ "default.handlebars->31->1137"
5542
]
5543
},
5544
{
@@ -5548,7 +5558,7 @@
5558
"zh-chs": "阿拉伯文(叙利亚)",
5559
"zh-cht": "阿拉伯文(敘利亞)",
5560
"xloc": [
5551
- "default.handlebars->31->1137"
5561
+ "default.handlebars->31->1150"
5562
]
5563
},
5564
{
@@ -5568,7 +5578,7 @@
5578
"zh-chs": "阿拉伯文(突尼斯)",
5579
"zh-cht": "阿拉伯文(突尼斯)",
5580
"xloc": [
5571
- "default.handlebars->31->1138"
5581
+ "default.handlebars->31->1151"
5582
]
5583
},
5584
{
@@ -5588,7 +5598,7 @@
5598
"zh-chs": "阿拉伯文(阿联酋)",
5599
"zh-cht": "阿拉伯文(阿聯酋)",
5600
"xloc": [
5591
- "default.handlebars->31->1139"
5601
+ "default.handlebars->31->1152"
5602
]
5603
},
5604
{
@@ -5608,7 +5618,7 @@
5618
"zh-chs": "阿拉伯文(也门)",
5619
"zh-cht": "阿拉伯文(也門)",
5620
"xloc": [
5611
- "default.handlebars->31->1140"
5621
+ "default.handlebars->31->1153"
5622
]
5623
},
5624
{
@@ -5628,7 +5638,7 @@
5638
"zh-chs": "阿拉贡文",
5639
"zh-cht": "阿拉貢文",
5640
"xloc": [
5631
- "default.handlebars->31->1141"
5641
+ "default.handlebars->31->1154"
5642
]
5643
},
5644
{
@@ -5649,7 +5659,7 @@
5659
"zh-cht": "結構",
5660
"xloc": [
5661
"default-mobile.handlebars->11->384",
5652
- "default.handlebars->31->1002"
5662
+ "default.handlebars->31->1015"
5663
]
5664
},
5665
{
@@ -5689,8 +5699,8 @@
5699
"zh-chs": "你确定要删除组{0}吗?删除设备组还将删除该组中有关设备的所有信息。",
5700
"zh-cht": "你確定要刪除群{0}嗎?刪除裝置群還將刪除該群中有關裝置的所有訊息。",
5701
"xloc": [
5692
- "default-mobile.handlebars->11->466",
5693
- "default.handlebars->31->1481"
5702
+ "default-mobile.handlebars->11->483",
5703
+ "default.handlebars->31->1494"
5704
]
5705
},
5706
{
@@ -5710,7 +5720,7 @@
5720
"zh-chs": "您确定要删除节点{0}吗?",
5721
"zh-cht": "你確定要刪除節點{0}嗎?",
5722
"xloc": [
5713
- "default.handlebars->31->820"
5723
+ "default.handlebars->31->833"
5724
]
5725
},
5726
{
@@ -5730,7 +5740,7 @@
5740
"zh-chs": "您确定要卸载所选代理吗?",
5741
"zh-cht": "你確定要卸載所選代理嗎?",
5742
"xloc": [
5733
- "default.handlebars->31->809"
5743
+ "default.handlebars->31->822"
5744
]
5745
},
5746
{
@@ -5750,7 +5760,7 @@
5760
"zh-chs": "您确定要卸载所选的{0}代理吗?",
5761
"zh-cht": "你確定要卸載所選的{0}代理嗎?",
5762
"xloc": [
5753
- "default.handlebars->31->808"
5763
+ "default.handlebars->31->821"
5764
]
5765
},
5766
{
@@ -5770,7 +5780,7 @@
5780
"zh-chs": "您确定要{0}插件吗:{1}",
5781
"zh-cht": "你確定要{0}外掛嗎:{1}",
5782
"xloc": [
5773
- "default.handlebars->31->2253"
5783
+ "default.handlebars->31->2266"
5784
]
5785
},
5786
{
@@ -5790,7 +5800,7 @@
5800
"zh-chs": "亚美尼亚文",
5801
"zh-cht": "亞美尼亞文",
5802
"xloc": [
5793
- "default.handlebars->31->1142"
5803
+ "default.handlebars->31->1155"
5804
]
5805
},
5806
{
@@ -5850,7 +5860,7 @@
5860
"zh-chs": "阿萨姆文",
5861
"zh-cht": "阿薩姆文",
5862
"xloc": [
5853
- "default.handlebars->31->1143"
5863
+ "default.handlebars->31->1156"
5864
]
5865
},
5866
{
@@ -5870,7 +5880,7 @@
5880
"zh-chs": "阿斯图里亚斯文",
5881
"zh-cht": "阿斯圖里亞斯文",
5882
"xloc": [
5873
- "default.handlebars->31->1144"
5883
+ "default.handlebars->31->1157"
5884
]
5885
},
5886
{
@@ -5890,7 +5900,7 @@
5900
"zh-chs": "尝试激活英特尔(R)AMT ACM模式",
5901
"zh-cht": "嘗試激活英特爾(R)AMT ACM模式",
5902
"xloc": [
5893
- "default.handlebars->31->1683"
5903
+ "default.handlebars->31->1696"
5904
]
5905
},
5906
{
@@ -5910,7 +5920,7 @@
5920
"zh-chs": "认证软件",
5921
"zh-cht": "認證軟體",
5922
"xloc": [
5913
- "default.handlebars->31->2022"
5923
+ "default.handlebars->31->2035"
5924
]
5925
},
5926
{
@@ -5934,8 +5944,8 @@
5944
"default-mobile.handlebars->11->63",
5945
"default-mobile.handlebars->11->82",
5946
"default-mobile.handlebars->11->84",
5937
- "default.handlebars->31->1108",
5938
- "default.handlebars->31->1110",
5947
+ "default.handlebars->31->1121",
5948
+ "default.handlebars->31->1123",
5949
"default.handlebars->31->136",
5950
"default.handlebars->31->141"
5951
]
@@ -6017,7 +6027,7 @@
6027
"zh-chs": "自动删除",
6028
"zh-cht": "自動刪除",
6029
"xloc": [
6020
- "default.handlebars->31->1404"
6030
+ "default.handlebars->31->1417"
6031
]
6032
},
6033
{
@@ -6061,7 +6071,7 @@
6071
"zh-chs": "自动下载代理程序核心转储文件:“{0}”",
6072
"zh-cht": "自動下載代理程序核心轉儲文件:“{0}”",
6073
"xloc": [
6064
- "default.handlebars->31->1764"
6074
+ "default.handlebars->31->1777"
6075
]
6076
},
6077
{
@@ -6101,7 +6111,7 @@
6111
"zh-chs": "可用內存",
6112
"zh-cht": "可用內存",
6113
"xloc": [
6104
- "default.handlebars->31->2200"
6114
+ "default.handlebars->31->2213"
6115
]
6116
},
6117
{
@@ -6121,7 +6131,18 @@
6131
"zh-chs": "阿塞拜疆文",
6132
"zh-cht": "阿塞拜疆文",
6133
"xloc": [
6124
- "default.handlebars->31->1145"
6134
+ "default.handlebars->31->1158"
6135
+ ]
6136
+ },
6137
+ {
6138
+ "en": "BAD",
6139
+ "xloc": [
6140
+ "default-mobile.handlebars->11->388",
6141
+ "default-mobile.handlebars->11->392",
6142
+ "default-mobile.handlebars->11->396",
6143
+ "default.handlebars->31->610",
6144
+ "default.handlebars->31->614",
6145
+ "default.handlebars->31->618"
6146
]
6147
},
6148
{
@@ -6141,8 +6162,8 @@
6162
"zh-chs": "的BIOS",
6163
"zh-cht": "的BIOS",
6164
"xloc": [
6144
- "default-mobile.handlebars->11->432",
6145
- "default.handlebars->31->1060"
6165
+ "default-mobile.handlebars->11->449",
6166
+ "default.handlebars->31->1073"
6167
]
6168
},
6169
{
@@ -6226,7 +6247,7 @@
6247
"nl": "BackSpace",
6248
"xloc": [
6249
"default-mobile.handlebars->11->317",
6229
- "default.handlebars->31->884"
6250
+ "default.handlebars->31->897"
6251
]
6252
},
6253
{
@@ -6266,8 +6287,8 @@
6287
"zh-chs": "背景与互动",
6288
"zh-cht": "背景與互動",
6289
"xloc": [
6269
- "default.handlebars->31->1587",
6270
- "default.handlebars->31->1594",
6290
+ "default.handlebars->31->1600",
6291
+ "default.handlebars->31->1607",
6292
"default.handlebars->31->353",
6293
"default.handlebars->31->367"
6294
]
@@ -6289,8 +6310,8 @@
6310
"zh-chs": "仅背景",
6311
"zh-cht": "僅背景",
6312
"xloc": [
6292
- "default.handlebars->31->1588",
6293
- "default.handlebars->31->1595",
6313
+ "default.handlebars->31->1601",
6314
+ "default.handlebars->31->1608",
6315
"default.handlebars->31->354",
6316
"default.handlebars->31->368",
6317
"default.handlebars->31->383"
@@ -6334,7 +6355,7 @@
6355
"zh-chs": "备用码",
6356
"zh-cht": "備用碼",
6357
"xloc": [
6337
- "default.handlebars->31->2024"
6358
+ "default.handlebars->31->2037"
6359
]
6360
},
6361
{
@@ -6354,7 +6375,7 @@
6375
"zh-chs": "错误的签名",
6376
"zh-cht": "錯誤的簽名",
6377
"xloc": [
6357
- "default.handlebars->31->2182"
6378
+ "default.handlebars->31->2195"
6379
]
6380
},
6381
{
@@ -6374,7 +6395,7 @@
6395
"zh-chs": "错误的网络证书",
6396
"zh-cht": "錯誤的網絡憑證",
6397
"xloc": [
6377
- "default.handlebars->31->2181"
6398
+ "default.handlebars->31->2194"
6399
]
6400
},
6401
{
@@ -6394,7 +6415,7 @@
6415
"zh-chs": "巴斯克",
6416
"zh-cht": "巴斯克",
6417
"xloc": [
6397
- "default.handlebars->31->1146"
6418
+ "default.handlebars->31->1159"
6419
]
6420
},
6421
{
@@ -6454,7 +6475,7 @@
6475
"zh-chs": "将{0}个文件批量上传到文件夹{1}",
6476
"zh-cht": "將{0}個文件批量上傳到文件夾{1}",
6477
"xloc": [
6457
- "default.handlebars->31->1763"
6478
+ "default.handlebars->31->1776"
6479
]
6480
},
6481
{
@@ -6474,7 +6495,7 @@
6495
"zh-chs": "白俄罗斯文",
6496
"zh-cht": "白俄羅斯文",
6497
"xloc": [
6477
- "default.handlebars->31->1148"
6498
+ "default.handlebars->31->1161"
6499
]
6500
},
6501
{
@@ -6494,7 +6515,7 @@
6515
"zh-chs": "孟加拉",
6516
"zh-cht": "孟加拉",
6517
"xloc": [
6497
- "default.handlebars->31->1149"
6518
+ "default.handlebars->31->1162"
6519
]
6520
},
6521
{
@@ -6524,8 +6545,8 @@
6545
"en": "Bootloader",
6546
"nl": "Bootloader",
6547
"xloc": [
6527
- "default-mobile.handlebars->11->396",
6528
- "default.handlebars->31->1014"
6548
+ "default-mobile.handlebars->11->413",
6549
+ "default.handlebars->31->1027"
6550
]
6551
},
6552
{
@@ -6545,7 +6566,7 @@
6566
"zh-chs": "波斯尼亚文",
6567
"zh-cht": "波斯尼亞文",
6568
"xloc": [
6548
- "default.handlebars->31->1150"
6569
+ "default.handlebars->31->1163"
6570
]
6571
},
6572
{
@@ -6565,7 +6586,7 @@
6586
"zh-chs": "布列塔尼",
6587
"zh-cht": "布列塔尼",
6588
"xloc": [
6568
- "default.handlebars->31->1151"
6589
+ "default.handlebars->31->1164"
6590
]
6591
},
6592
{
@@ -6585,7 +6606,7 @@
6606
"zh-chs": "广播",
6607
"zh-cht": "廣播",
6608
"xloc": [
6588
- "default.handlebars->31->1938",
6609
+ "default.handlebars->31->1951",
6610
"default.handlebars->container->column_l->p4->3->1->0->3->1"
6611
]
6612
},
@@ -6606,7 +6627,7 @@
6627
"zh-chs": "广播消息",
6628
"zh-cht": "廣播消息",
6629
"xloc": [
6609
- "default.handlebars->31->1859"
6630
+ "default.handlebars->31->1872"
6631
]
6632
},
6633
{
@@ -6626,7 +6647,7 @@
6647
"zh-chs": "向所有连接的用户广播消息。",
6648
"zh-cht": "向所有連接的用戶廣播消息。",
6649
"xloc": [
6629
- "default.handlebars->31->1854"
6650
+ "default.handlebars->31->1867"
6651
]
6652
},
6653
{
@@ -6646,7 +6667,7 @@
6667
"zh-chs": "保加利亚文",
6668
"zh-cht": "保加利亞文",
6669
"xloc": [
6649
- "default.handlebars->31->1147"
6670
+ "default.handlebars->31->1160"
6671
]
6672
},
6673
{
@@ -6666,7 +6687,7 @@
6687
"zh-chs": "缅甸文",
6688
"zh-cht": "緬甸文",
6689
"xloc": [
6669
- "default.handlebars->31->1152"
6690
+ "default.handlebars->31->1165"
6691
]
6692
},
6693
{
@@ -6707,7 +6728,7 @@
6728
"zh-chs": "CCM模式",
6729
"zh-cht": "CCM模式",
6730
"xloc": [
6710
- "default.handlebars->31->1464"
6731
+ "default.handlebars->31->1477"
6732
]
6733
},
6734
{
@@ -6749,7 +6770,7 @@
6770
"zh-chs": "CIRA服务器",
6771
"zh-cht": "CIRA伺服器",
6772
"xloc": [
6752
- "default.handlebars->31->2239"
6773
+ "default.handlebars->31->2252"
6774
]
6775
},
6776
{
@@ -6769,7 +6790,7 @@
6790
"zh-chs": "CIRA服务器命令",
6791
"zh-cht": "CIRA伺服器指令",
6792
"xloc": [
6772
- "default.handlebars->31->2240"
6793
+ "default.handlebars->31->2253"
6794
]
6795
},
6796
{
@@ -6789,7 +6810,7 @@
6810
"zh-chs": "CIRA设置",
6811
"zh-cht": "CIRA設置",
6812
"xloc": [
6792
- "default.handlebars->31->1472"
6813
+ "default.handlebars->31->1485"
6814
]
6815
},
6816
{
@@ -6809,8 +6830,8 @@
6830
"zh-chs": "CPU",
6831
"zh-cht": "CPU",
6832
"xloc": [
6812
- "default-mobile.handlebars->11->438",
6813
- "default.handlebars->31->1066"
6833
+ "default-mobile.handlebars->11->455",
6834
+ "default.handlebars->31->1079"
6835
]
6836
},
6837
{
@@ -6830,7 +6851,7 @@
6851
"zh-chs": "CPU负载",
6852
"zh-cht": "CPU負載",
6853
"xloc": [
6833
- "default.handlebars->31->2196"
6854
+ "default.handlebars->31->2209"
6855
]
6856
},
6857
{
@@ -6850,7 +6871,7 @@
6871
"zh-chs": "最近15分钟的CPU负载",
6872
"zh-cht": "最近15分鐘的CPU負載",
6873
"xloc": [
6853
- "default.handlebars->31->2199"
6874
+ "default.handlebars->31->2212"
6875
]
6876
},
6877
{
@@ -6870,7 +6891,7 @@
6891
"zh-chs": "最近5分钟的CPU负载",
6892
"zh-cht": "最近5分鐘的CPU負載",
6893
"xloc": [
6873
- "default.handlebars->31->2198"
6894
+ "default.handlebars->31->2211"
6895
]
6896
},
6897
{
@@ -6890,7 +6911,7 @@
6911
"zh-chs": "最近一分钟的CPU负载",
6912
"zh-cht": "最近一分鐘的CPU負載",
6913
"xloc": [
6893
- "default.handlebars->31->2197"
6914
+ "default.handlebars->31->2210"
6915
]
6916
},
6917
{
@@ -6910,8 +6931,8 @@
6931
"zh-chs": "CR+LF",
6932
"zh-cht": "CR+LF",
6933
"xloc": [
6913
- "default.handlebars->31->934",
6914
- "default.handlebars->31->943",
6934
+ "default.handlebars->31->947",
6935
+ "default.handlebars->31->956",
6936
"default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
6937
"terminal.handlebars->3->21",
6938
"terminal.handlebars->3->7",
@@ -6935,7 +6956,7 @@
6956
"zh-chs": "CSV",
6957
"zh-cht": "CSV",
6958
"xloc": [
6938
- "default.handlebars->31->1777"
6959
+ "default.handlebars->31->1790"
6960
]
6961
},
6962
{
@@ -6955,8 +6976,8 @@
6976
"zh-chs": "CSV格式",
6977
"zh-cht": "CSV格式",
6978
"xloc": [
6958
- "default.handlebars->31->1781",
6959
- "default.handlebars->31->1846",
6979
+ "default.handlebars->31->1794",
6980
+ "default.handlebars->31->1859",
6981
"default.handlebars->31->502"
6982
]
6983
},
@@ -6994,7 +7015,7 @@
7015
"zh-chs": "呼叫错误",
7016
"zh-cht": "呼叫錯誤",
7017
"xloc": [
6997
- "default.handlebars->31->2254"
7018
+ "default.handlebars->31->2267"
7019
]
7020
},
7021
{
@@ -7017,7 +7038,7 @@
7038
"agent-translations.json",
7039
"default-mobile.handlebars->11->93",
7040
"default-mobile.handlebars->dialog->idx_dlgButtonBar",
7020
- "default.handlebars->31->1382",
7041
+ "default.handlebars->31->1395",
7042
"default.handlebars->container->dialog->idx_dlgButtonBar",
7043
"desktop.handlebars->p11->dialog->idx_dlgButtonBar",
7044
"login-mobile.handlebars->dialog->idx_dlgButtonBar",
@@ -7045,12 +7066,12 @@
7066
"zh-chs": "容量",
7067
"zh-cht": "容量",
7068
"xloc": [
7048
- "default-mobile.handlebars->11->443",
7049
- "default-mobile.handlebars->11->448",
7050
- "default-mobile.handlebars->11->450",
7051
- "default.handlebars->31->1071",
7052
- "default.handlebars->31->1076",
7053
- "default.handlebars->31->1078"
7069
+ "default-mobile.handlebars->11->460",
7070
+ "default-mobile.handlebars->11->465",
7071
+ "default-mobile.handlebars->11->467",
7072
+ "default.handlebars->31->1084",
7073
+ "default.handlebars->31->1089",
7074
+ "default.handlebars->31->1091"
7075
]
7076
},
7077
{
@@ -7070,8 +7091,8 @@
7091
"zh-chs": "容量/速度",
7092
"zh-cht": "容量/速度",
7093
"xloc": [
7073
- "default-mobile.handlebars->11->441",
7074
- "default.handlebars->31->1069"
7094
+ "default-mobile.handlebars->11->458",
7095
+ "default.handlebars->31->1082"
7096
]
7097
},
7098
{
@@ -7091,7 +7112,7 @@
7112
"zh-chs": "加泰罗尼亚文",
7113
"zh-cht": "加泰羅尼亞文",
7114
"xloc": [
7094
- "default.handlebars->31->1153"
7115
+ "default.handlebars->31->1166"
7116
]
7117
},
7118
{
@@ -7131,7 +7152,7 @@
7152
"zh-chs": "查莫罗",
7153
"zh-cht": "查莫羅",
7154
"xloc": [
7134
- "default.handlebars->31->1154"
7155
+ "default.handlebars->31->1167"
7156
]
7157
},
7158
{
@@ -7173,7 +7194,7 @@
7194
"zh-chs": "更改{0}的电邮",
7195
"zh-cht": "更改{0}的電郵",
7196
"xloc": [
7176
- "default.handlebars->31->2054"
7197
+ "default.handlebars->31->2067"
7198
]
7199
},
7200
{
@@ -7193,9 +7214,9 @@
7214
"zh-chs": "更改组",
7215
"zh-cht": "更改群",
7216
"xloc": [
7196
- "default.handlebars->31->648",
7197
- "default.handlebars->31->817",
7198
- "default.handlebars->31->818"
7217
+ "default.handlebars->31->661",
7218
+ "default.handlebars->31->830",
7219
+ "default.handlebars->31->831"
7220
]
7221
},
7222
{
@@ -7216,8 +7237,8 @@
7237
"zh-cht": "更改密碼",
7238
"xloc": [
7239
"default-mobile.handlebars->11->101",
7219
- "default.handlebars->31->1349",
7220
- "default.handlebars->31->2041"
7240
+ "default.handlebars->31->1362",
7241
+ "default.handlebars->31->2054"
7242
]
7243
},
7244
{
@@ -7237,7 +7258,7 @@
7258
"zh-chs": "更改{0}的密码",
7259
"zh-cht": "更改{0}的密碼",
7260
"xloc": [
7240
- "default.handlebars->31->2061"
7261
+ "default.handlebars->31->2074"
7262
]
7263
},
7264
{
@@ -7257,7 +7278,7 @@
7278
"zh-chs": "更改{0}的真实名称",
7279
"zh-cht": "更改{0}的真實名稱",
7280
"xloc": [
7260
- "default.handlebars->31->2049"
7281
+ "default.handlebars->31->2062"
7282
]
7283
},
7284
{
@@ -7339,7 +7360,7 @@
7360
"zh-chs": "更改该用户的密码",
7361
"zh-cht": "更改該用戶的密碼",
7362
"xloc": [
7342
- "default.handlebars->31->2040"
7363
+ "default.handlebars->31->2053"
7364
]
7365
},
7366
{
@@ -7379,7 +7400,7 @@
7400
"zh-chs": "在此处更改您的帐户电邮地址。",
7401
"zh-cht": "在此處更改你的帳戶電郵地址。",
7402
"xloc": [
7382
- "default.handlebars->31->1336"
7403
+ "default.handlebars->31->1349"
7404
]
7405
},
7406
{
@@ -7399,7 +7420,7 @@
7420
"zh-chs": "在下面的框中两次输入旧密码和新密码,以更改帐户密码。",
7421
"zh-cht": "在下面的框中兩次輸入舊密碼和新密碼,以更改帳戶密碼。",
7422
"xloc": [
7402
- "default.handlebars->31->1342"
7423
+ "default.handlebars->31->1355"
7424
]
7425
},
7426
{
@@ -7419,7 +7440,7 @@
7440
"zh-chs": "更改帐户凭据",
7441
"zh-cht": "帳戶憑證已更改",
7442
"xloc": [
7422
- "default.handlebars->31->1735"
7443
+ "default.handlebars->31->1748"
7444
]
7445
},
7446
{
@@ -7439,7 +7460,7 @@
7460
"zh-chs": "{1}组中的设备{0}已更改:{2}",
7461
"zh-cht": "{1}組中的設備{0}已更改:{2}",
7462
"xloc": [
7442
- "default.handlebars->31->1719"
7463
+ "default.handlebars->31->1732"
7464
]
7465
},
7466
{
@@ -7459,7 +7480,7 @@
7480
"zh-chs": "语言从{1}更改为{2}",
7481
"zh-cht": "語言從{1}更改為{2}",
7482
"xloc": [
7462
- "default.handlebars->31->1663"
7483
+ "default.handlebars->31->1676"
7484
]
7485
},
7486
{
@@ -7479,8 +7500,8 @@
7500
"zh-chs": "已更改{0}的用户设备权限",
7501
"zh-cht": "已更改{0}的用戶設備權限",
7502
"xloc": [
7482
- "default.handlebars->31->1721",
7483
- "default.handlebars->31->1742"
7503
+ "default.handlebars->31->1734",
7504
+ "default.handlebars->31->1755"
7505
]
7506
},
7507
{
@@ -7500,7 +7521,7 @@
7521
"zh-chs": "更改语言将需要刷新页面。",
7522
"zh-cht": "更改語言將需要刷新頁面。",
7523
"xloc": [
7503
- "default.handlebars->31->1321"
7524
+ "default.handlebars->31->1334"
7525
]
7526
},
7527
{
@@ -7520,11 +7541,11 @@
7541
"zh-chs": "聊天",
7542
"zh-cht": "聊天",
7543
"xloc": [
7523
- "default.handlebars->31->1798",
7524
- "default.handlebars->31->2036",
7525
- "default.handlebars->31->2037",
7526
- "default.handlebars->31->713",
7527
- "default.handlebars->31->734"
7544
+ "default.handlebars->31->1811",
7545
+ "default.handlebars->31->2049",
7546
+ "default.handlebars->31->2050",
7547
+ "default.handlebars->31->726",
7548
+ "default.handlebars->31->747"
7549
]
7550
},
7551
{
@@ -7544,10 +7565,10 @@
7565
"zh-chs": "聊天并通知",
7566
"zh-cht": "聊天並通知",
7567
"xloc": [
7547
- "default-mobile.handlebars->11->487",
7548
- "default-mobile.handlebars->11->507",
7549
- "default.handlebars->31->1533",
7550
- "default.handlebars->31->1569"
7568
+ "default-mobile.handlebars->11->504",
7569
+ "default-mobile.handlebars->11->524",
7570
+ "default.handlebars->31->1546",
7571
+ "default.handlebars->31->1582"
7572
]
7573
},
7574
{
@@ -7555,8 +7576,8 @@
7576
"nl": "Chatverzoek, klik hier om te accepteren.",
7577
"fr": "Demande de chat, cliquez ici pour accepter.",
7578
"xloc": [
7558
- "default-mobile.handlebars->11->539",
7559
- "default.handlebars->31->2151"
7579
+ "default-mobile.handlebars->11->556",
7580
+ "default.handlebars->31->2164"
7581
]
7582
},
7583
{
@@ -7596,7 +7617,7 @@
7617
"zh-chs": "车臣",
7618
"zh-cht": "車臣",
7619
"xloc": [
7599
- "default.handlebars->31->1155"
7620
+ "default.handlebars->31->1168"
7621
]
7622
},
7623
{
@@ -7696,8 +7717,8 @@
7717
"zh-chs": "检查...",
7718
"zh-cht": "檢查...",
7719
"xloc": [
7699
- "default.handlebars->31->1121",
7700
- "default.handlebars->31->2248"
7720
+ "default.handlebars->31->1134",
7721
+ "default.handlebars->31->2261"
7722
]
7723
},
7724
{
@@ -7717,7 +7738,7 @@
7738
"zh-chs": "中文",
7739
"zh-cht": "中文",
7740
"xloc": [
7720
- "default.handlebars->31->1156"
7741
+ "default.handlebars->31->1169"
7742
]
7743
},
7744
{
@@ -7737,7 +7758,7 @@
7758
"zh-chs": "中文(香港)",
7759
"zh-cht": "中文(香港)",
7760
"xloc": [
7740
- "default.handlebars->31->1157"
7761
+ "default.handlebars->31->1170"
7762
]
7763
},
7764
{
@@ -7757,7 +7778,7 @@
7778
"zh-chs": "中文(中国)",
7779
"zh-cht": "中文(中國)",
7780
"xloc": [
7760
- "default.handlebars->31->1158"
7781
+ "default.handlebars->31->1171"
7782
]
7783
},
7784
{
@@ -7777,7 +7798,7 @@
7798
"zh-chs": "简体中文",
7799
"zh-cht": "簡體中文",
7800
"xloc": [
7780
- "default.handlebars->31->1318"
7801
+ "default.handlebars->31->1331"
7802
]
7803
},
7804
{
@@ -7797,7 +7818,7 @@
7818
"zh-chs": "中文(新加坡)",
7819
"zh-cht": "中文(新加坡)",
7820
"xloc": [
7800
- "default.handlebars->31->1159"
7821
+ "default.handlebars->31->1172"
7822
]
7823
},
7824
{
@@ -7817,7 +7838,7 @@
7838
"zh-chs": "中文(台湾)",
7839
"zh-cht": "中文(台灣)",
7840
"xloc": [
7820
- "default.handlebars->31->1160"
7841
+ "default.handlebars->31->1173"
7842
]
7843
},
7844
{
@@ -7837,7 +7858,7 @@
7858
"zh-chs": "繁体中文",
7859
"zh-cht": "繁體中文",
7860
"xloc": [
7840
- "default.handlebars->31->1319"
7861
+ "default.handlebars->31->1332"
7862
]
7863
},
7864
{
@@ -7878,7 +7899,7 @@
7899
"zh-chs": "楚瓦什",
7900
"zh-cht": "楚瓦什",
7901
"xloc": [
7881
- "default.handlebars->31->1161"
7902
+ "default.handlebars->31->1174"
7903
]
7904
},
7905
{
@@ -7921,11 +7942,11 @@
7942
"default-mobile.handlebars->11->372",
7943
"default-mobile.handlebars->11->374",
7944
"default-mobile.handlebars->11->70",
7924
- "default.handlebars->31->1657",
7925
- "default.handlebars->31->979",
7926
- "default.handlebars->31->981",
7927
- "default.handlebars->31->983",
7928
- "default.handlebars->31->985",
7945
+ "default.handlebars->31->1670",
7946
+ "default.handlebars->31->992",
7947
+ "default.handlebars->31->994",
7948
+ "default.handlebars->31->996",
7949
+ "default.handlebars->31->998",
7950
"default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->7",
7951
"default.handlebars->container->column_l->p41->3->1",
7952
"messenger.handlebars->xbottom->1->1->0->5"
@@ -7968,8 +7989,8 @@
7989
"zh-chs": "全部清除",
7990
"zh-cht": "全部清除",
7991
"xloc": [
7971
- "default-mobile.handlebars->11->522",
7972
- "default.handlebars->31->2134"
7992
+ "default-mobile.handlebars->11->539",
7993
+ "default.handlebars->31->2147"
7994
]
7995
},
7996
{
@@ -8010,7 +8031,7 @@
8031
"zh-chs": "清除核心",
8032
"zh-cht": "清除核心",
8033
"xloc": [
8013
- "default.handlebars->31->1092"
8034
+ "default.handlebars->31->1105"
8035
]
8036
},
8037
{
@@ -8050,8 +8071,8 @@
8071
"zh-chs": "清除此通知",
8072
"zh-cht": "清除此通知",
8073
"xloc": [
8053
- "default-mobile.handlebars->11->521",
8054
- "default.handlebars->31->2133"
8074
+ "default-mobile.handlebars->11->538",
8075
+ "default.handlebars->31->2146"
8076
]
8077
},
8078
{
@@ -8111,8 +8132,8 @@
8132
"zh-chs": "单击此处编辑设备组名称",
8133
"zh-cht": "單擊此處編輯裝置群名稱",
8134
"xloc": [
8114
- "default.handlebars->31->1393",
8115
- "default.handlebars->31->1608"
8135
+ "default.handlebars->31->1406",
8136
+ "default.handlebars->31->1621"
8137
]
8138
},
8139
{
@@ -8152,7 +8173,7 @@
8173
"zh-chs": "单击此处编辑用户组名称",
8174
"zh-cht": "單擊此處編輯用戶群名稱",
8175
"xloc": [
8155
- "default.handlebars->31->1915"
8176
+ "default.handlebars->31->1928"
8177
]
8178
},
8179
{
@@ -8223,7 +8244,7 @@
8244
"zh-cht": "單擊確定將驗證電郵發送到:",
8245
"xloc": [
8246
"default-mobile.handlebars->11->86",
8226
- "default.handlebars->31->1333"
8247
+ "default.handlebars->31->1346"
8248
]
8249
},
8250
{
@@ -8284,8 +8305,8 @@
8305
"zh-chs": "客户端控制模式(CCM)",
8306
"zh-cht": "客戶端控制模式(CCM)",
8307
"xloc": [
8287
- "default-mobile.handlebars->11->419",
8288
- "default.handlebars->31->1047"
8308
+ "default-mobile.handlebars->11->436",
8309
+ "default.handlebars->31->1060"
8310
]
8311
},
8312
{
@@ -8305,7 +8326,7 @@
8326
"zh-chs": "客户编号",
8327
"zh-cht": "客戶編號",
8328
"xloc": [
8308
- "default.handlebars->31->1375"
8329
+ "default.handlebars->31->1388"
8330
]
8331
},
8332
{
@@ -8325,7 +8346,7 @@
8346
"zh-chs": "客户端启动的远程访问",
8347
"zh-cht": "客戶端啟動的遠程訪問",
8348
"xloc": [
8328
- "default.handlebars->31->1471"
8349
+ "default.handlebars->31->1484"
8350
]
8351
},
8352
{
@@ -8345,7 +8366,7 @@
8366
"zh-chs": "客户机密",
8367
"zh-cht": "客戶機密",
8368
"xloc": [
8348
- "default.handlebars->31->1376"
8369
+ "default.handlebars->31->1389"
8370
]
8371
},
8372
{
@@ -8389,8 +8410,8 @@
8410
"default-mobile.handlebars->11->68",
8411
"default.handlebars->31->148",
8412
"default.handlebars->31->156",
8392
- "default.handlebars->31->925",
8393
- "default.handlebars->31->956"
8413
+ "default.handlebars->31->938",
8414
+ "default.handlebars->31->969"
8415
]
8416
},
8417
{
@@ -8410,7 +8431,7 @@
8431
"zh-chs": "封闭式桌面多路复用会话,{0}秒",
8432
"zh-cht": "封閉式桌面多路復用會話,{0}秒",
8433
"xloc": [
8413
- "default.handlebars->31->1668"
8434
+ "default.handlebars->31->1681"
8435
]
8436
},
8437
{
@@ -8532,10 +8553,10 @@
8553
"zh-chs": "指令",
8554
"zh-cht": "指令",
8555
"xloc": [
8535
- "default-mobile.handlebars->11->509",
8536
- "default.handlebars->31->1571",
8537
- "default.handlebars->31->715",
8538
- "default.handlebars->31->736"
8556
+ "default-mobile.handlebars->11->526",
8557
+ "default.handlebars->31->1584",
8558
+ "default.handlebars->31->728",
8559
+ "default.handlebars->31->749"
8560
]
8561
},
8562
{
@@ -8555,8 +8576,8 @@
8576
"zh-chs": "通用设备组",
8577
"zh-cht": "通用裝置群",
8578
"xloc": [
8558
- "default.handlebars->31->1946",
8559
- "default.handlebars->31->2066"
8579
+ "default.handlebars->31->1959",
8580
+ "default.handlebars->31->2079"
8581
]
8582
},
8583
{
@@ -8576,8 +8597,8 @@
8597
"zh-chs": "通用设备",
8598
"zh-cht": "通用裝置",
8599
"xloc": [
8579
- "default.handlebars->31->1952",
8580
- "default.handlebars->31->2078"
8600
+ "default.handlebars->31->1965",
8601
+ "default.handlebars->31->2091"
8602
]
8603
},
8604
{
@@ -8597,7 +8618,7 @@
8618
"zh-chs": "压缩档案...",
8619
"zh-cht": "壓縮檔案...",
8620
"xloc": [
8600
- "default.handlebars->31->951"
8621
+ "default.handlebars->31->964"
8622
]
8623
},
8624
{
@@ -8618,15 +8639,15 @@
8639
"zh-cht": "確認",
8640
"xloc": [
8641
"default-mobile.handlebars->11->301",
8621
- "default-mobile.handlebars->11->467",
8622
- "default.handlebars->31->1482",
8623
- "default.handlebars->31->1826",
8624
- "default.handlebars->31->1905",
8625
- "default.handlebars->31->1966",
8626
- "default.handlebars->31->2064",
8642
+ "default-mobile.handlebars->11->484",
8643
+ "default.handlebars->31->1495",
8644
+ "default.handlebars->31->1839",
8645
+ "default.handlebars->31->1918",
8646
+ "default.handlebars->31->1979",
8647
+ "default.handlebars->31->2077",
8648
"default.handlebars->31->472",
8628
- "default.handlebars->31->812",
8629
- "default.handlebars->31->821"
8649
+ "default.handlebars->31->825",
8650
+ "default.handlebars->31->834"
8651
]
8652
},
8653
{
@@ -8647,7 +8668,7 @@
8668
"zh-cht": "確認將1個副本複製到此位置?",
8669
"xloc": [
8670
"default-mobile.handlebars->11->363",
8650
- "default.handlebars->31->974"
8671
+ "default.handlebars->31->987"
8672
]
8673
},
8674
{
@@ -8667,7 +8688,7 @@
8688
"zh-chs": "确认{0}个条目的复制到此位置?",
8689
"zh-cht": "確認{0}個條目的複製到此位置?",
8690
"xloc": [
8670
- "default.handlebars->31->973"
8691
+ "default.handlebars->31->986"
8692
]
8693
},
8694
{
@@ -8707,7 +8728,7 @@
8728
"zh-chs": "确认删除选定的帐户?",
8729
"zh-cht": "確認刪除所選帳戶?",
8730
"xloc": [
8710
- "default.handlebars->31->1825"
8731
+ "default.handlebars->31->1838"
8732
]
8733
},
8734
{
@@ -8747,7 +8768,7 @@
8768
"zh-chs": "确认删除选定的用户组?",
8769
"zh-cht": "確認刪除所選用戶群?",
8770
"xloc": [
8750
- "default.handlebars->31->1904"
8771
+ "default.handlebars->31->1917"
8772
]
8773
},
8774
{
@@ -8767,7 +8788,7 @@
8788
"zh-chs": "确认删除用户{0}?",
8789
"zh-cht": "確認刪除用戶{0}?",
8790
"xloc": [
8770
- "default.handlebars->31->2063"
8791
+ "default.handlebars->31->2076"
8792
]
8793
},
8794
{
@@ -8787,7 +8808,7 @@
8808
"zh-chs": "确认删除用户“ {0} ”的成员身份?",
8809
"zh-cht": "確認刪除用戶“ {0} ”的成員身份?",
8810
"xloc": [
8790
- "default.handlebars->31->1969"
8811
+ "default.handlebars->31->1982"
8812
]
8813
},
8814
{
@@ -8807,7 +8828,7 @@
8828
"zh-chs": "确认删除用户组“ {0} ”的成员身份?",
8829
"zh-cht": "確認刪除用戶群“ {0} ”的成員身份?",
8830
"xloc": [
8810
- "default.handlebars->31->2095"
8831
+ "default.handlebars->31->2108"
8832
]
8833
},
8834
{
@@ -8828,7 +8849,7 @@
8849
"zh-cht": "確認將1個條目移動到此位置?",
8850
"xloc": [
8851
"default-mobile.handlebars->11->365",
8831
- "default.handlebars->31->976"
8852
+ "default.handlebars->31->989"
8853
]
8854
},
8855
{
@@ -8848,7 +8869,7 @@
8869
"zh-chs": "确认将{0}个条目移到此位置?",
8870
"zh-cht": "確認將{0}個條目移到該位置?",
8871
"xloc": [
8851
- "default.handlebars->31->975"
8872
+ "default.handlebars->31->988"
8873
]
8874
},
8875
{
@@ -8888,7 +8909,7 @@
8909
"zh-chs": "确认覆盖?",
8910
"zh-cht": "確認覆蓋?",
8911
"xloc": [
8891
- "default.handlebars->31->1651"
8912
+ "default.handlebars->31->1664"
8913
]
8914
},
8915
{
@@ -8908,8 +8929,8 @@
8929
"zh-chs": "确认删除设备“ {0} ”的访问权限?",
8930
"zh-cht": "確認刪除裝置“ {0} ”的訪問權限?",
8931
"xloc": [
8911
- "default.handlebars->31->1959",
8912
- "default.handlebars->31->2086"
8932
+ "default.handlebars->31->1972",
8933
+ "default.handlebars->31->2099"
8934
]
8935
},
8936
{
@@ -8929,8 +8950,8 @@
8950
"zh-chs": "确认删除设备组“ {0} ”的访问权限?",
8951
"zh-cht": "確認刪除裝置群“ {0} ”的訪問權限?",
8952
"xloc": [
8932
- "default.handlebars->31->1961",
8933
- "default.handlebars->31->2099"
8953
+ "default.handlebars->31->1974",
8954
+ "default.handlebars->31->2112"
8955
]
8956
},
8957
{
@@ -8950,7 +8971,7 @@
8971
"zh-chs": "确认删除用户“ {0} ”的访问权限?",
8972
"zh-cht": "確認刪除用戶“ {0} ”的訪問權限?",
8973
"xloc": [
8953
- "default.handlebars->31->2088"
8974
+ "default.handlebars->31->2101"
8975
]
8976
},
8977
{
@@ -8970,7 +8991,7 @@
8991
"zh-chs": "确认删除用户组“ {0} ”的访问权限?",
8992
"zh-cht": "確認刪除用戶群“ {0} ”的訪問權限?",
8993
"xloc": [
8973
- "default.handlebars->31->2091"
8994
+ "default.handlebars->31->2104"
8995
]
8996
},
8997
{
@@ -8990,8 +9011,8 @@
9011
"zh-chs": "确认删除访问权限?",
9012
"zh-cht": "確認刪除訪問權限?",
9013
"xloc": [
8993
- "default.handlebars->31->2089",
8994
- "default.handlebars->31->2092"
9014
+ "default.handlebars->31->2102",
9015
+ "default.handlebars->31->2105"
9016
]
9017
},
9018
{
@@ -9012,7 +9033,7 @@
9033
"zh-cht": "確認刪除身份驗證軟體兩步登入?",
9034
"xloc": [
9035
"default-mobile.handlebars->11->85",
9015
- "default.handlebars->31->1111"
9036
+ "default.handlebars->31->1124"
9037
]
9038
},
9039
{
@@ -9049,7 +9070,7 @@
9070
"zh-chs": "确认删除设备共享“{0}”?",
9071
"zh-cht": "確認刪除設備共享“{0}”?",
9072
"xloc": [
9052
- "default.handlebars->31->2084"
9073
+ "default.handlebars->31->2097"
9074
]
9075
},
9076
{
@@ -9103,7 +9124,7 @@
9124
"zh-chs": "确认删除用户“ {0} ”的权限?",
9125
"zh-cht": "確認刪除用戶“ {0} ”的權限?",
9126
"xloc": [
9106
- "default.handlebars->31->1580"
9127
+ "default.handlebars->31->1593"
9128
]
9129
},
9130
{
@@ -9123,7 +9144,7 @@
9144
"zh-chs": "确认删除用户组“ {0} ”的权限?",
9145
"zh-cht": "確認刪除用戶群“ {0} ”的權限?",
9146
"xloc": [
9126
- "default.handlebars->31->1582"
9147
+ "default.handlebars->31->1595"
9148
]
9149
},
9150
{
@@ -9160,7 +9181,7 @@
9181
"zh-chs": "确认删除用户{0}?",
9182
"zh-cht": "確認刪除用戶{0}?",
9183
"xloc": [
9163
- "default-mobile.handlebars->11->518"
9184
+ "default-mobile.handlebars->11->535"
9185
]
9186
},
9187
{
@@ -9181,7 +9202,7 @@
9202
"zh-cht": "將{1}入口{2}中的{0}限製到此位置?",
9203
"xloc": [
9204
"default-mobile.handlebars->11->138",
9184
- "default.handlebars->31->1652"
9205
+ "default.handlebars->31->1665"
9206
]
9207
},
9208
{
@@ -9205,8 +9226,8 @@
9226
"default-mobile.handlebars->11->345",
9227
"default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
9228
"default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3",
9208
- "default.handlebars->31->1421",
9209
- "default.handlebars->31->946",
9229
+ "default.handlebars->31->1434",
9230
+ "default.handlebars->31->959",
9231
"default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1span",
9232
"default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2span",
9233
"default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
@@ -9254,7 +9275,7 @@
9275
"zh-chs": "连接到服务器",
9276
"zh-cht": "連接到伺服器",
9277
"xloc": [
9257
- "default.handlebars->31->1475"
9278
+ "default.handlebars->31->1488"
9279
]
9280
},
9281
{
@@ -9376,7 +9397,7 @@
9397
"zh-chs": "已连接的英特尔®AMT",
9398
"zh-cht": "已連接的Intel® AMT",
9399
"xloc": [
9379
- "default.handlebars->31->2187"
9400
+ "default.handlebars->31->2200"
9401
]
9402
},
9403
{
@@ -9396,7 +9417,7 @@
9417
"zh-chs": "已连接的用户",
9418
"zh-cht": "已连接的用户",
9419
"xloc": [
9399
- "default.handlebars->31->2192"
9420
+ "default.handlebars->31->2205"
9421
]
9422
},
9423
{
@@ -9416,8 +9437,8 @@
9437
"zh-chs": "现在已连接",
9438
"zh-cht": "現在已連接",
9439
"xloc": [
9419
- "default-mobile.handlebars->11->388",
9420
- "default.handlebars->31->1006"
9440
+ "default-mobile.handlebars->11->405",
9441
+ "default.handlebars->31->1019"
9442
]
9443
},
9444
{
@@ -9460,11 +9481,11 @@
9481
"default-mobile.handlebars->11->2",
9482
"default-mobile.handlebars->11->381",
9483
"default-mobile.handlebars->11->48",
9484
+ "default.handlebars->31->1010",
9485
"default.handlebars->31->244",
9486
"default.handlebars->31->247",
9487
"default.handlebars->31->291",
9488
"default.handlebars->31->9",
9467
- "default.handlebars->31->997",
9489
"desktop.handlebars->3->2",
9490
"terminal.handlebars->3->2",
9491
"xterm.handlebars->9->2"
@@ -9487,7 +9508,7 @@
9508
"zh-chs": "连接数量",
9509
"zh-cht": "連接數量",
9510
"xloc": [
9490
- "default.handlebars->31->2206"
9511
+ "default.handlebars->31->2219"
9512
]
9513
},
9514
{
@@ -9507,7 +9528,7 @@
9528
"zh-chs": "连接转发器",
9529
"zh-cht": "連接轉發器",
9530
"xloc": [
9510
- "default.handlebars->31->2238"
9531
+ "default.handlebars->31->2251"
9532
]
9533
},
9534
{
@@ -9568,9 +9589,9 @@
9589
"zh-cht": "連接性",
9590
"xloc": [
9591
"default-mobile.handlebars->11->266",
9571
- "default.handlebars->31->1615",
9592
+ "default.handlebars->31->1628",
9593
"default.handlebars->31->235",
9573
- "default.handlebars->31->633",
9594
+ "default.handlebars->31->646",
9595
"default.handlebars->container->column_l->p21->3->1->meshConnChartDiv->1"
9596
]
9597
},
@@ -9591,8 +9612,8 @@
9612
"zh-chs": "控制台",
9613
"zh-cht": "控制台",
9614
"xloc": [
9594
- "default.handlebars->31->708",
9595
- "default.handlebars->31->729",
9615
+ "default.handlebars->31->721",
9616
+ "default.handlebars->31->742",
9617
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevConsole",
9618
"default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerConsole",
9619
"default.handlebars->contextMenu->cxconsole"
@@ -9635,8 +9656,8 @@
9656
"zh-chs": "控制",
9657
"zh-cht": "控制",
9658
"xloc": [
9638
- "default.handlebars->31->707",
9639
- "default.handlebars->31->728",
9659
+ "default.handlebars->31->720",
9660
+ "default.handlebars->31->741",
9661
"messenger.handlebars->13->1"
9662
]
9663
},
@@ -9657,7 +9678,7 @@
9678
"zh-chs": "Cookie编码器",
9679
"zh-cht": "Cookie編碼器",
9680
"xloc": [
9660
- "default.handlebars->31->2222"
9681
+ "default.handlebars->31->2235"
9682
]
9683
},
9684
{
@@ -9814,8 +9835,8 @@
9835
"zh-chs": "复制连结到剪贴板",
9836
"zh-cht": "複製連結到剪貼板",
9837
"xloc": [
9817
- "default.handlebars->31->1620",
9818
- "default.handlebars->31->1639",
9838
+ "default.handlebars->31->1633",
9839
+ "default.handlebars->31->1652",
9840
"default.handlebars->31->211",
9841
"default.handlebars->31->370"
9842
]
@@ -9918,7 +9939,7 @@
9939
"zh-chs": "复制:“{0}”到“{1}”",
9940
"zh-cht": "複製:“{0}”到“{1}”",
9941
"xloc": [
9921
- "default.handlebars->31->1711"
9942
+ "default.handlebars->31->1724"
9943
]
9944
},
9945
{
@@ -10064,7 +10085,7 @@
10085
"zh-chs": "核心服务器",
10086
"zh-cht": "核心伺服器",
10087
"xloc": [
10067
- "default.handlebars->31->2221"
10088
+ "default.handlebars->31->2234"
10089
]
10090
},
10091
{
@@ -10084,7 +10105,7 @@
10105
"zh-chs": "科西嘉文",
10106
"zh-cht": "科西嘉文",
10107
"xloc": [
10087
- "default.handlebars->31->1162"
10108
+ "default.handlebars->31->1175"
10109
]
10110
},
10111
{
@@ -10104,7 +10125,7 @@
10125
"zh-chs": "创建帐号",
10126
"zh-cht": "創建帳號",
10127
"xloc": [
10107
- "default.handlebars->31->1873",
10128
+ "default.handlebars->31->1886",
10129
"login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->12->1->1",
10130
"login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->12->1->1",
10131
"login2.handlebars->centralTable->1->0->logincell->createpanel->1->9->1->12->1->1"
@@ -10147,7 +10168,7 @@
10168
"zh-chs": "创建用户组",
10169
"zh-cht": "創建用戶群",
10170
"xloc": [
10150
- "default.handlebars->31->1912"
10171
+ "default.handlebars->31->1925"
10172
]
10173
},
10174
{
@@ -10167,7 +10188,7 @@
10188
"zh-chs": "创建连结以与访客共享此设备",
10189
"zh-cht": "創建鏈結以與訪客共享此裝置",
10190
"xloc": [
10170
- "default.handlebars->31->646"
10191
+ "default.handlebars->31->659"
10192
]
10193
},
10194
{
@@ -10187,7 +10208,7 @@
10208
"zh-chs": "使用以下选项创建一个新的设备组。",
10209
"zh-cht": "使用以下選項創建一個新的裝置群。",
10210
"xloc": [
10190
- "default.handlebars->31->1356"
10211
+ "default.handlebars->31->1369"
10212
]
10213
},
10214
{
@@ -10247,7 +10268,7 @@
10268
"zh-chs": "创建文件夹:“{0}”",
10269
"zh-cht": "創建文件夾:“{0}”",
10270
"xloc": [
10250
- "default.handlebars->31->1704"
10271
+ "default.handlebars->31->1717"
10272
]
10273
},
10274
{
@@ -10267,7 +10288,7 @@
10288
"zh-chs": "通过导入以下格式的JSON档案一次创建多个帐户:",
10289
"zh-cht": "通過導入以下格式的JSON檔案一次創建多個帳戶:",
10290
"xloc": [
10270
- "default.handlebars->31->1837"
10291
+ "default.handlebars->31->1850"
10292
]
10293
},
10294
{
@@ -10309,7 +10330,7 @@
10330
"zh-chs": "创建的设备组:{0}",
10331
"zh-cht": "創建的設備組:{0}",
10332
"xloc": [
10312
- "default.handlebars->31->1715"
10333
+ "default.handlebars->31->1728"
10334
]
10335
},
10336
{
@@ -10329,7 +10350,7 @@
10350
"zh-chs": "创建一个链接,该链接允许没有帐户的访客在有限的时间内远程控制此设备。",
10351
"zh-cht": "創建一個鏈接,該鏈接允許沒有帳戶的訪客在有限的時間內遠程控制此設備。",
10352
"xloc": [
10332
- "default.handlebars->31->747"
10353
+ "default.handlebars->31->760"
10354
]
10355
},
10356
{
@@ -10383,7 +10404,7 @@
10404
"zh-chs": "创建",
10405
"zh-cht": "創建",
10406
"xloc": [
10386
- "default.handlebars->31->1998"
10407
+ "default.handlebars->31->2011"
10408
]
10409
},
10410
{
@@ -10403,7 +10424,7 @@
10424
"zh-chs": "创建时间",
10425
"zh-cht": "創作時間",
10426
"xloc": [
10406
- "default.handlebars->31->1403"
10427
+ "default.handlebars->31->1416"
10428
]
10429
},
10430
{
@@ -10445,8 +10466,8 @@
10466
"zh-chs": "创建者",
10467
"zh-cht": "創作者",
10468
"xloc": [
10448
- "default.handlebars->31->1401",
10449
- "default.handlebars->31->1402"
10469
+ "default.handlebars->31->1414",
10470
+ "default.handlebars->31->1415"
10471
]
10472
},
10473
{
@@ -10466,7 +10487,7 @@
10487
"zh-chs": "证书",
10488
"zh-cht": "證書",
10489
"xloc": [
10469
- "default.handlebars->31->1373"
10490
+ "default.handlebars->31->1386"
10491
]
10492
},
10493
{
@@ -10486,7 +10507,7 @@
10507
"zh-chs": "克里语",
10508
"zh-cht": "克里語",
10509
"xloc": [
10489
- "default.handlebars->31->1163"
10510
+ "default.handlebars->31->1176"
10511
]
10512
},
10513
{
@@ -10506,7 +10527,7 @@
10527
"zh-chs": "克罗地亚文",
10528
"zh-cht": "克羅地亞文",
10529
"xloc": [
10509
- "default.handlebars->31->1164"
10530
+ "default.handlebars->31->1177"
10531
]
10532
},
10533
{
@@ -10571,8 +10592,8 @@
10592
"default-mobile.handlebars->11->334",
10593
"default-mobile.handlebars->11->338",
10594
"default.handlebars->31->57",
10574
- "default.handlebars->31->901",
10575
- "default.handlebars->31->905",
10595
+ "default.handlebars->31->914",
10596
+ "default.handlebars->31->918",
10597
"terminal.handlebars->3->6"
10598
]
10599
},
@@ -10680,8 +10701,8 @@
10701
"nl": "Huidig wachtwoord is niet correct.",
10702
"fr": "Le mot de passe actuel n'est pas correct.",
10703
"xloc": [
10683
- "default-mobile.handlebars->11->549",
10684
- "default.handlebars->31->2161"
10704
+ "default-mobile.handlebars->11->566",
10705
+ "default.handlebars->31->2174"
10706
]
10707
},
10708
{
@@ -10739,7 +10760,7 @@
10760
"zh-chs": "捷克文",
10761
"zh-cht": "捷克文",
10762
"xloc": [
10742
- "default.handlebars->31->1165"
10763
+ "default.handlebars->31->1178"
10764
]
10765
},
10766
{
@@ -10779,7 +10800,7 @@
10800
"zh-chs": "丹麦文",
10801
"zh-cht": "丹麥文",
10802
"xloc": [
10782
- "default.handlebars->31->1166"
10803
+ "default.handlebars->31->1179"
10804
]
10805
},
10806
{
@@ -10799,7 +10820,7 @@
10820
"zh-chs": "数据通道",
10821
"zh-cht": "數據通道",
10822
"xloc": [
10802
- "default.handlebars->31->869",
10823
+ "default.handlebars->31->882",
10824
"desktop.handlebars->3->11"
10825
]
10826
},
@@ -10820,7 +10841,7 @@
10841
"zh-chs": "日期和时间",
10842
"zh-cht": "日期和時間",
10843
"xloc": [
10823
- "default.handlebars->31->1324"
10844
+ "default.handlebars->31->1337"
10845
]
10846
},
10847
{
@@ -10841,7 +10862,7 @@
10862
"zh-cht": "天",
10863
"xloc": [
10864
"default-mobile.handlebars->11->291",
10844
- "default.handlebars->31->796"
10865
+ "default.handlebars->31->809"
10866
]
10867
},
10868
{
@@ -10861,7 +10882,7 @@
10882
"zh-chs": "停用",
10883
"zh-cht": "停用",
10884
"xloc": [
10864
- "default.handlebars->31->1454"
10885
+ "default.handlebars->31->1467"
10886
]
10887
},
10888
{
@@ -10881,7 +10902,7 @@
10902
"zh-chs": "如果设置停用CCM",
10903
"zh-cht": "如果設置停用CCM",
10904
"xloc": [
10884
- "default.handlebars->31->1466"
10905
+ "default.handlebars->31->1479"
10906
]
10907
},
10908
{
@@ -10939,10 +10960,10 @@
10960
"zh-chs": "默认",
10961
"zh-cht": "默認",
10962
"xloc": [
10942
- "default.handlebars->31->1860",
10943
- "default.handlebars->31->1908",
10944
- "default.handlebars->31->1919",
10945
- "default.handlebars->31->1987"
10963
+ "default.handlebars->31->1873",
10964
+ "default.handlebars->31->1921",
10965
+ "default.handlebars->31->1932",
10966
+ "default.handlebars->31->2000"
10967
]
10968
},
10969
{
@@ -10951,7 +10972,7 @@
10972
"nl": "Del",
10973
"xloc": [
10974
"default-mobile.handlebars->11->322",
10954
- "default.handlebars->31->889"
10975
+ "default.handlebars->31->902"
10976
]
10977
},
10978
{
@@ -10975,9 +10996,9 @@
10996
"default-mobile.handlebars->11->355",
10997
"default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1",
10998
"default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1",
10978
- "default.handlebars->31->1646",
10999
+ "default.handlebars->31->1659",
11000
"default.handlebars->31->535",
10980
- "default.handlebars->31->965",
11001
+ "default.handlebars->31->978",
11002
"default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
11003
"default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
11004
"default.handlebars->container->dialog->idx_dlgButtonBar->5",
@@ -11006,7 +11027,7 @@
11027
"zh-cht": "刪除帳戶",
11028
"xloc": [
11029
"default-mobile.handlebars->11->95",
11009
- "default.handlebars->31->1341"
11030
+ "default.handlebars->31->1354"
11031
]
11032
},
11033
{
@@ -11026,7 +11047,7 @@
11047
"zh-chs": "删除帐户",
11048
"zh-cht": "刪除帳戶",
11049
"xloc": [
11029
- "default.handlebars->31->1827"
11050
+ "default.handlebars->31->1840"
11051
]
11052
},
11053
{
@@ -11047,7 +11068,7 @@
11068
"zh-cht": "刪除裝置",
11069
"xloc": [
11070
"default-mobile.handlebars->11->271",
11050
- "default.handlebars->31->650"
11071
+ "default.handlebars->31->663"
11072
]
11073
},
11074
{
@@ -11067,10 +11088,10 @@
11088
"zh-chs": "删除群组",
11089
"zh-cht": "刪除群組",
11090
"xloc": [
11070
- "default-mobile.handlebars->11->465",
11071
- "default-mobile.handlebars->11->468",
11072
- "default.handlebars->31->1450",
11073
- "default.handlebars->31->1483"
11091
+ "default-mobile.handlebars->11->482",
11092
+ "default-mobile.handlebars->11->485",
11093
+ "default.handlebars->31->1463",
11094
+ "default.handlebars->31->1496"
11095
]
11096
},
11097
{
@@ -11091,7 +11112,7 @@
11112
"zh-cht": "刪除節點",
11113
"xloc": [
11114
"default-mobile.handlebars->11->299",
11094
- "default.handlebars->31->822"
11115
+ "default.handlebars->31->835"
11116
]
11117
},
11118
{
@@ -11131,7 +11152,7 @@
11152
"zh-chs": "删除用户",
11153
"zh-cht": "刪除用戶",
11154
"xloc": [
11134
- "default.handlebars->31->2039"
11155
+ "default.handlebars->31->2052"
11156
]
11157
},
11158
{
@@ -11151,8 +11172,8 @@
11172
"zh-chs": "删除用户群组",
11173
"zh-cht": "刪除用戶群組",
11174
"xloc": [
11154
- "default.handlebars->31->1957",
11155
- "default.handlebars->31->1967"
11175
+ "default.handlebars->31->1970",
11176
+ "default.handlebars->31->1980"
11177
]
11178
},
11179
{
@@ -11172,7 +11193,7 @@
11193
"zh-chs": "删除用户群组",
11194
"zh-cht": "刪除用戶群組",
11195
"xloc": [
11175
- "default.handlebars->31->1906"
11196
+ "default.handlebars->31->1919"
11197
]
11198
},
11199
{
@@ -11192,7 +11213,7 @@
11213
"zh-chs": "删除用户{0}",
11214
"zh-cht": "刪除用戶{0}",
11215
"xloc": [
11195
- "default.handlebars->31->2062"
11216
+ "default.handlebars->31->2075"
11217
]
11218
},
11219
{
@@ -11213,7 +11234,7 @@
11234
"zh-cht": "刪除帳戶",
11235
"xloc": [
11236
"default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountActions->3->9->0",
11216
- "default.handlebars->31->1823",
11237
+ "default.handlebars->31->1836",
11238
"default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->p2AccountPassActions->7"
11239
]
11240
},
@@ -11254,7 +11275,7 @@
11275
"zh-chs": "删除群组",
11276
"zh-cht": "刪除群組",
11277
"xloc": [
11257
- "default.handlebars->31->1902"
11278
+ "default.handlebars->31->1915"
11279
]
11280
},
11281
{
@@ -11294,7 +11315,7 @@
11315
"zh-chs": "递归删除:“{0}”,{1}个元素已删除",
11316
"zh-cht": "遞歸刪除:“{0}”,{1}個元素已刪除",
11317
"xloc": [
11297
- "default.handlebars->31->1706"
11318
+ "default.handlebars->31->1719"
11319
]
11320
},
11321
{
@@ -11316,8 +11337,8 @@
11337
"xloc": [
11338
"default-mobile.handlebars->11->135",
11339
"default-mobile.handlebars->11->357",
11319
- "default.handlebars->31->1648",
11320
- "default.handlebars->31->967"
11340
+ "default.handlebars->31->1661",
11341
+ "default.handlebars->31->980"
11342
]
11343
},
11344
{
@@ -11337,7 +11358,7 @@
11358
"zh-chs": "删除用户群组{0}?",
11359
"zh-cht": "刪除用戶群組{0}?",
11360
"xloc": [
11340
- "default.handlebars->31->1965"
11361
+ "default.handlebars->31->1978"
11362
]
11363
},
11364
{
@@ -11359,8 +11380,8 @@
11380
"xloc": [
11381
"default-mobile.handlebars->11->134",
11382
"default-mobile.handlebars->11->356",
11362
- "default.handlebars->31->1647",
11363
- "default.handlebars->31->966"
11383
+ "default.handlebars->31->1660",
11384
+ "default.handlebars->31->979"
11385
]
11386
},
11387
{
@@ -11400,7 +11421,7 @@
11421
"zh-chs": "删除:“{0}”",
11422
"zh-cht": "刪除:“{0}”",
11423
"xloc": [
11403
- "default.handlebars->31->1705"
11424
+ "default.handlebars->31->1718"
11425
]
11426
},
11427
{
@@ -11420,7 +11441,7 @@
11441
"zh-chs": "删除:“{0}”,{1}个元素已删除",
11442
"zh-cht": "刪除:“{0}”,已刪除{1}個元素",
11443
"xloc": [
11423
- "default.handlebars->31->1707"
11444
+ "default.handlebars->31->1720"
11445
]
11446
},
11447
{
@@ -11441,7 +11462,7 @@
11462
"zh-cht": "被拒絕",
11463
"xloc": [
11464
"default-mobile.handlebars->11->310",
11444
- "default.handlebars->31->865",
11465
+ "default.handlebars->31->878",
11466
"desktop.handlebars->3->7",
11467
"terminal.handlebars->3->11"
11468
]
@@ -11536,21 +11557,21 @@
11557
"default-mobile.handlebars->11->236",
11558
"default-mobile.handlebars->11->237",
11559
"default-mobile.handlebars->11->305",
11539
- "default-mobile.handlebars->11->400",
11540
- "default-mobile.handlebars->11->457",
11541
- "default-mobile.handlebars->11->470",
11542
- "default.handlebars->31->1018",
11543
- "default.handlebars->31->1028",
11544
- "default.handlebars->31->1361",
11545
- "default.handlebars->31->1398",
11546
- "default.handlebars->31->1485",
11547
- "default.handlebars->31->1911",
11548
- "default.handlebars->31->1921",
11549
- "default.handlebars->31->1922",
11550
- "default.handlebars->31->1963",
11560
+ "default-mobile.handlebars->11->417",
11561
+ "default-mobile.handlebars->11->474",
11562
+ "default-mobile.handlebars->11->487",
11563
+ "default.handlebars->31->1031",
11564
+ "default.handlebars->31->1041",
11565
+ "default.handlebars->31->1374",
11566
+ "default.handlebars->31->1411",
11567
+ "default.handlebars->31->1498",
11568
+ "default.handlebars->31->1924",
11569
+ "default.handlebars->31->1934",
11570
+ "default.handlebars->31->1935",
11571
+ "default.handlebars->31->1976",
11572
"default.handlebars->31->576",
11573
"default.handlebars->31->577",
11553
- "default.handlebars->31->860",
11574
+ "default.handlebars->31->873",
11575
"default.handlebars->31->88",
11576
"default.handlebars->container->column_l->p42->p42tbl->1->0->3"
11577
]
@@ -11590,12 +11611,12 @@
11611
"zh-cht": "桌面",
11612
"xloc": [
11613
"default-mobile.handlebars->11->278",
11593
- "default.handlebars->31->1491",
11594
- "default.handlebars->31->2111",
11614
+ "default.handlebars->31->1504",
11615
+ "default.handlebars->31->2124",
11616
"default.handlebars->31->541",
11596
- "default.handlebars->31->695",
11597
- "default.handlebars->31->750",
11598
- "default.handlebars->31->931",
11617
+ "default.handlebars->31->708",
11618
+ "default.handlebars->31->763",
11619
+ "default.handlebars->31->944",
11620
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
11621
"default.handlebars->contextMenu->cxdesktop",
11622
"desktop.handlebars->3->23"
@@ -11638,10 +11659,10 @@
11659
"zh-chs": "桌面通知",
11660
"zh-cht": "桌面通知",
11661
"xloc": [
11641
- "default.handlebars->31->1412",
11642
- "default.handlebars->31->1926",
11643
- "default.handlebars->31->2013",
11644
- "default.handlebars->31->614"
11662
+ "default.handlebars->31->1425",
11663
+ "default.handlebars->31->1939",
11664
+ "default.handlebars->31->2026",
11665
+ "default.handlebars->31->627"
11666
]
11667
},
11668
{
@@ -11661,10 +11682,10 @@
11682
"zh-chs": "桌面提示",
11683
"zh-cht": "桌面提示",
11684
"xloc": [
11664
- "default.handlebars->31->1411",
11665
- "default.handlebars->31->1925",
11666
- "default.handlebars->31->2012",
11667
- "default.handlebars->31->613"
11685
+ "default.handlebars->31->1424",
11686
+ "default.handlebars->31->1938",
11687
+ "default.handlebars->31->2025",
11688
+ "default.handlebars->31->626"
11689
]
11690
},
11691
{
@@ -11684,10 +11705,10 @@
11705
"zh-chs": "桌面提示+工具栏",
11706
"zh-cht": "桌面提示+工具欄",
11707
"xloc": [
11687
- "default.handlebars->31->1409",
11688
- "default.handlebars->31->1923",
11689
- "default.handlebars->31->2010",
11690
- "default.handlebars->31->611"
11708
+ "default.handlebars->31->1422",
11709
+ "default.handlebars->31->1936",
11710
+ "default.handlebars->31->2023",
11711
+ "default.handlebars->31->624"
11712
]
11713
},
11714
{
@@ -11749,17 +11770,17 @@
11770
"zh-chs": "桌面工具栏",
11771
"zh-cht": "桌面工具欄",
11772
"xloc": [
11752
- "default.handlebars->31->1410",
11753
- "default.handlebars->31->1924",
11754
- "default.handlebars->31->2011",
11755
- "default.handlebars->31->612"
11773
+ "default.handlebars->31->1423",
11774
+ "default.handlebars->31->1937",
11775
+ "default.handlebars->31->2024",
11776
+ "default.handlebars->31->625"
11777
]
11778
},
11779
{
11780
"en": "Desktop, View only",
11781
"nl": "Desktop, Alleen kijken",
11782
"xloc": [
11762
- "default.handlebars->31->751"
11783
+ "default.handlebars->31->764"
11784
]
11785
},
11786
{
@@ -11779,7 +11800,7 @@
11800
"zh-chs": "桌面时段",
11801
"zh-cht": "桌面時段",
11802
"xloc": [
11782
- "default.handlebars->31->930"
11803
+ "default.handlebars->31->943"
11804
]
11805
},
11806
{
@@ -11862,11 +11883,11 @@
11883
"zh-chs": "设备",
11884
"zh-cht": "裝置",
11885
"xloc": [
11865
- "default-mobile.handlebars->11->395",
11866
- "default.handlebars->31->1013",
11867
- "default.handlebars->31->1514",
11886
+ "default-mobile.handlebars->11->412",
11887
+ "default.handlebars->31->1026",
11888
+ "default.handlebars->31->1527",
11889
"default.handlebars->31->197",
11869
- "default.handlebars->31->2081",
11890
+ "default.handlebars->31->2094",
11891
"default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->5"
11892
]
11893
},
@@ -11889,7 +11910,7 @@
11910
"xloc": [
11911
"default-mobile.handlebars->11->288",
11912
"default-mobile.handlebars->11->289",
11892
- "default.handlebars->31->787"
11913
+ "default.handlebars->31->800"
11914
]
11915
},
11916
{
@@ -11930,16 +11951,16 @@
11951
"zh-cht": "裝置群",
11952
"xloc": [
11953
"agent-translations.json",
11933
- "default-mobile.handlebars->11->527",
11934
- "default.handlebars->31->1509",
11935
- "default.handlebars->31->1512",
11936
- "default.handlebars->31->1513",
11937
- "default.handlebars->31->1774",
11938
- "default.handlebars->31->1949",
11939
- "default.handlebars->31->1955",
11940
- "default.handlebars->31->2069",
11941
- "default.handlebars->31->2120",
11942
- "default.handlebars->31->2139"
11954
+ "default-mobile.handlebars->11->544",
11955
+ "default.handlebars->31->1522",
11956
+ "default.handlebars->31->1525",
11957
+ "default.handlebars->31->1526",
11958
+ "default.handlebars->31->1787",
11959
+ "default.handlebars->31->1962",
11960
+ "default.handlebars->31->1968",
11961
+ "default.handlebars->31->2082",
11962
+ "default.handlebars->31->2133",
11963
+ "default.handlebars->31->2152"
11964
]
11965
},
11966
{
@@ -11959,8 +11980,8 @@
11980
"zh-chs": "设备组用户",
11981
"zh-cht": "裝置群用戶",
11982
"xloc": [
11962
- "default-mobile.handlebars->11->516",
11963
- "default.handlebars->31->1578"
11983
+ "default-mobile.handlebars->11->533",
11984
+ "default.handlebars->31->1591"
11985
]
11986
},
11987
{
@@ -11981,11 +12002,11 @@
12002
"zh-cht": "裝置群",
12003
"xloc": [
12004
"default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->3",
11984
- "default.handlebars->31->1790",
11985
- "default.handlebars->31->1896",
11986
- "default.handlebars->31->1936",
11987
- "default.handlebars->31->2007",
11988
- "default.handlebars->31->2190",
12005
+ "default.handlebars->31->1803",
12006
+ "default.handlebars->31->1909",
12007
+ "default.handlebars->31->1949",
12008
+ "default.handlebars->31->2020",
12009
+ "default.handlebars->31->2203",
12010
"default.handlebars->container->column_l->p2->p2info->7"
12011
]
12012
},
@@ -12026,7 +12047,7 @@
12047
"zh-chs": "设备位置",
12048
"zh-cht": "裝置位置",
12049
"xloc": [
12029
- "default.handlebars->31->823"
12050
+ "default.handlebars->31->836"
12051
]
12052
},
12053
{
@@ -12046,7 +12067,7 @@
12067
"zh-chs": "设备消息",
12068
"zh-cht": "裝置訊息",
12069
"xloc": [
12049
- "default.handlebars->31->744"
12070
+ "default.handlebars->31->757"
12071
]
12072
},
12073
{
@@ -12067,9 +12088,9 @@
12088
"zh-cht": "裝置名稱",
12089
"xloc": [
12090
"default-mobile.handlebars->11->303",
12070
- "default.handlebars->31->2119",
12091
+ "default.handlebars->31->2132",
12092
"default.handlebars->31->305",
12072
- "default.handlebars->31->858",
12093
+ "default.handlebars->31->871",
12094
"player.handlebars->3->9"
12095
]
12096
},
@@ -12091,7 +12112,7 @@
12112
"zh-cht": "裝置通知",
12113
"xloc": [
12114
"default.handlebars->31->494",
12094
- "default.handlebars->31->746"
12115
+ "default.handlebars->31->759"
12116
]
12117
},
12118
{
@@ -12128,7 +12149,7 @@
12149
"zh-chs": "设备共享链接",
12150
"zh-cht": "設備共享鏈接",
12151
"xloc": [
12131
- "default.handlebars->31->691"
12152
+ "default.handlebars->31->704"
12153
]
12154
},
12155
{
@@ -12168,8 +12189,8 @@
12189
"zh-chs": "设备连接。",
12190
"zh-cht": "裝置連接。",
12191
"xloc": [
12171
- "default.handlebars->31->1329",
12172
- "default.handlebars->31->1599"
12192
+ "default.handlebars->31->1342",
12193
+ "default.handlebars->31->1612"
12194
]
12195
},
12196
{
@@ -12189,8 +12210,8 @@
12210
"zh-chs": "设备断开连接。",
12211
"zh-cht": "裝置斷開連接。",
12212
"xloc": [
12192
- "default.handlebars->31->1330",
12193
- "default.handlebars->31->1600"
12213
+ "default.handlebars->31->1343",
12214
+ "default.handlebars->31->1613"
12215
]
12216
},
12217
{
@@ -12210,7 +12231,7 @@
12231
"zh-chs": "创建的设备组:{0}",
12232
"zh-cht": "設備組已創建:{0}",
12233
"xloc": [
12213
- "default.handlebars->31->1736"
12234
+ "default.handlebars->31->1749"
12235
]
12236
},
12237
{
@@ -12230,7 +12251,7 @@
12251
"zh-chs": "设备组已删除:{0}",
12252
"zh-cht": "設備組已刪除:{0}",
12253
"xloc": [
12233
- "default.handlebars->31->1737"
12254
+ "default.handlebars->31->1750"
12255
]
12256
},
12257
{
@@ -12250,7 +12271,7 @@
12271
"zh-chs": "设备组成员身份已更改:{0}",
12272
"zh-cht": "設備組成員身份已更改:{0}",
12273
"xloc": [
12253
- "default.handlebars->31->1738"
12274
+ "default.handlebars->31->1751"
12275
]
12276
},
12277
{
@@ -12270,7 +12291,7 @@
12291
"zh-chs": "其他设备组管理员可以查看和更改设备组注释。",
12292
"zh-cht": "其他裝置群管理員可以查看和更改裝置群註釋。",
12293
"xloc": [
12273
- "default.handlebars->31->741"
12294
+ "default.handlebars->31->754"
12295
]
12296
},
12297
{
@@ -12290,7 +12311,7 @@
12311
"zh-chs": "设备组通知已更改",
12312
"zh-cht": "設備組通知已更改",
12313
"xloc": [
12293
- "default.handlebars->31->1733"
12314
+ "default.handlebars->31->1746"
12315
]
12316
},
12317
{
@@ -12310,7 +12331,7 @@
12331
"zh-chs": "未删除的设备组:{0}",
12332
"zh-cht": "未刪除的設備組:{0}",
12333
"xloc": [
12313
- "default.handlebars->31->1716"
12334
+ "default.handlebars->31->1729"
12335
]
12336
},
12337
{
@@ -12703,7 +12724,7 @@
12724
"zh-chs": "设备请求激活Intel(R)AMT ACM,FQDN:{0}",
12725
"zh-cht": "設備請求激活Intel(R)AMT ACM,FQDN:{0}",
12726
"xloc": [
12706
- "default.handlebars->31->1718"
12727
+ "default.handlebars->31->1731"
12728
]
12729
},
12730
{
@@ -12740,8 +12761,8 @@
12761
"zh-chs": "设备",
12762
"zh-cht": "裝置",
12763
"xloc": [
12743
- "default.handlebars->31->1897",
12744
- "default.handlebars->31->1937"
12764
+ "default.handlebars->31->1910",
12765
+ "default.handlebars->31->1950"
12766
]
12767
},
12768
{
@@ -12761,7 +12782,8 @@
12782
"zh-chs": "已禁用",
12783
"zh-cht": "已禁用",
12784
"xloc": [
12764
- "default.handlebars->31->607"
12785
+ "default-mobile.handlebars->11->398",
12786
+ "default.handlebars->31->620"
12787
]
12788
},
12789
{
@@ -12781,7 +12803,7 @@
12803
"zh-chs": "禁用的电子邮件两因素身份验证",
12804
"zh-cht": "禁用的電子郵件兩因素身份驗證",
12805
"xloc": [
12784
- "default.handlebars->31->1749"
12806
+ "default.handlebars->31->1762"
12807
]
12808
},
12809
{
@@ -12804,8 +12826,8 @@
12826
"agent-translations.json",
12827
"default-mobile.handlebars->11->346",
12828
"default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
12807
- "default.handlebars->31->1422",
12808
- "default.handlebars->31->947",
12829
+ "default.handlebars->31->1435",
12830
+ "default.handlebars->31->960",
12831
"default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->disconnectbutton1span",
12832
"default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->disconnectbutton2span",
12833
"desktop.handlebars->p11->deskarea0->deskarea1->3->disconnectbutton1span",
@@ -12905,7 +12927,7 @@
12927
"zh-chs": "在远程设备上显示一个消息框。",
12928
"zh-cht": "在遠程裝置上顯示一個訊息框。",
12929
"xloc": [
12908
- "default.handlebars->31->745"
12930
+ "default.handlebars->31->758"
12931
]
12932
},
12933
{
@@ -12945,7 +12967,7 @@
12967
"zh-chs": "在远程设备上显示短信",
12968
"zh-cht": "在遠程裝置上顯示短信",
12969
"xloc": [
12948
- "default.handlebars->31->644"
12970
+ "default.handlebars->31->657"
12971
]
12972
},
12973
{
@@ -12965,7 +12987,7 @@
12987
"zh-chs": "显示设备组名称",
12988
"zh-cht": "顯示裝置群名稱",
12989
"xloc": [
12968
- "default.handlebars->31->1328"
12990
+ "default.handlebars->31->1341"
12991
]
12992
},
12993
{
@@ -12985,7 +13007,7 @@
13007
"zh-chs": "显示名称",
13008
"zh-cht": "顯示名稱",
13009
"xloc": [
12988
- "default.handlebars->31->916"
13010
+ "default.handlebars->31->929"
13011
]
13012
},
13013
{
@@ -13005,7 +13027,7 @@
13027
"zh-chs": "显示公共连结",
13028
"zh-cht": "顯示公共鏈結",
13029
"xloc": [
13008
- "default.handlebars->31->1619"
13030
+ "default.handlebars->31->1632"
13031
]
13032
},
13033
{
@@ -13025,7 +13047,7 @@
13047
"zh-chs": "显示消息框,标题= “{0}”,消息= “{1}”",
13048
"zh-cht": "顯示消息框,標題= “{0}”,消息= “{1}”",
13049
"xloc": [
13028
- "default.handlebars->31->1678"
13050
+ "default.handlebars->31->1691"
13051
]
13052
},
13053
{
@@ -13045,7 +13067,7 @@
13067
"zh-chs": "显示吐司消息,标题= “{0}”,消息= “{1}”",
13068
"zh-cht": "顯示吐司消息,標題= “{0}”,消息= “{1}”",
13069
"xloc": [
13048
- "default.handlebars->31->1686"
13070
+ "default.handlebars->31->1699"
13071
]
13072
},
13073
{
@@ -13065,8 +13087,8 @@
13087
"zh-chs": "什么都不做",
13088
"zh-cht": "什麼都不做",
13089
"xloc": [
13068
- "default.handlebars->31->1469",
13069
- "default.handlebars->31->1473"
13090
+ "default.handlebars->31->1482",
13091
+ "default.handlebars->31->1486"
13092
]
13093
},
13094
{
@@ -13086,10 +13108,10 @@
13108
"zh-chs": "域",
13109
"zh-cht": "域",
13110
"xloc": [
13089
- "default.handlebars->31->1861",
13090
- "default.handlebars->31->1909",
13091
- "default.handlebars->31->1918",
13092
- "default.handlebars->31->1986",
13111
+ "default.handlebars->31->1874",
13112
+ "default.handlebars->31->1922",
13113
+ "default.handlebars->31->1931",
13114
+ "default.handlebars->31->1999",
13115
"mstsc.handlebars->main->1->3->1->2->1->0",
13116
"mstsc.handlebars->main->1->3->1->2->3"
13117
]
@@ -13111,7 +13133,7 @@
13133
"zh-chs": "请勿更改,如果设置请保留CCM",
13134
"zh-cht": "請勿更改,如果設置請保留CCM",
13135
"xloc": [
13114
- "default.handlebars->31->1465"
13136
+ "default.handlebars->31->1478"
13137
]
13138
},
13139
{
@@ -13148,7 +13170,7 @@
13170
"zh-chs": "不要连接到服务器",
13171
"zh-cht": "不要連接到伺服器",
13172
"xloc": [
13151
- "default.handlebars->31->1474"
13173
+ "default.handlebars->31->1487"
13174
]
13175
},
13176
{
@@ -13213,7 +13235,7 @@
13235
"nl": "Omlaag",
13236
"xloc": [
13237
"default-mobile.handlebars->11->330",
13216
- "default.handlebars->31->897"
13238
+ "default.handlebars->31->910"
13239
]
13240
},
13241
{
@@ -13277,7 +13299,7 @@
13299
"zh-cht": "下載檔案",
13300
"xloc": [
13301
"default-mobile.handlebars->11->376",
13280
- "default.handlebars->31->986"
13302
+ "default.handlebars->31->999"
13303
]
13304
},
13305
{
@@ -13317,7 +13339,7 @@
13339
"zh-chs": "下载MeshCmd",
13340
"zh-cht": "下載MeshCmd",
13341
"xloc": [
13320
- "default.handlebars->31->848"
13342
+ "default.handlebars->31->861"
13343
]
13344
},
13345
{
@@ -13377,7 +13399,7 @@
13399
"zh-chs": "下载报告",
13400
"zh-cht": "下載報告",
13401
"xloc": [
13380
- "default.handlebars->31->1779",
13402
+ "default.handlebars->31->1792",
13403
"default.handlebars->container->column_l->p3->3->1->0->3"
13404
]
13405
},
@@ -13398,7 +13420,7 @@
13420
"zh-chs": "下载带有指令档案的“ meshcmd”,以通过此服务器将网络讯息发送到该设备。紧记编辑meshaction.txt并添加您的帐户密码或进行任何必要的更改。",
13421
"zh-cht": "下載帶有指令檔案的“ meshcmd”,以通過此服務器將網絡讯息發送到該裝置。緊記編輯meshaction.txt並新增你的帳戶密碼或進行任何必要的更改。",
13422
"xloc": [
13401
- "default.handlebars->31->841"
13423
+ "default.handlebars->31->854"
13424
]
13425
},
13426
{
@@ -13478,7 +13500,7 @@
13500
"zh-chs": "下载电源事件",
13501
"zh-cht": "下載電源事件",
13502
"xloc": [
13481
- "default.handlebars->31->797"
13503
+ "default.handlebars->31->810"
13504
]
13505
},
13506
{
@@ -13578,7 +13600,7 @@
13600
"zh-chs": "使用以下一种档案格式下载事件列表。",
13601
"zh-cht": "使用以下一種檔案格式下載事件列表。",
13602
"xloc": [
13581
- "default.handlebars->31->1780"
13603
+ "default.handlebars->31->1793"
13604
]
13605
},
13606
{
@@ -13598,7 +13620,7 @@
13620
"zh-chs": "使用以下一种档案格式下载用户列表。",
13621
"zh-cht": "使用以下一種檔案格式下載用戶列表。",
13622
"xloc": [
13601
- "default.handlebars->31->1845"
13623
+ "default.handlebars->31->1858"
13624
]
13625
},
13626
{
@@ -13679,7 +13701,7 @@
13701
"zh-chs": "下载:“{0}”",
13702
"zh-cht": "下載:“{0}”",
13703
"xloc": [
13682
- "default.handlebars->31->1709"
13704
+ "default.handlebars->31->1722"
13705
]
13706
},
13707
{
@@ -13719,7 +13741,7 @@
13741
"zh-chs": "代理重复",
13742
"zh-cht": "代理重複",
13743
"xloc": [
13722
- "default.handlebars->31->2186"
13744
+ "default.handlebars->31->2199"
13745
]
13746
},
13747
{
@@ -13759,7 +13781,7 @@
13781
"zh-chs": "复制用户组",
13782
"zh-cht": "複製用戶群",
13783
"xloc": [
13762
- "default.handlebars->31->1913"
13784
+ "default.handlebars->31->1926"
13785
]
13786
},
13787
{
@@ -13796,8 +13818,8 @@
13818
"zh-chs": "持续时间",
13819
"zh-cht": "持續時間",
13820
"xloc": [
13799
- "default.handlebars->31->2105",
13800
- "default.handlebars->31->2125",
13821
+ "default.handlebars->31->2118",
13822
+ "default.handlebars->31->2138",
13823
"player.handlebars->3->2"
13824
]
13825
},
@@ -13835,7 +13857,7 @@
13857
"zh-chs": "荷兰文(比利时)",
13858
"zh-cht": "荷蘭文(比利時)",
13859
"xloc": [
13838
- "default.handlebars->31->1168"
13860
+ "default.handlebars->31->1181"
13861
]
13862
},
13863
{
@@ -13855,7 +13877,7 @@
13877
"zh-chs": "荷兰文(标准)",
13878
"zh-cht": "荷蘭文(標準)",
13879
"xloc": [
13858
- "default.handlebars->31->1167"
13880
+ "default.handlebars->31->1180"
13881
]
13882
},
13883
{
@@ -14144,7 +14166,7 @@
14166
"zh-cht": "編輯裝置",
14167
"xloc": [
14168
"default-mobile.handlebars->11->308",
14147
- "default.handlebars->31->863"
14169
+ "default.handlebars->31->876"
14170
]
14171
},
14172
{
@@ -14164,13 +14186,13 @@
14186
"zh-chs": "编辑设备组",
14187
"zh-cht": "編輯裝置群",
14188
"xloc": [
14167
- "default-mobile.handlebars->11->471",
14168
- "default-mobile.handlebars->11->473",
14169
- "default-mobile.handlebars->11->493",
14170
- "default.handlebars->31->1486",
14171
- "default.handlebars->31->1518",
14172
- "default.handlebars->31->1542",
14173
- "default.handlebars->31->1554"
14189
+ "default-mobile.handlebars->11->488",
14190
+ "default-mobile.handlebars->11->490",
14191
+ "default-mobile.handlebars->11->510",
14192
+ "default.handlebars->31->1499",
14193
+ "default.handlebars->31->1531",
14194
+ "default.handlebars->31->1555",
14195
+ "default.handlebars->31->1567"
14196
]
14197
},
14198
{
@@ -14190,7 +14212,7 @@
14212
"zh-chs": "编辑设备组功能",
14213
"zh-cht": "編輯裝置群功能",
14214
"xloc": [
14193
- "default.handlebars->31->1504"
14215
+ "default.handlebars->31->1517"
14216
]
14217
},
14218
{
@@ -14210,8 +14232,8 @@
14232
"zh-chs": "编辑设备组权限",
14233
"zh-cht": "編輯裝置群權限",
14234
"xloc": [
14213
- "default.handlebars->31->1539",
14214
- "default.handlebars->31->1551"
14235
+ "default.handlebars->31->1552",
14236
+ "default.handlebars->31->1564"
14237
]
14238
},
14239
{
@@ -14231,7 +14253,7 @@
14253
"zh-chs": "编辑设备组用户同意",
14254
"zh-cht": "編輯裝置群用戶同意",
14255
"xloc": [
14234
- "default.handlebars->31->1487"
14256
+ "default.handlebars->31->1500"
14257
]
14258
},
14259
{
@@ -14251,8 +14273,8 @@
14273
"zh-chs": "编辑设备笔记",
14274
"zh-cht": "編輯裝置筆記",
14275
"xloc": [
14254
- "default-mobile.handlebars->11->485",
14255
- "default.handlebars->31->1531"
14276
+ "default-mobile.handlebars->11->502",
14277
+ "default.handlebars->31->1544"
14278
]
14279
},
14280
{
@@ -14272,8 +14294,8 @@
14294
"zh-chs": "编辑设备权限",
14295
"zh-cht": "編輯裝置權限",
14296
"xloc": [
14275
- "default.handlebars->31->1544",
14276
- "default.handlebars->31->1546"
14297
+ "default.handlebars->31->1557",
14298
+ "default.handlebars->31->1559"
14299
]
14300
},
14301
{
@@ -14313,7 +14335,7 @@
14335
"zh-chs": "编辑设备用户同意",
14336
"zh-cht": "編輯裝置用戶同意",
14337
"xloc": [
14316
- "default.handlebars->31->1489"
14338
+ "default.handlebars->31->1502"
14339
]
14340
},
14341
{
@@ -14333,7 +14355,7 @@
14355
"zh-chs": "编辑群组",
14356
"zh-cht": "編輯群組",
14357
"xloc": [
14336
- "default.handlebars->31->719"
14358
+ "default.handlebars->31->732"
14359
]
14360
},
14361
{
@@ -14360,7 +14382,7 @@
14382
"default.handlebars->31->591",
14383
"default.handlebars->31->594",
14384
"default.handlebars->31->597",
14363
- "default.handlebars->31->804"
14385
+ "default.handlebars->31->817"
14386
]
14387
},
14388
{
@@ -14380,8 +14402,8 @@
14402
"zh-chs": "编辑笔记",
14403
"zh-cht": "編輯筆記",
14404
"xloc": [
14383
- "default-mobile.handlebars->11->500",
14384
- "default.handlebars->31->1561"
14405
+ "default-mobile.handlebars->11->517",
14406
+ "default.handlebars->31->1574"
14407
]
14408
},
14409
{
@@ -14401,7 +14423,7 @@
14423
"zh-chs": "编辑用户同意",
14424
"zh-cht": "編輯用戶同意",
14425
"xloc": [
14404
- "default.handlebars->31->1488"
14426
+ "default.handlebars->31->1501"
14427
]
14428
},
14429
{
@@ -14421,7 +14443,7 @@
14443
"zh-chs": "编辑用户设备组权限",
14444
"zh-cht": "編輯用戶裝置群權限",
14445
"xloc": [
14424
- "default.handlebars->31->1552"
14446
+ "default.handlebars->31->1565"
14447
]
14448
},
14449
{
@@ -14441,7 +14463,7 @@
14463
"zh-chs": "编辑用户设备权限",
14464
"zh-cht": "編輯用戶裝置權限",
14465
"xloc": [
14444
- "default.handlebars->31->1547"
14466
+ "default.handlebars->31->1560"
14467
]
14468
},
14469
{
@@ -14461,7 +14483,7 @@
14483
"zh-chs": "编辑用户组",
14484
"zh-cht": "編輯用戶群",
14485
"xloc": [
14464
- "default.handlebars->31->1964"
14486
+ "default.handlebars->31->1977"
14487
]
14488
},
14489
{
@@ -14481,7 +14503,7 @@
14503
"zh-chs": "编辑用户组设备权限",
14504
"zh-cht": "編輯用戶群裝置權限",
14505
"xloc": [
14484
- "default.handlebars->31->1549"
14506
+ "default.handlebars->31->1562"
14507
]
14508
},
14509
{
@@ -14501,7 +14523,7 @@
14523
"zh-chs": "编辑用户组用户同意",
14524
"zh-cht": "編輯用戶組用戶同意",
14525
"xloc": [
14504
- "default.handlebars->31->1490"
14526
+ "default.handlebars->31->1503"
14527
]
14528
},
14529
{
@@ -14583,11 +14605,11 @@
14605
"zh-cht": "電郵",
14606
"xloc": [
14607
"default-mobile.handlebars->11->89",
14586
- "default.handlebars->31->1863",
14587
- "default.handlebars->31->1990",
14588
- "default.handlebars->31->1992",
14589
- "default.handlebars->31->2032",
14590
- "default.handlebars->31->2050",
14608
+ "default.handlebars->31->1876",
14609
+ "default.handlebars->31->2003",
14610
+ "default.handlebars->31->2005",
14611
+ "default.handlebars->31->2045",
14612
+ "default.handlebars->31->2063",
14613
"default.handlebars->31->337",
14614
"login-mobile.handlebars->5->42",
14615
"login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
@@ -14620,7 +14642,7 @@
14642
"zh-cht": "電郵地址變更",
14643
"xloc": [
14644
"default-mobile.handlebars->11->90",
14623
- "default.handlebars->31->1337"
14645
+ "default.handlebars->31->1350"
14646
]
14647
},
14648
{
@@ -14641,7 +14663,7 @@
14663
"zh-cht": "電郵認證",
14664
"xloc": [
14665
"default-mobile.handlebars->11->79",
14644
- "default.handlebars->31->1105"
14666
+ "default.handlebars->31->1118"
14667
]
14668
},
14669
{
@@ -14701,7 +14723,7 @@
14723
"zh-cht": "電郵驗證",
14724
"xloc": [
14725
"default-mobile.handlebars->11->88",
14704
- "default.handlebars->31->1335"
14726
+ "default.handlebars->31->1348"
14727
]
14728
},
14729
{
@@ -14741,7 +14763,7 @@
14763
"zh-chs": "电邮未验证",
14764
"zh-cht": "電郵未驗證",
14765
"xloc": [
14744
- "default.handlebars->31->1809"
14766
+ "default.handlebars->31->1822"
14767
]
14768
},
14769
{
@@ -14761,8 +14783,8 @@
14783
"zh-chs": "电子邮件已验证",
14784
"zh-cht": "電子郵件已驗證",
14785
"xloc": [
14764
- "default.handlebars->31->1810",
14765
- "default.handlebars->31->1984"
14786
+ "default.handlebars->31->1823",
14787
+ "default.handlebars->31->1997"
14788
]
14789
},
14790
{
@@ -14782,7 +14804,7 @@
14804
"zh-chs": "电邮已验证。",
14805
"zh-cht": "電郵已驗證。",
14806
"xloc": [
14785
- "default.handlebars->31->1869"
14807
+ "default.handlebars->31->1882"
14808
]
14809
},
14810
{
@@ -14802,7 +14824,7 @@
14824
"zh-chs": "电邮未验证",
14825
"zh-cht": "電郵未驗證",
14826
"xloc": [
14805
- "default.handlebars->31->1985"
14827
+ "default.handlebars->31->1998"
14828
]
14829
},
14830
{
@@ -14822,8 +14844,8 @@
14844
"zh-chs": "电邮已发送。",
14845
"zh-cht": "電郵已發送。",
14846
"xloc": [
14825
- "default-mobile.handlebars->11->542",
14826
- "default.handlebars->31->2154",
14847
+ "default-mobile.handlebars->11->559",
14848
+ "default.handlebars->31->2167",
14849
"login-mobile.handlebars->5->2",
14850
"login.handlebars->5->2",
14851
"login2.handlebars->7->3"
@@ -14868,7 +14890,7 @@
14890
"zh-chs": "已通过电邮验证,并且需要重置密码。",
14891
"zh-cht": "已通過電郵驗證,並且需要重置密碼。",
14892
"xloc": [
14871
- "default.handlebars->31->1870"
14893
+ "default.handlebars->31->1883"
14894
]
14895
},
14896
{
@@ -14888,7 +14910,7 @@
14910
"zh-chs": "电邮/短信流量",
14911
"zh-cht": "電郵/短信流量",
14912
"xloc": [
14891
- "default.handlebars->31->2230"
14913
+ "default.handlebars->31->2243"
14914
]
14915
},
14916
{
@@ -14934,7 +14956,7 @@
14956
"zh-chs": "启用邀请代码",
14957
"zh-cht": "啟用邀請代碼",
14958
"xloc": [
14937
- "default.handlebars->31->1584"
14959
+ "default.handlebars->31->1597"
14960
]
14961
},
14962
{
@@ -14975,7 +14997,7 @@
14997
"zh-cht": "啟用電郵二因子鑑別。",
14998
"xloc": [
14999
"default-mobile.handlebars->11->81",
14978
- "default.handlebars->31->1107"
15000
+ "default.handlebars->31->1120"
15001
]
15002
},
15003
{
@@ -15015,7 +15037,7 @@
15037
"zh-chs": "已启用",
15038
"zh-cht": "已啟用",
15039
"xloc": [
15018
- "default.handlebars->31->2127"
15040
+ "default.handlebars->31->2140"
15041
]
15042
},
15043
{
@@ -15035,7 +15057,7 @@
15057
"zh-chs": "启用电子邮件两因素身份验证",
15058
"zh-cht": "啟用電子郵件兩因素身份驗證",
15059
"xloc": [
15038
- "default.handlebars->31->1748"
15060
+ "default.handlebars->31->1761"
15061
]
15062
},
15063
{
@@ -15064,7 +15086,7 @@
15086
"nl": "End",
15087
"xloc": [
15088
"default-mobile.handlebars->11->324",
15067
- "default.handlebars->31->891"
15089
+ "default.handlebars->31->904"
15090
]
15091
},
15092
{
@@ -15084,7 +15106,7 @@
15106
"zh-chs": "时间结束",
15107
"zh-cht": "時間結束",
15108
"xloc": [
15087
- "default.handlebars->31->2124"
15109
+ "default.handlebars->31->2137"
15110
]
15111
},
15112
{
@@ -15104,7 +15126,7 @@
15126
"zh-chs": "从{1}到{2},{3}秒结束了桌面会话“{0}”",
15127
"zh-cht": "從{1}到{2},{3}秒結束了桌面會話“{0}”",
15128
"xloc": [
15107
- "default.handlebars->31->1671"
15129
+ "default.handlebars->31->1684"
15130
]
15131
},
15132
{
@@ -15124,7 +15146,7 @@
15146
"zh-chs": "从{1}到{2},{3}秒结束了文件管理会话“{0}”",
15147
"zh-cht": "從{1}到{2},{3}秒結束了文件管理會話“{0}”",
15148
"xloc": [
15127
- "default.handlebars->31->1672"
15149
+ "default.handlebars->31->1685"
15150
]
15151
},
15152
{
@@ -15144,7 +15166,7 @@
15166
"zh-chs": "从{1}到{2},{3}秒结束了中继会话“{0}”",
15167
"zh-cht": "從{1}到{2},{3}秒結束了中繼會話“{0}”",
15168
"xloc": [
15147
- "default.handlebars->31->1669"
15169
+ "default.handlebars->31->1682"
15170
]
15171
},
15172
{
@@ -15164,7 +15186,7 @@
15186
"zh-chs": "从{1}到{2},{3}秒结束了终端会话“{0}”",
15187
"zh-cht": "從{1}到{2},{3}秒結束了終端會話“{0}”",
15188
"xloc": [
15167
- "default.handlebars->31->1670"
15189
+ "default.handlebars->31->1683"
15190
]
15191
},
15192
{
@@ -15184,7 +15206,7 @@
15206
"zh-chs": "英文",
15207
"zh-cht": "英文",
15208
"xloc": [
15187
- "default.handlebars->31->1169"
15209
+ "default.handlebars->31->1182"
15210
]
15211
},
15212
{
@@ -15204,7 +15226,7 @@
15226
"zh-chs": "英文(澳洲)",
15227
"zh-cht": "英文(澳洲)",
15228
"xloc": [
15207
- "default.handlebars->31->1170"
15229
+ "default.handlebars->31->1183"
15230
]
15231
},
15232
{
@@ -15224,7 +15246,7 @@
15246
"zh-chs": "英文(伯利茲)",
15247
"zh-cht": "英文(伯利茲)",
15248
"xloc": [
15227
- "default.handlebars->31->1171"
15249
+ "default.handlebars->31->1184"
15250
]
15251
},
15252
{
@@ -15244,7 +15266,7 @@
15266
"zh-chs": "英文(加拿大)",
15267
"zh-cht": "英文(加拿大)",
15268
"xloc": [
15247
- "default.handlebars->31->1172"
15269
+ "default.handlebars->31->1185"
15270
]
15271
},
15272
{
@@ -15264,7 +15286,7 @@
15286
"zh-chs": "英文(爱尔兰)",
15287
"zh-cht": "英文(愛爾蘭)",
15288
"xloc": [
15267
- "default.handlebars->31->1173"
15289
+ "default.handlebars->31->1186"
15290
]
15291
},
15292
{
@@ -15284,7 +15306,7 @@
15306
"zh-chs": "英文(牙买加)",
15307
"zh-cht": "英文(牙買加)",
15308
"xloc": [
15287
- "default.handlebars->31->1174"
15309
+ "default.handlebars->31->1187"
15310
]
15311
},
15312
{
@@ -15304,7 +15326,7 @@
15326
"zh-chs": "英文(纽西兰)",
15327
"zh-cht": "英文(紐西蘭)",
15328
"xloc": [
15307
- "default.handlebars->31->1175"
15329
+ "default.handlebars->31->1188"
15330
]
15331
},
15332
{
@@ -15324,7 +15346,7 @@
15346
"zh-chs": "英文(菲律宾)",
15347
"zh-cht": "英文(菲律賓)",
15348
"xloc": [
15327
- "default.handlebars->31->1176"
15349
+ "default.handlebars->31->1189"
15350
]
15351
},
15352
{
@@ -15344,7 +15366,7 @@
15366
"zh-chs": "英语(南非)",
15367
"zh-cht": "英語(南非)",
15368
"xloc": [
15347
- "default.handlebars->31->1177"
15369
+ "default.handlebars->31->1190"
15370
]
15371
},
15372
{
@@ -15364,7 +15386,7 @@
15386
"zh-chs": "英文(特立尼达和多巴哥)",
15387
"zh-cht": "英文(特立尼達和多巴哥)",
15388
"xloc": [
15367
- "default.handlebars->31->1178"
15389
+ "default.handlebars->31->1191"
15390
]
15391
},
15392
{
@@ -15384,7 +15406,7 @@
15406
"zh-chs": "英文(英国)",
15407
"zh-cht": "英文(英國)",
15408
"xloc": [
15387
- "default.handlebars->31->1179"
15409
+ "default.handlebars->31->1192"
15410
]
15411
},
15412
{
@@ -15404,7 +15426,7 @@
15426
"zh-chs": "美国英文",
15427
"zh-cht": "美國英語",
15428
"xloc": [
15407
- "default.handlebars->31->1180"
15429
+ "default.handlebars->31->1193"
15430
]
15431
},
15432
{
@@ -15424,7 +15446,7 @@
15446
"zh-chs": "英文(津巴布韦)",
15447
"zh-cht": "英文(津巴布韋)",
15448
"xloc": [
15427
- "default.handlebars->31->1181"
15449
+ "default.handlebars->31->1194"
15450
]
15451
},
15452
{
@@ -15445,10 +15467,10 @@
15467
"zh-cht": "輸入",
15468
"xloc": [
15469
"default-mobile.handlebars->11->319",
15448
- "default.handlebars->31->1363",
15449
- "default.handlebars->31->1364",
15450
- "default.handlebars->31->886",
15451
- "default.handlebars->31->959"
15470
+ "default.handlebars->31->1376",
15471
+ "default.handlebars->31->1377",
15472
+ "default.handlebars->31->899",
15473
+ "default.handlebars->31->972"
15474
]
15475
},
15476
{
@@ -15468,7 +15490,7 @@
15490
"zh-chs": "输入管理领域名称的逗号分隔列表。",
15491
"zh-cht": "輸入管理領域名稱的逗號分隔列表。",
15492
"xloc": [
15471
- "default.handlebars->31->1874"
15493
+ "default.handlebars->31->1887"
15494
]
15495
},
15496
{
@@ -15528,7 +15550,7 @@
15550
"zh-chs": "输入文本,然后单击确定以远程键入它。在继续操作之前,请确保将远程光标放置在正确的位置。",
15551
"zh-cht": "輸入文本,然後單擊確定以遠程鍵入它。在繼續操作之前,請確保將遠程光標放置在正確的位置。",
15552
"xloc": [
15531
- "default.handlebars->31->910"
15553
+ "default.handlebars->31->923"
15554
]
15555
},
15556
{
@@ -15590,7 +15612,7 @@
15612
"zh-chs": "输入支持SMS的电话号码。验证后,该号码可用于登录验证和其他通知。",
15613
"zh-cht": "輸入支持SMS的電話號碼。驗證後,該號碼可用於登入驗證和其他通知。",
15614
"xloc": [
15593
- "default.handlebars->31->1102"
15615
+ "default.handlebars->31->1115"
15616
]
15617
},
15618
{
@@ -15618,8 +15640,8 @@
15640
"nl": "Fout, uitnodigingscode \\\"{0}\\\" al in gebruik.",
15641
"fr": "Erreur, code d'invitation \\\"{0}\\\" déjà utilisé.",
15642
"xloc": [
15621
- "default-mobile.handlebars->11->550",
15622
- "default.handlebars->31->2162"
15643
+ "default-mobile.handlebars->11->567",
15644
+ "default.handlebars->31->2175"
15645
]
15646
},
15647
{
@@ -15627,8 +15649,8 @@
15649
"nl": "Fout, wachtwoord niet gewijzigd.",
15650
"fr": "Erreur, mot de passe non modifié.",
15651
"xloc": [
15630
- "default-mobile.handlebars->11->547",
15631
- "default.handlebars->31->2159"
15652
+ "default-mobile.handlebars->11->564",
15653
+ "default.handlebars->31->2172"
15654
]
15655
},
15656
{
@@ -15636,8 +15658,8 @@
15658
"nl": "Fout, het is niet mogelijk om naar algemeen gebruikt wachtwoord te veranderen.",
15659
"fr": "Erreur, impossible de changer le mot de passe couramment utilisé.",
15660
"xloc": [
15639
- "default-mobile.handlebars->11->546",
15640
- "default.handlebars->31->2158"
15661
+ "default-mobile.handlebars->11->563",
15662
+ "default.handlebars->31->2171"
15663
]
15664
},
15665
{
@@ -15645,8 +15667,8 @@
15667
"nl": "Fout, kan niet wijzigen naar eerder gebruikt wachtwoord.",
15668
"fr": "Erreur, impossible de changer le mot de passe précédemment utilisé.",
15669
"xloc": [
15648
- "default-mobile.handlebars->11->545",
15649
- "default.handlebars->31->2157"
15670
+ "default-mobile.handlebars->11->562",
15671
+ "default.handlebars->31->2170"
15672
]
15673
},
15674
{
@@ -15675,7 +15697,7 @@
15697
"nl": "Escape",
15698
"xloc": [
15699
"default-mobile.handlebars->11->320",
15678
- "default.handlebars->31->887"
15700
+ "default.handlebars->31->900"
15701
]
15702
},
15703
{
@@ -15695,7 +15717,7 @@
15717
"zh-chs": "世界文",
15718
"zh-cht": "世界語",
15719
"xloc": [
15698
- "default.handlebars->31->1182"
15720
+ "default.handlebars->31->1195"
15721
]
15722
},
15723
{
@@ -15715,7 +15737,7 @@
15737
"zh-chs": "爱沙尼亚文",
15738
"zh-cht": "愛沙尼亞語",
15739
"xloc": [
15718
- "default.handlebars->31->1183"
15740
+ "default.handlebars->31->1196"
15741
]
15742
},
15743
{
@@ -15735,7 +15757,7 @@
15757
"zh-chs": "事件详情",
15758
"zh-cht": "事件詳情",
15759
"xloc": [
15738
- "default.handlebars->31->999"
15760
+ "default.handlebars->31->1012"
15761
]
15762
},
15763
{
@@ -15755,7 +15777,7 @@
15777
"zh-chs": "事件列表输出",
15778
"zh-cht": "事件列表輸出",
15779
"xloc": [
15758
- "default.handlebars->31->1785"
15780
+ "default.handlebars->31->1798"
15781
]
15782
},
15783
{
@@ -15861,7 +15883,7 @@
15883
"zh-cht": "到期時間",
15884
"xloc": [
15885
"default.handlebars->31->203",
15864
- "default.handlebars->31->771"
15886
+ "default.handlebars->31->784"
15887
]
15888
},
15889
{
@@ -15943,7 +15965,7 @@
15965
"zh-chs": "扩充式ASCII",
15966
"zh-cht": "擴充式ASCII",
15967
"xloc": [
15946
- "default.handlebars->31->938",
15968
+ "default.handlebars->31->951",
15969
"terminal.handlebars->3->16"
15970
]
15971
},
@@ -15985,7 +16007,7 @@
16007
"zh-chs": "外部",
16008
"zh-cht": "外部",
16009
"xloc": [
15988
- "default.handlebars->31->2213"
16010
+ "default.handlebars->31->2226"
16011
]
16012
},
16013
{
@@ -16025,7 +16047,7 @@
16047
"zh-chs": "FYRO马其顿语",
16048
"zh-cht": "FYRO馬其頓語",
16049
"xloc": [
16028
- "default.handlebars->31->1233"
16050
+ "default.handlebars->31->1246"
16051
]
16052
},
16053
{
@@ -16045,7 +16067,7 @@
16067
"zh-chs": "法罗语",
16068
"zh-cht": "法羅語",
16069
"xloc": [
16048
- "default.handlebars->31->1184"
16070
+ "default.handlebars->31->1197"
16071
]
16072
},
16073
{
@@ -16073,8 +16095,8 @@
16095
"nl": "E-mailadres kan niet worden gewijzigd, een ander account gebruikt al: {0}.",
16096
"fr": "Échec de la modification de l'adresse e-mail, un autre compte utilise déjà: {0}.",
16097
"xloc": [
16076
- "default-mobile.handlebars->11->541",
16077
- "default.handlebars->31->2153"
16098
+ "default-mobile.handlebars->11->558",
16099
+ "default.handlebars->31->2166"
16100
]
16101
},
16102
{
@@ -16094,7 +16116,7 @@
16116
"zh-chs": "本地用户拒绝后无法启动远程桌面",
16117
"zh-cht": "本地用戶拒絕後無法啟動遠程桌面",
16118
"xloc": [
16097
- "default.handlebars->31->1694"
16119
+ "default.handlebars->31->1707"
16120
]
16121
},
16122
{
@@ -16114,7 +16136,7 @@
16136
"zh-chs": "本地用户拒绝后无法启动远程文件",
16137
"zh-cht": "本地用戶拒絕後無法啟動遠程文件",
16138
"xloc": [
16117
- "default.handlebars->31->1701"
16139
+ "default.handlebars->31->1714"
16140
]
16141
},
16142
{
@@ -16135,7 +16157,7 @@
16157
"zh-cht": "無法啟動遠程終端接合{0}({1})",
16158
"xloc": [
16159
"default-mobile.handlebars->11->311",
16138
- "default.handlebars->31->866",
16160
+ "default.handlebars->31->879",
16161
"desktop.handlebars->3->8",
16162
"terminal.handlebars->3->12"
16163
]
@@ -16157,7 +16179,7 @@
16179
"zh-chs": "波斯文(波斯文)",
16180
"zh-cht": "波斯語(波斯語)",
16181
"xloc": [
16160
- "default.handlebars->31->1185"
16182
+ "default.handlebars->31->1198"
16183
]
16184
},
16185
{
@@ -16199,7 +16221,7 @@
16221
"zh-chs": "功能",
16222
"zh-cht": "功能",
16223
"xloc": [
16202
- "default.handlebars->31->1408"
16224
+ "default.handlebars->31->1421"
16225
]
16226
},
16227
{
@@ -16219,7 +16241,7 @@
16241
"zh-chs": "斐济",
16242
"zh-cht": "斐濟",
16243
"xloc": [
16222
- "default.handlebars->31->1186"
16244
+ "default.handlebars->31->1199"
16245
]
16246
},
16247
{
@@ -16261,7 +16283,7 @@
16283
"xloc": [
16284
"default-mobile.handlebars->11->360",
16285
"default.handlebars->31->533",
16264
- "default.handlebars->31->970"
16286
+ "default.handlebars->31->983"
16287
]
16288
},
16289
{
@@ -16297,8 +16319,8 @@
16319
"zh-chs": "档案操作",
16320
"zh-cht": "檔案操作",
16321
"xloc": [
16300
- "default.handlebars->31->950",
16301
- "default.handlebars->31->952"
16322
+ "default.handlebars->31->963",
16323
+ "default.handlebars->31->965"
16324
]
16325
},
16326
{
@@ -16338,7 +16360,7 @@
16360
"zh-chs": "文件系统驱动",
16361
"zh-cht": "FileSystemDriver",
16362
"xloc": [
16341
- "default.handlebars->31->919"
16363
+ "default.handlebars->31->932"
16364
]
16365
},
16366
{
@@ -16360,8 +16382,8 @@
16382
"xloc": [
16383
"default-mobile.handlebars->11->182",
16384
"default-mobile.handlebars->11->279",
16363
- "default.handlebars->31->1498",
16364
- "default.handlebars->31->2112",
16385
+ "default.handlebars->31->1511",
16386
+ "default.handlebars->31->2125",
16387
"default.handlebars->31->276",
16388
"default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles",
16389
"default.handlebars->contextMenu->cxfiles"
@@ -16404,10 +16426,10 @@
16426
"zh-chs": "档案通知",
16427
"zh-cht": "檔案通知",
16428
"xloc": [
16407
- "default.handlebars->31->1416",
16408
- "default.handlebars->31->1930",
16409
- "default.handlebars->31->2017",
16410
- "default.handlebars->31->618"
16429
+ "default.handlebars->31->1429",
16430
+ "default.handlebars->31->1943",
16431
+ "default.handlebars->31->2030",
16432
+ "default.handlebars->31->631"
16433
]
16434
},
16435
{
@@ -16427,10 +16449,10 @@
16449
"zh-chs": "档案提示",
16450
"zh-cht": "檔案提示",
16451
"xloc": [
16430
- "default.handlebars->31->1415",
16431
- "default.handlebars->31->1929",
16432
- "default.handlebars->31->2016",
16433
- "default.handlebars->31->617"
16452
+ "default.handlebars->31->1428",
16453
+ "default.handlebars->31->1942",
16454
+ "default.handlebars->31->2029",
16455
+ "default.handlebars->31->630"
16456
]
16457
},
16458
{
@@ -16451,7 +16473,7 @@
16473
"zh-cht": "過濾",
16474
"xloc": [
16475
"default-mobile.handlebars->container->page_content->column_l->p2->xdevicesBar->1",
16454
- "default.handlebars->31->955",
16476
+ "default.handlebars->31->968",
16477
"default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar",
16478
"default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar",
16479
"default.handlebars->container->column_l->p4->3->1->0->3->3"
@@ -16494,7 +16516,7 @@
16516
"zh-chs": "查找文件",
16517
"zh-cht": "查找文件",
16518
"xloc": [
16497
- "default.handlebars->31->958"
16519
+ "default.handlebars->31->971"
16520
]
16521
},
16522
{
@@ -16514,7 +16536,7 @@
16536
"zh-chs": "录制会话已完成,{0}秒",
16537
"zh-cht": "錄製會話已完成,{0}秒",
16538
"xloc": [
16517
- "default.handlebars->31->1667"
16539
+ "default.handlebars->31->1680"
16540
]
16541
},
16542
{
@@ -16534,7 +16556,16 @@
16556
"zh-chs": "芬兰",
16557
"zh-cht": "芬蘭",
16558
"xloc": [
16537
- "default.handlebars->31->1187"
16559
+ "default.handlebars->31->1200"
16560
+ ]
16561
+ },
16562
+ {
16563
+ "en": "Firewall",
16564
+ "xloc": [
16565
+ "default-mobile.handlebars->11->393",
16566
+ "default-mobile.handlebars->11->395",
16567
+ "default.handlebars->31->615",
16568
+ "default.handlebars->31->617"
16569
]
16570
},
16571
{
@@ -16701,8 +16732,8 @@
16732
"zh-chs": "下次登录时强制重置密码。",
16733
"zh-cht": "下次登入時強制重置密碼。",
16734
"xloc": [
16704
- "default.handlebars->31->1868",
16705
- "default.handlebars->31->2059"
16735
+ "default.handlebars->31->1881",
16736
+ "default.handlebars->31->2072"
16737
]
16738
},
16739
{
@@ -16785,7 +16816,7 @@
16816
"zh-chs": "格式化",
16817
"zh-cht": "格式化",
16818
"xloc": [
16788
- "default.handlebars->31->1776"
16819
+ "default.handlebars->31->1789"
16820
]
16821
},
16822
{
@@ -16826,8 +16857,8 @@
16857
"zh-chs": "自由",
16858
"zh-cht": "自由",
16859
"xloc": [
16829
- "default.handlebars->31->2171",
16830
- "default.handlebars->31->2173"
16860
+ "default.handlebars->31->2184",
16861
+ "default.handlebars->31->2186"
16862
]
16863
},
16864
{
@@ -16868,7 +16899,7 @@
16899
"zh-chs": "法文(比利时)",
16900
"zh-cht": "法語(比利時)",
16901
"xloc": [
16871
- "default.handlebars->31->1189"
16902
+ "default.handlebars->31->1202"
16903
]
16904
},
16905
{
@@ -16888,7 +16919,7 @@
16919
"zh-chs": "法文(加拿大)",
16920
"zh-cht": "法語(加拿大)",
16921
"xloc": [
16891
- "default.handlebars->31->1190"
16922
+ "default.handlebars->31->1203"
16923
]
16924
},
16925
{
@@ -16908,7 +16939,7 @@
16939
"zh-chs": "法文(法国)",
16940
"zh-cht": "法語(法國)",
16941
"xloc": [
16911
- "default.handlebars->31->1191"
16942
+ "default.handlebars->31->1204"
16943
]
16944
},
16945
{
@@ -16928,7 +16959,7 @@
16959
"zh-chs": "法文(卢森堡)",
16960
"zh-cht": "法語(盧森堡)",
16961
"xloc": [
16931
- "default.handlebars->31->1192"
16962
+ "default.handlebars->31->1205"
16963
]
16964
},
16965
{
@@ -16948,7 +16979,7 @@
16979
"zh-chs": "法文(摩纳哥)",
16980
"zh-cht": "法語(摩納哥)",
16981
"xloc": [
16951
- "default.handlebars->31->1193"
16982
+ "default.handlebars->31->1206"
16983
]
16984
},
16985
{
@@ -16968,7 +16999,7 @@
16999
"zh-chs": "法文(标准)",
17000
"zh-cht": "法語(標準)",
17001
"xloc": [
16971
- "default.handlebars->31->1188"
17002
+ "default.handlebars->31->1201"
17003
]
17004
},
17005
{
@@ -16988,7 +17019,7 @@
17019
"zh-chs": "法文(瑞士)",
17020
"zh-cht": "法語(瑞士)",
17021
"xloc": [
16991
- "default.handlebars->31->1194"
17022
+ "default.handlebars->31->1207"
17023
]
17024
},
17025
{
@@ -17008,7 +17039,7 @@
17039
"zh-chs": "弗里斯兰文",
17040
"zh-cht": "弗里斯蘭語",
17041
"xloc": [
17011
- "default.handlebars->31->1195"
17042
+ "default.handlebars->31->1208"
17043
]
17044
},
17045
{
@@ -17028,7 +17059,7 @@
17059
"zh-chs": "弗留利",
17060
"zh-cht": "弗留利",
17061
"xloc": [
17031
- "default.handlebars->31->1196"
17062
+ "default.handlebars->31->1209"
17063
]
17064
},
17065
{
@@ -17049,12 +17080,12 @@
17080
"zh-cht": "完整管理員",
17081
"xloc": [
17082
"default-mobile.handlebars->11->116",
17052
- "default-mobile.handlebars->11->463",
17053
- "default-mobile.handlebars->11->472",
17054
- "default-mobile.handlebars->11->492",
17055
- "default.handlebars->31->1370",
17056
- "default.handlebars->31->1517",
17057
- "default.handlebars->31->1880"
17083
+ "default-mobile.handlebars->11->480",
17084
+ "default-mobile.handlebars->11->489",
17085
+ "default-mobile.handlebars->11->509",
17086
+ "default.handlebars->31->1383",
17087
+ "default.handlebars->31->1530",
17088
+ "default.handlebars->31->1893"
17089
]
17090
},
17091
{
@@ -17074,7 +17105,7 @@
17105
"zh-chs": "完整管理员(保留所有权利)",
17106
"zh-cht": "完整管理員(保留所有權利)",
17107
"xloc": [
17077
- "default.handlebars->31->1553"
17108
+ "default.handlebars->31->1566"
17109
]
17110
},
17111
{
@@ -17111,7 +17142,7 @@
17142
"zh-chs": "完整设备权限",
17143
"zh-cht": "完整裝置權限",
17144
"xloc": [
17114
- "default.handlebars->31->700"
17145
+ "default.handlebars->31->713"
17146
]
17147
},
17148
{
@@ -17131,7 +17162,7 @@
17162
"zh-chs": "全部权限",
17163
"zh-cht": "全部權限",
17164
"xloc": [
17134
- "default.handlebars->31->718"
17165
+ "default.handlebars->31->731"
17166
]
17167
},
17168
{
@@ -17193,7 +17224,7 @@
17224
"zh-chs": "完整管理员",
17225
"zh-cht": "完整管理員",
17226
"xloc": [
17196
- "default.handlebars->31->1978"
17227
+ "default.handlebars->31->1991"
17228
]
17229
},
17230
{
@@ -17213,8 +17244,8 @@
17244
"zh-chs": "全自动的",
17245
"zh-cht": "全自動的",
17246
"xloc": [
17216
- "default.handlebars->31->1433",
17217
- "default.handlebars->31->1456"
17247
+ "default.handlebars->31->1446",
17248
+ "default.handlebars->31->1469"
17249
]
17250
},
17251
{
@@ -17234,8 +17265,8 @@
17265
"zh-chs": "GPU",
17266
"zh-cht": "GPU",
17267
"xloc": [
17237
- "default-mobile.handlebars->11->439",
17238
- "default.handlebars->31->1067"
17268
+ "default-mobile.handlebars->11->456",
17269
+ "default.handlebars->31->1080"
17270
]
17271
},
17272
{
@@ -17255,7 +17286,7 @@
17286
"zh-chs": "盖尔文(爱尔兰)",
17287
"zh-cht": "蓋爾語(愛爾蘭)",
17288
"xloc": [
17258
- "default.handlebars->31->1198"
17289
+ "default.handlebars->31->1211"
17290
]
17291
},
17292
{
@@ -17275,7 +17306,7 @@
17306
"zh-chs": "盖尔文(苏格兰文)",
17307
"zh-cht": "蓋爾語(蘇格蘭語)",
17308
"xloc": [
17278
- "default.handlebars->31->1197"
17309
+ "default.handlebars->31->1210"
17310
]
17311
},
17312
{
@@ -17295,7 +17326,7 @@
17326
"zh-chs": "加拉契文",
17327
"zh-cht": "加拉契語",
17328
"xloc": [
17298
- "default.handlebars->31->1199"
17329
+ "default.handlebars->31->1212"
17330
]
17331
},
17332
{
@@ -17421,7 +17452,7 @@
17452
"zh-chs": "格鲁吉亚文",
17453
"zh-cht": "格魯吉亞文",
17454
"xloc": [
17424
- "default.handlebars->31->1200"
17455
+ "default.handlebars->31->1213"
17456
]
17457
},
17458
{
@@ -17441,7 +17472,7 @@
17472
"zh-chs": "德文(奥地利)",
17473
"zh-cht": "德語(奧地利)",
17474
"xloc": [
17444
- "default.handlebars->31->1202"
17475
+ "default.handlebars->31->1215"
17476
]
17477
},
17478
{
@@ -17461,7 +17492,7 @@
17492
"zh-chs": "德文(德国)",
17493
"zh-cht": "德文(德國)",
17494
"xloc": [
17464
- "default.handlebars->31->1203"
17495
+ "default.handlebars->31->1216"
17496
]
17497
},
17498
{
@@ -17481,7 +17512,7 @@
17512
"zh-chs": "德文(列支敦士登)",
17513
"zh-cht": "德文(列支敦士登)",
17514
"xloc": [
17484
- "default.handlebars->31->1204"
17515
+ "default.handlebars->31->1217"
17516
]
17517
},
17518
{
@@ -17501,7 +17532,7 @@
17532
"zh-chs": "德文(卢森堡)",
17533
"zh-cht": "德語(盧森堡)",
17534
"xloc": [
17504
- "default.handlebars->31->1205"
17535
+ "default.handlebars->31->1218"
17536
]
17537
},
17538
{
@@ -17521,7 +17552,7 @@
17552
"zh-chs": "德文(标准)",
17553
"zh-cht": "德語(標準)",
17554
"xloc": [
17524
- "default.handlebars->31->1201"
17555
+ "default.handlebars->31->1214"
17556
]
17557
},
17558
{
@@ -17541,7 +17572,7 @@
17572
"zh-chs": "德文(瑞士)",
17573
"zh-cht": "德文(瑞士)",
17574
"xloc": [
17544
- "default.handlebars->31->1206"
17575
+ "default.handlebars->31->1219"
17576
]
17577
},
17578
{
@@ -17561,7 +17592,7 @@
17592
"zh-chs": "获取此设备的MQTT登录凭证。",
17593
"zh-cht": "獲取此裝置的MQTT登入憑證。",
17594
"xloc": [
17564
- "default.handlebars->31->669"
17595
+ "default.handlebars->31->682"
17596
]
17597
},
17598
{
@@ -17602,7 +17633,7 @@
17633
"zh-chs": "正在获取剪贴板内容,{0}个字节",
17634
"zh-cht": "正在獲取剪貼板內容,{0}個字節",
17635
"xloc": [
17605
- "default.handlebars->31->1681"
17636
+ "default.handlebars->31->1694"
17637
]
17638
},
17639
{
@@ -17664,7 +17695,7 @@
17695
"zh-chs": "好",
17696
"zh-cht": "好",
17697
"xloc": [
17667
- "default.handlebars->31->1366"
17698
+ "default.handlebars->31->1379"
17699
]
17700
},
17701
{
@@ -17709,8 +17740,8 @@
17740
"zh-chs": "Google云端硬盘备份",
17741
"zh-cht": "Google雲端硬盤備份",
17742
"xloc": [
17712
- "default.handlebars->31->1377",
17713
- "default.handlebars->31->1380",
17743
+ "default.handlebars->31->1390",
17744
+ "default.handlebars->31->1393",
17745
"default.handlebars->31->220"
17746
]
17747
},
@@ -17731,7 +17762,7 @@
17762
"zh-chs": "Google云端硬盘控制台",
17763
"zh-cht": "Google雲端硬盤控制台",
17764
"xloc": [
17734
- "default.handlebars->31->1374"
17765
+ "default.handlebars->31->1387"
17766
]
17767
},
17768
{
@@ -17771,7 +17802,7 @@
17802
"zh-chs": "Google云端硬盘备份当前处于活动状态。",
17803
"zh-cht": "Google雲端硬盤備份當前處於活動狀態。",
17804
"xloc": [
17774
- "default.handlebars->31->1378"
17805
+ "default.handlebars->31->1391"
17806
]
17807
},
17808
{
@@ -17791,7 +17822,7 @@
17822
"zh-chs": "希腊文",
17823
"zh-cht": "希臘文",
17824
"xloc": [
17794
- "default.handlebars->31->1207"
17825
+ "default.handlebars->31->1220"
17826
]
17827
},
17828
{
@@ -17833,8 +17864,8 @@
17864
"zh-chs": "集体指令",
17865
"zh-cht": "集體指令",
17866
"xloc": [
17836
- "default.handlebars->31->1824",
17837
- "default.handlebars->31->1903",
17867
+ "default.handlebars->31->1837",
17868
+ "default.handlebars->31->1916",
17869
"default.handlebars->31->470",
17870
"default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar",
17871
"default.handlebars->container->column_l->p4->3->1->0->3->3",
@@ -17858,7 +17889,7 @@
17889
"zh-chs": "通过...分组",
17890
"zh-cht": "通過...分群",
17891
"xloc": [
17861
- "default.handlebars->31->1772"
17892
+ "default.handlebars->31->1785"
17893
]
17894
},
17895
{
@@ -17878,7 +17909,7 @@
17909
"zh-chs": "组标识符",
17910
"zh-cht": "群標識符",
17911
"xloc": [
17881
- "default.handlebars->31->1920"
17912
+ "default.handlebars->31->1933"
17913
]
17914
},
17915
{
@@ -17898,7 +17929,7 @@
17929
"zh-chs": "群组成员",
17930
"zh-cht": "群組成員",
17931
"xloc": [
17901
- "default.handlebars->31->1941"
17932
+ "default.handlebars->31->1954"
17933
]
17934
},
17935
{
@@ -17918,7 +17949,7 @@
17949
"zh-chs": "用户{0}的群组权限。",
17950
"zh-cht": "用戶{0}的群組權限。",
17951
"xloc": [
17921
- "default.handlebars->31->1516"
17952
+ "default.handlebars->31->1529"
17953
]
17954
},
17955
{
@@ -17938,7 +17969,7 @@
17969
"zh-chs": "{0}的群组权限。",
17970
"zh-cht": "{0}的群組權限。",
17971
"xloc": [
17941
- "default.handlebars->31->1515"
17972
+ "default.handlebars->31->1528"
17973
]
17974
},
17975
{
@@ -18019,7 +18050,7 @@
18050
"zh-cht": "來賓姓名",
18051
"xloc": [
18052
"default.handlebars->31->198",
18022
- "default.handlebars->31->748"
18053
+ "default.handlebars->31->761"
18054
]
18055
},
18056
{
@@ -18039,7 +18070,7 @@
18070
"zh-chs": "古久拉提",
18071
"zh-cht": "古久拉提",
18072
"xloc": [
18042
- "default.handlebars->31->1208"
18073
+ "default.handlebars->31->1221"
18074
]
18075
},
18076
{
@@ -18082,7 +18113,7 @@
18113
"zh-chs": "海地文",
18114
"zh-cht": "海地文",
18115
"xloc": [
18085
- "default.handlebars->31->1209"
18116
+ "default.handlebars->31->1222"
18117
]
18118
},
18119
{
@@ -18122,7 +18153,7 @@
18153
"zh-chs": "强行断开代理",
18154
"zh-cht": "強行斷開代理",
18155
"xloc": [
18125
- "default.handlebars->31->1097"
18156
+ "default.handlebars->31->1110"
18157
]
18158
},
18159
{
@@ -18142,7 +18173,7 @@
18173
"zh-chs": "堆总数",
18174
"zh-cht": "堆總數",
18175
"xloc": [
18145
- "default.handlebars->31->2215"
18176
+ "default.handlebars->31->2228"
18177
]
18178
},
18179
{
@@ -18162,7 +18193,7 @@
18193
"zh-chs": "堆使用",
18194
"zh-cht": "堆使用",
18195
"xloc": [
18165
- "default.handlebars->31->2214"
18196
+ "default.handlebars->31->2227"
18197
]
18198
},
18199
{
@@ -18182,7 +18213,7 @@
18213
"zh-chs": "希伯来文",
18214
"zh-cht": "希伯來文",
18215
"xloc": [
18185
- "default.handlebars->31->1210"
18216
+ "default.handlebars->31->1223"
18217
]
18218
},
18219
{
@@ -18243,7 +18274,7 @@
18274
"zh-chs": "已请求帮助,用户:{0},详细信息:{1}",
18275
"zh-cht": "已請求幫助,用戶:{0},詳細信息:{1}",
18276
"xloc": [
18246
- "default.handlebars->31->1758"
18277
+ "default.handlebars->31->1771"
18278
]
18279
},
18280
{
@@ -18304,7 +18335,7 @@
18335
"zh-chs": "帮助翻译MeshCentral",
18336
"zh-cht": "幫助翻譯MeshCentral",
18337
"xloc": [
18307
- "default.handlebars->31->1325"
18338
+ "default.handlebars->31->1338"
18339
]
18340
},
18341
{
@@ -18408,7 +18439,7 @@
18439
"zh-chs": "印地文",
18440
"zh-cht": "印地文",
18441
"xloc": [
18411
- "default.handlebars->31->1211"
18442
+ "default.handlebars->31->1224"
18443
]
18444
},
18445
{
@@ -18446,7 +18477,7 @@
18477
"zh-cht": "保存1個項目進行複製",
18478
"xloc": [
18479
"default-mobile.handlebars->11->369",
18449
- "default.handlebars->31->980"
18480
+ "default.handlebars->31->993"
18481
]
18482
},
18483
{
@@ -18467,7 +18498,7 @@
18498
"zh-cht": "保存1個項目進行移動",
18499
"xloc": [
18500
"default-mobile.handlebars->11->373",
18470
- "default.handlebars->31->984"
18501
+ "default.handlebars->31->997"
18502
]
18503
},
This file is too large to show in full.
views/default-mobile.handlebars
+33
-4
@@ -1579,6 +1579,8 @@
1579
if (message.event.node.intelamt.flags != null) { node.intelamt.flags = message.event.node.intelamt.flags; }
1580
if (message.event.node.intelamt.warn != null) { node.intelamt.warn = message.event.node.intelamt.warn; } else { delete node.intelamt.warn; }
1581
}
1582
+ if (message.event.node.av != null) { node.av = message.event.node.av; }
1583
+ if (message.event.node.wsc != null) { node.wsc = message.event.node.wsc; }
1584
node.namel = node.name.toLowerCase();
1585
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1586
if (message.event.node.icon) { node.icon = message.event.node.icon; }
@@ -1588,6 +1590,7 @@
1590
refreshDevice(node._id);
1591
//updateMapMarkers();
1592
updateDevices();
1593
+ if (currentNode == node) { updateDeviceDetails(); }
1594
1595
//if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
1596
}
@@ -4293,6 +4296,32 @@
4296
var m = hardware.windows.osinfo;
4297
if (m.OSArchitecture) { x += addDetailItem("Architecture", EscapeHtml(m.OSArchitecture), s); }
4298
}
4299
+
4300
+ // Windows Security Central
4301
+ if (node.wsc) {
4302
+ var y = [];
4303
+ if (node.wsc.antiVirus != null) { if (node.wsc.antiVirus == 'OK') { y.push("AV" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("AV" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
4304
+ if (node.wsc.autoUpdate != null) { if (node.wsc.autoUpdate == 'OK') { y.push("Update" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("Update" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
4305
+ if (node.wsc.firewall != null) { if (node.wsc.firewall == 'OK') { y.push("Firewall" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("Firewall" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
4306
+ x += addDetailItem("Windows Security", y.join(', '));
4307
+ }
4308
+
4309
+ // Antivirus
4310
+ if (node.av && node.av.length > 0) {
4311
+ var y = [];
4312
+ for (var i in node.av) {
4313
+ if (node.av[i].product) {
4314
+ var avx = EscapeHtml(node.av[i].product);
4315
+ if (node.av[i].enabled !== true) { avx += ' - <span style=color:red>' + "Disabled" + '</span>'; }
4316
+ if (node.av[i].updated !== true) { avx += ' - <span style=color:red>' + "Out of date" + '</span>'; }
4317
+ if ((node.av[i].enabled == true) && (node.av[i].updated == true)) { avx += ' - <span style=color:green>' + "OK" + '</span>'; }
4318
+ y.push(avx);
4319
+ }
4320
+ }
4321
+ x += addDetailItem("Antivirus", y.join('<br />'));
4322
+ }
4323
+
4324
+
4325
if (x != '') { sections.push({ name: "Operating System", html: x, img: 'software' }); }
4326
}
4327
@@ -4361,16 +4390,16 @@
4390
var iplayer = m[j];
4391
if (iplayer.family == 'IPv4') {
4392
if (iplayer.gateway && iplayer.netmask) {
4364
- x += addDetailItem("IPv4 Layer", format("IP: {0}, Mask: {1}, Gateway: {2}", EscapeHtml(iplayer.address), EscapeHtml(iplayer.netmask), EscapeHtml(iplayer.gateway)));
4393
+ x += addDetailItem("IPv4 Layer", format("{0}, Mask: {1}, Gateway: {2}", EscapeHtml(iplayer.address), EscapeHtml(iplayer.netmask), EscapeHtml(iplayer.gateway)));
4394
} else {
4366
- x += addDetailItem("IPv4 Layer", format("IP: {0}", EscapeHtml(iplayer.address)));
4395
+ x += addDetailItem("IPv4 Layer", format("{0}", EscapeHtml(iplayer.address)));
4396
}
4397
}
4398
if (iplayer.family == 'IPv6') {
4399
if (iplayer.gateway && iplayer.netmask) {
4371
- x += addDetailItem("IPv6 Layer", format("IP: {0}, Mask: {1}, Gateway: {2}", EscapeHtml(iplayer.address), EscapeHtml(iplayer.netmask), EscapeHtml(iplayer.gateway)));
4400
+ x += addDetailItem("IPv6 Layer", format("{0}, Mask: {1}, Gateway: {2}", EscapeHtml(iplayer.address), EscapeHtml(iplayer.netmask), EscapeHtml(iplayer.gateway)));
4401
} else {
4373
- x += addDetailItem("IPv6 Layer", format("IP: {0}", EscapeHtml(iplayer.address)));
4402
+ x += addDetailItem("IPv6 Layer", format("{0}", EscapeHtml(iplayer.address)));
4403
}
4404
}
4405
}
views/default.handlebars
+13
-1
@@ -2866,6 +2866,7 @@
2866
if (message.event.node.intelamt.warn != null) { node.intelamt.warn = message.event.node.intelamt.warn; } else { delete node.intelamt.warn; }
2867
}
2868
if (message.event.node.av != null) { node.av = message.event.node.av; }
2869
+ if (message.event.node.wsc != null) { node.wsc = message.event.node.wsc; }
2870
node.namel = node.name.toLowerCase();
2871
if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
2872
if (message.event.node.icon) { node.icon = message.event.node.icon; }
@@ -4358,7 +4359,9 @@
4359
if (xxdialogMode) return false;
4360
var mesh = meshes[meshid], x = '', installType = 0, moreoptions = '';
4361
4361
- var opts = '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Windows" + '</option><option value=1>' + "Linux / BSD" + '</option><option value=5>' + "Linux / BSD / macOS Binary Installer" + '</option><option value=2>' + "Apple macOS" + '</option><option value=6>' + "Mobile device" + '</option><option value=3>' + "Windows (UnInstall)" + '</option><option value=4>' + "Linux / BSD (UnInstall)" + '</option></select>';
4362
+ var opts = '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px><option value=0>' + "Windows" + '</option><option value=1>' + "Linux / BSD" + '</option><option value=5>' + "Linux / BSD / macOS Binary Installer" + '</option><option value=2>' + "Apple macOS" + '</option>';
4363
+ if ((features & 2) == 0) { opts += '<option value=6>' + "Mobile device" + '</option>'; } // Don't display mobile setup in LAN mode.
4364
+ opts += '<option value=3>' + "Windows (UnInstall)" + '</option><option value=4>' + "Linux / BSD (UnInstall)" + '</option></select>';
4365
x += addHtmlValue("Operating System", opts);
4366
4367
var servername = serverinfo.name;
@@ -5901,6 +5904,15 @@
5904
// Operating system description
5905
if (node.osdesc) { x += addDeviceAttribute("Operating System", node.osdesc); }
5906
5907
+ // Windows Security Central
5908
+ if (node.wsc) {
5909
+ var y = [];
5910
+ if (node.wsc.antiVirus != null) { if (node.wsc.antiVirus == 'OK') { y.push("AV" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("AV" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
5911
+ if (node.wsc.autoUpdate != null) { if (node.wsc.autoUpdate == 'OK') { y.push("Update" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("Update" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
5912
+ if (node.wsc.firewall != null) { if (node.wsc.firewall == 'OK') { y.push("Firewall" + ' - <span style=color:green>' + "OK" + '</span>'); } else { y.push("Firewall" + ' - <span style=color:red>' + "BAD" + '</span>'); } }
5913
+ x += addDeviceAttribute("Windows Security", y.join(', '));
5914
+ }
5915
+
5916
// Antivirus
5917
if (node.av && node.av.length > 0) {
5918
var y = [];