Added Intel AMT watchdog presence in MeshCmd
Ylian Saint-Hilaire committed
Apr 28, 2018 at 15:36 UTC
024023247d1d30c491fd40facf86395285178626
9 files changed
+168
-25
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/meshcmd.js
+97
-4
@@ -91,7 +91,7 @@ function run(argv) {
91
//console.log('addedModules = ' + JSON.stringify(addedModules));
92
var actionpath = 'meshaction.txt';
93
if (args.actionfile != null) { actionpath = args.actionfile; }
94
- var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG'];
94
+ var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTPRESENCE'];
95
96
// Load the action file
97
var actionfile = null;
@@ -117,6 +117,7 @@ function run(argv) {
117
if ((typeof args.output) == 'string') { settings.output = args.output; }
118
if ((typeof args.debug) == 'string') { settings.debugLevel = parseInt(args.debug); }
119
if ((typeof args.script) == 'string') { settings.script = args.script; }
120
+ if ((typeof args.agent) == 'string') { settings.agent = args.agent; }
121
if (args.noconsole) { settings.noconsole = true; }
122
if (args.nocommander) { settings.noconsole = true; }
123
if (args.lmsdebug) { settings.lmsdebug = true; }
@@ -147,6 +148,7 @@ function run(argv) {
148
console.log(' AmtClearWebApp - Clear everything from Intel AMT web storage.');
149
console.log(' AmtStorageState - Show contents of the Intel AMT web storage.');
150
console.log(' AmtSaveState - Save all Intel AMT WSMAN object to file.');
151
+ console.log(' AmtPresence - Heartbeat a local Intel AMT watchdog agent.');
152
console.log(' AmtScript - Run .mescript on Intel AMT.');
153
console.log('\r\nHelp on a specific action using:\r\n');
154
console.log(' meshcmd help [action]');
@@ -221,6 +223,12 @@ function run(argv) {
223
console.log(' --user [username] The Intel AMT login username, admin is default.');
224
console.log(' --pass [password] The Intel AMT login password.');
225
console.log(' --tls Specifies that TLS must be used.');
226
+ } else if (action == 'amtpresence') {
227
+ console.log('AmtPresence will heartbeat a local Intel AMT watchdog agent. Example usage:\r\n\r\n meshcmd amtpresence --agent B4B6A24C-255E-A75C-F5E8-B00B4D946AA7');
228
+ console.log('\r\nPossible arguments:\r\n');
229
+ console.log(' --user [username] The Intel AMT login username, admin is default.');
230
+ console.log(' --pass [password] The Intel AMT login password.');
231
+ console.log(' --agent [uuid] The unique identifier of the watchdog agent.');
232
} else if (action == 'amtscript') {
233
console.log('AmtScript will run a .mescript file on the local or remote Intel AMT. Script files can be built using the MeshCommander script editor and be used to setup or perform actions on Intel AMT. Example usage:\r\n\r\n meshcmd amtscript --script myscript.mescript --host 1.2.3.4 --user admin --pass mypassword --tls');
234
console.log('\r\nPossible arguments:\r\n');
@@ -373,6 +381,12 @@ function run(argv) {
381
startLms(function (state) {
382
console.log(['MicroLMS did not start. Must run as administrator or LMS already active.', 'MicroLMS started.', 'MicroLMS started, MeshCommander on HTTP/16994.', 'MEI error'][state]); console.log('Press ctrl-c to exit.'); if (state == 0) { exit(0); }
383
});
384
+ } else if (settings.action == 'amtpresence') {
385
+ // Heartbeat a Intel AMT watchdog
386
+ if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
387
+ if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
388
+ if ((settings.agent == null) || (typeof settings.agent != 'string') || (settings.agent == '')) { console.log('No or invalid \"agent\" specified, use --agent [agent].'); exit(1); return; }
389
+ performAmtAgentPresence();
390
} else if (settings.action == 'amtscript') {
391
// Start running a MEScript
392
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
@@ -414,6 +428,84 @@ function run(argv) {
428
}
429
}
430
431
+//
432
+// Intel AMT Agent Presence
433
+//
434
+
435
+function performAmtAgentPresence() { startLms(function () { tempWatchdogTimer = setTimeout(performAmtAgentPresenceRegister, 3000); }); }
436
+
437
+function performAmtAgentPresenceRegister() {
438
+ // Setup the Intel AMT WSMAN stack
439
+ tempWatchdogTimer = null;
440
+ var transport = require('amt-wsman-duk');
441
+ var wsman = require('amt-wsman');
442
+ var amt = require('amt');
443
+ wsstack = new wsman(transport, '127.0.0.1', settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
444
+ amtstack = new amt(wsstack);
445
+
446
+ // Register the watchdog
447
+ watchdog = { DeviceID: Buffer.from(guidToStr(settings.agent.split('-').join('')).split('-').join(''), 'hex').toString('base64'), Retry: 0 };
448
+ amtstack.AMT_AgentPresenceWatchdog_RegisterAgent(performAmtAgentPresenceRegisterRetry, watchdog, watchdog.Seq, { 'DeviceID': watchdog.DeviceID });
449
+}
450
+
451
+// Called after the agent is registered
452
+function performAmtAgentPresenceRegisterRetry(stack, name, response, status, watchdog) {
453
+ if ((status == 200) && (response.Body.SessionSequenceNumber) && (response.Body.TimeoutInterval)) {
454
+ console.log('Asserting presence of the watchdog...');
455
+ watchdog.Seq = response.Body.SessionSequenceNumber;
456
+ watchdog.Interval = response.Body.TimeoutInterval * 800;
457
+ watchdog.Retry = 0;
458
+ tempWatchdogTimer = setTimeout(performAmtAgentPresenceAssert, watchdog.Interval);
459
+ } else {
460
+ debug(1, 'Failed to register, status = ' + status);
461
+ watchdog.Retry++;
462
+ if (watchdog.Retry < 5) {
463
+ tempWatchdogTimer = setTimeout(function () { amtstack.AMT_AgentPresenceWatchdog_RegisterAgent(performAmtAgentPresenceRegisterRetry, watchdog, watchdog.Seq, { 'DeviceID': watchdog.DeviceID }); }, 1000);
464
+ } else {
465
+ console.log('Failed to register this watchdog.');
466
+ process.exit(0);
467
+ }
468
+ }
469
+}
470
+
471
+// Start a new agent assert
472
+function performAmtAgentPresenceAssert() {
473
+ watchdog.Seq++;
474
+ amtstack.AMT_AgentPresenceWatchdog_AssertPresence(watchdog.Seq, performAmtAgentPresenceAssertRetry, watchdog, 0, { 'DeviceID': watchdog.DeviceID });
475
+}
476
+
477
+// Called after the agent is asserted
478
+function performAmtAgentPresenceAssertRetry(stack, name, response, status, watchdog) {
479
+ if (status == 200) {
480
+ debug(1, 'Succesful assert, sequence = ' + watchdog.Seq);
481
+ watchdog.Retry = 0;
482
+ tempWatchdogTimer = setTimeout(performAmtAgentPresenceAssert, watchdog.Interval);
483
+ } else {
484
+ debug(1, 'Failed to assert, status = ' + status);
485
+ watchdog.Retry++;
486
+ if (watchdog.Retry < 5) {
487
+ amtstack.AMT_AgentPresenceWatchdog_AssertPresence(watchdog.Seq, performAmtAgentPresenceAssertRetry, watchdog, 0, { 'DeviceID': watchdog.DeviceID });
488
+ } else {
489
+ console.log('Failed to assert presence on this watchdog.');
490
+ process.exit(0);
491
+ }
492
+ }
493
+}
494
+
495
+function performAmtAgentPresenceEx5(stack, name, response, status, watchdog) {
496
+ console.log('b', status, watchdog);
497
+ if (status == 200) {
498
+ watchdog.Retry = 0;
499
+ } else {
500
+ watchdog.Retry++;
501
+ if (watchdog.Retry < 5) {
502
+ amtstack.AMT_AgentPresenceWatchdog_AssertPresence(watchdog.Seq, performAmtAgentPresenceEx4, watchdog, 0, { 'DeviceID': watchdog.DeviceID });
503
+ } else {
504
+ console.log('Failed to assert presence on this watchdog.');
505
+ process.exit(0);
506
+ }
507
+ }
508
+}
509
510
//
511
// Intel AMT Audit Log
@@ -868,9 +960,10 @@ function setupMeiOsAdmin(func, state) {
960
//var AllWsman = "CIM_SoftwareIdentity,IPS_SecIOService,IPS_ScreenSettingData,IPS_ProvisioningRecordLog,IPS_HostBasedSetupService,IPS_HostIPSettings,IPS_IPv6PortSettings".split(',');
961
//osamtstack.BatchEnum(null, AllWsman, startLmsWsmanResponse, null, true);
962
871
- tempTimer = setInterval(function () { kvmGetData(true); }, 2000);
872
- kvmGetData(false);
873
- kvmSetData(JSON.stringify({ action: 'restart', ver: 1 }));
963
+ //*************************************
964
+ //tempTimer = setInterval(function () { kvmGetData(true); }, 2000);
965
+ //kvmGetData(false);
966
+ //kvmSetData(JSON.stringify({ action: 'restart', ver: 1 }));
967
});
968
}
969
agents/modules_meshcmd/amt.js
+6
-3
@@ -199,9 +199,12 @@ function AmtStackCreateService(wsmanStack) {
199
}
200
201
// Auto generated methods
202
- obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func); }
203
- obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); }
204
- obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); }
202
+ obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func, tag, pri, selectors); }
203
+ obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); }
204
+ obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); }
205
+ //obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func); }
206
+ //obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); }
207
+ //obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); }
208
obj.AMT_AgentPresenceWatchdog_AddAction = function (OldState, NewState, EventOnTransition, ActionSd, ActionEac, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AddAction", { "OldState": OldState, "NewState": NewState, "EventOnTransition": EventOnTransition, "ActionSd": ActionSd, "ActionEac": ActionEac }, callback_func, tag, pri, selectors); }
209
obj.AMT_AgentPresenceWatchdog_DeleteAllActions = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "DeleteAllActions", {}, callback_func, tag, pri, selectors); }
210
obj.AMT_AgentPresenceWatchdogAction_GetActionEac = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdogAction", "GetActionEac", {}, callback_func); }
mpsserver.js
+1
@@ -216,6 +216,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
216
passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
217
password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
218
}
219
+ //console.log('MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
220
Debug(3, 'MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
221
222
// Check the CIRA password
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.1.6-y",
3
+ "version": "0.1.7-a",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
public/scripts/agent-desktop-0.0.2.js
+3
-1
@@ -272,7 +272,9 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
272
}
273
274
obj.SendKeyMsgKC = function (action, kc) {
275
- if (obj.State == 3) obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, (action - 1), kc));
275
+ if (obj.State != 3) return;
276
+ if (typeof action == 'object') { for (var i in action) { obj.SendKeyMsgKC(action[i][0], action[i][1]); } }
277
+ else { obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, (action - 1), kc)); }
278
}
279
280
obj.sendcad = function() { obj.SendCtrlAltDelMsg(); }
public/scripts/amt-desktop-0.0.2.js
+5
-9
@@ -550,17 +550,13 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
550
return obj.haltEvent(e);
551
}
552
553
- obj.sendkey = function (k, d) { obj.send(String.fromCharCode(4, d, 0, 0) + IntToStr(k)); }
553
+ obj.sendkey = function (k, d) {
554
+ if (typeof k == 'object') { for (var i in k) { obj.sendkey(k[i][0], k[i][1]); } }
555
+ else { obj.send(String.fromCharCode(4, d, 0, 0) + IntToStr(k)); }
556
+ }
557
558
obj.SendCtrlAltDelMsg = function () { obj.sendcad(); }
556
- obj.sendcad = function () {
557
- obj.sendkey(0xFFE3, 1); // Control
558
- obj.sendkey(0xFFE9, 1); // Alt
559
- obj.sendkey(0xFFFF, 1); // Delete
560
- obj.sendkey(0xFFFF, 0); // Delete
561
- obj.sendkey(0xFFE9, 0); // Alt
562
- obj.sendkey(0xFFE3, 0); // Control
563
- }
559
+ obj.sendcad = function () { obj.sendkey([[0xFFE3, 1], [0xFFE9, 1], [0xFFFF, 1], [0xFFFF, 0], [0xFFE9, 0], [0xFFE3, 0]]); } // Control down, Alt down, Delete down, Delete up , Alt up , Control up
560
561
var _MouseInputGrab = false;
562
var _KeyInputGrab = false;
views/default.handlebars
+55
-7
@@ -389,9 +389,16 @@
389
<input id=DeskToolsButton type=button value=Tools title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">
390
</div>
391
<div>
392
-
393
- <input id="DeskCAD" type="button" value="Ctrl-Alt-Del" onkeypress="return false" onkeydown="return false" onclick="sendCAD()">
394
- <span title="Toggle mouse and keyboard input"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()">Input</span>
392
+ <select style="margin-left:6px" id="deskkeys">
393
+ <option value=0>Win+Down</option>
394
+ <option value=1>Win+Up</option>
395
+ <option value=2>Win+L</option>
396
+ <option value=3>Win+M</option>
397
+ <option value=4>Shift+Win+M</option>
398
+ </select>
399
+ <input id="DeskWD" type=button value="Send" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
400
+ <input id="DeskCAD" style="margin-left:6px" type="button" value="Ctrl-Alt-Del" onkeypress="return false" onkeydown="return false" onclick="sendCAD()">
401
+ <span style="margin-left:6px" title="Toggle mouse and keyboard input"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()">Input</span>
402
</div>
403
</td>
404
</tr>
@@ -1094,7 +1101,8 @@
1101
if (message.current == message.latest) {
1102
setDialogMode(2, "MeshCentral Version", 1, null, x);
1103
} else {
1097
- setDialogMode(2, "MeshCentral Version", 3, server_showVersionDlgEx, x + '<br />Select OK to start server self-update.');
1104
+ setDialogMode(2, "MeshCentral Version", 3, server_showVersionDlgEx, x + '<br /><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> Check and click OK to start server self-update.');
1105
+ server_showVersionDlgUpdate();
1106
}
1107
}
1108
break;
@@ -3318,6 +3326,10 @@
3326
QE('deskSaveBtn', deskState == 3);
3327
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
3328
QE('DeskCAD', deskState == 3);
3329
+ QE('DeskWD', deskState == 3);
3330
+ QE('deskkeys', deskState == 3);
3331
+ QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5));
3332
+ QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5));
3333
QE('DeskToolsButton', online);
3334
QV('DeskToastButton', (currentNode.agent) && (currentNode.agent.id < 5));
3335
QE('DeskToastButton', online);
@@ -3493,6 +3505,43 @@
3505
}
3506
}
3507
3508
+ // Remote desktop special key combos for Windows
3509
+ function deskSendKeys() {
3510
+ if (xxdialogMode || desktop == null || desktop.State != 3) return;
3511
+ var ks = Q('deskkeys').value;
3512
+ if (ks == 0) { // WIN+Down arrow
3513
+ if (desktop.contype == 2) {
3514
+ desktop.m.sendkey([[0xffe7,1],[0xff54,1],[0xff54,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
3515
+ } else {
3516
+ desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,40],[desktop.m.KeyAction.UP,40],[desktop.m.KeyAction.EXUP,0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
3517
+ }
3518
+ } else if (ks == 1) { // WIN+Up arrow
3519
+ if (desktop.contype == 2) {
3520
+ desktop.m.sendkey([[0xffe7,1],[0xff52,1],[0xff52,0],[0xffe7,0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
3521
+ } else {
3522
+ desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,38],[desktop.m.KeyAction.UP,38],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
3523
+ }
3524
+ } else if (ks == 2) { // WIN+L arrow
3525
+ if (desktop.contype == 2) {
3526
+ desktop.m.sendkey([[0xffe7,1],[0x6c,1],[0x6c,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
3527
+ } else {
3528
+ desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
3529
+ }
3530
+ } else if (ks == 3) { // WIN+M arrow
3531
+ if (desktop.contype == 2) {
3532
+ desktop.m.sendkey([[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
3533
+ } else {
3534
+ desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
3535
+ }
3536
+ } else if (ks == 4) { // Shift+WIN+M arrow
3537
+ if (desktop.contype == 2) {
3538
+ desktop.m.sendkey([[0xffe1,1],[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0],[0xffe1,0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
3539
+ } else {
3540
+ desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN,16],[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,77],[desktop.m.KeyAction.UP,77],[desktop.m.KeyAction.EXUP,0x5B],[desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
3541
+ }
3542
+ }
3543
+ }
3544
+
3545
// Send CTRL-ALT-DEL
3546
function sendCAD() {
3547
if (xxdialogMode || desktop == null || desktop.State != 3) return;
@@ -4538,9 +4587,8 @@
4587
meshserver.send({ action: 'serverversion' });
4588
}
4589
4541
- function server_showVersionDlgEx() {
4542
- meshserver.send({ action: 'serverupdate' });
4543
- }
4590
+ function server_showVersionDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
4591
+ function server_showVersionDlgEx() { meshserver.send({ action: 'serverupdate' }); }
4592
4593
//
4594
// MY MESHS