More mobile site improvements, MeshCmd fix

Ylian Saint-Hilaire committed Jun 6, 2018 at 16:52 UTC b87eeee0f065a5caf6256bd10b645b2fd3d146cc
4 files changed +471 -51
agents/meshcmd.js
+21 -17
@@ -1305,8 +1305,10 @@ function removeItemFromArray(array, element) {
1305 // Run MeshCmd, but before we do, we need to see if what type of service we are going to be
1306 var serviceName = null;
1307 var serviceOpSpecified = 0;
1308 +var serviceInstall = 0;
1309
1310 for (var i in process.argv) {
1311 + if (process.argv[i].toLowerCase() == 'install') { serviceInstall = 1 } else if (process.argv[i].toLowerCase() == 'uninstall') { serviceInstall = -1 }
1312 if ((process.argv[i].toLowerCase() == 'microlms') || (process.argv[i].toLowerCase() == 'amtlms') || (process.argv[i].toLowerCase() == 'lms')) { serviceName = 'MicroLMS'; break; }
1313 if ((process.argv[i].toLowerCase() == 'meshcommander') || (process.argv[i].toLowerCase() == 'commander')) { serviceName = 'MeshCommander'; break; }
1314 }
@@ -1323,22 +1325,24 @@ if (serviceName == null) {
1325 else { serviceName = 'not_a_service'; }
1326 }
1327
1326 -var serviceHost = require('serviceHost');
1327 -var meshcmdService = new serviceHost({ name: serviceName, startType: 'AUTO_START' });
1328 -
1329 -// Called when the background service is started.
1330 -meshcmdService.on('serviceStart', function onStart() {
1331 - console.setDestination(console.Destinations.DISABLED); // Disable console.log().
1332 - if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } //
1333 - else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); }
1334 - else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
1335 -});
1336 -
1337 -// Called when the background service is stopping
1338 -meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
1339 -
1340 -// Called when the executable is not running as a service, run normally.
1341 -meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
1342 -meshcmdService.run();
1328 +if (serviceInstall == 0) {
1329 + run(process.argv);
1330 +} else {
1331 + var serviceHost = require('serviceHost');
1332 + var meshcmdService = new serviceHost({ name: serviceName, startType: 'AUTO_START' });
1333 +
1334 + // Called when the background service is started.
1335 + meshcmdService.on('serviceStart', function onStart() {
1336 + console.setDestination(console.Destinations.DISABLED); // Disable console.log().
1337 + if (process.execPath.includes('MicroLMS')) { run([process.execPath, 'microlms']); } //
1338 + else if (process.execPath.includes('MeshCommander')) { run([process.execPath, 'meshcommander']); }
1339 + else { console.log('Aborting Service Start, because unknown binary: ' + process.execPath); process.exit(1); }
1340 + });
1341
1342 + // Called when the background service is stopping
1343 + meshcmdService.on('serviceStop', function onStop() { console.log('Stopping service'); process.exit(); }); // The console.log() is for debugging, will be ignored unless "console.setDestination()" is set.
1344
1345 + // Called when the executable is not running as a service, run normally.
1346 + meshcmdService.on('normalStart', function onNormalStart() { try { run(process.argv); } catch (e) { console.log('ERROR: ' + e); } });
1347 + meshcmdService.run();
1348 +}
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.8-a",
3 + "version": "0.1.8-b",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default-mobile.handlebars
+448 -33
@@ -8,23 +8,20 @@
8 <meta name="format-detection" content="telephone=no" />
9 <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
10 <script type="text/javascript" src="scripts/meshcentral.js"></script>
11 + <script type="text/javascript" src="scripts/agent-redir-ws-0.1.0.js"></script>
12 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
13 + <script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
14 + <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0.js"></script>
15 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2.js"></script>
16 + <script type="text/javascript" src="scripts/zlib.js"></script>
17 + <script type="text/javascript" src="scripts/zlib-inflate.js"></script>
18 + <script type="text/javascript" src="scripts/zlib-adler32.js"></script>
19 + <script type="text/javascript" src="scripts/zlib-crc32.js"></script>
20 <title>MeshCentral - Login</title>
21 <style>
13 - a {
14 - color: #036;
15 - text-decoration: underline;
16 - }
17 -
18 - #footer a {
19 - color: #fff;
20 - text-decoration: underline;
21 - }
22 -
23 - #footer a:hover {
24 - color: #fff;
25 - text-decoration: none;
26 - }
27 -
22 + a { color: #036; text-decoration: underline }
23 + #footer a { color: #fff; text-decoration: underline }
24 + #footer a:hover { color: #fff; text-decoration: none }
25 .i1 {background:url(../images/icons50.png) 0px 0px;height:50px;width:50px;border:none;}
26 .i2 {background:url(../images/icons50.png) -50px 0px;height:50px;width:50px;border:none;}
27 .i3 {background:url(../images/icons50.png) -100px 0px;height:50px;width:50px;border:none;}
@@ -148,11 +145,64 @@
145 </td>
146 </tr>
147 </table>
151 - <div style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
148 + <div id=p10general style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
149 <div id=p10html style="margin-left:8px;margin-right:8px"></div>
150 <div id=p10html2></div>
151 <div id=p10html3></div>
152 </div>
153 + <div id=p10desktop style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%;display:none">
154 + <div id=deskarea1>
155 + <div style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
156 + <div style="float:right;text-align:right">
157 + <span id="p14power"></span>&nbsp;
158 + </div>
159 + <div style="margin-left:3px">
160 + <input type=button id=connectbutton1 value="Connect" onclick=connectDesktop(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled">
161 + <input type=button id=connectbutton1h value="HW Connect" onclick=connectDesktop(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled">
162 + <input type=button id=disconnectbutton1 value="Disconnect" onclick=connectDesktop(event,0) onkeypress="return false" onkeydown="return false">
163 + <span id="deskstatus">Disconnected</span>
164 + </div>
165 + </div>
166 + </div>
167 + <div id=deskarea2>
168 + <div>
169 + <div style=background-color:gray><div id=progressbar style=height:2px;width:0%;background-color:red></div></div>
170 + </div>
171 + </div>
172 + <div id=deskarea3 style="height:calc(100% - 56px)">
173 + <div id=deskarea3x style="background:black;text-align:center;height:100%;position:relative">
174 + <div id=DeskParent style="height:100%">
175 + <canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas>
176 + </div>
177 + <div id=DeskTools style="position:absolute;width:400px;height:100%;background-color:gray;top:0;right:0;border-left:2px solid lightgray;display:none">
178 + <a id=DeskToolsRefreshButton style="float:right;padding:3px;cursor:pointer" onclick="refreshDeskTools()">Refresh</a>
179 + <div id=DeskToolsBar style="position:absolute;padding:3px;border-radius: 3px 3px 0px 0px;top:5px;left:4px;bottom:26px;background-color:lightgray;cursor:pointer">Processes</div>
180 + <div style="position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:lightgray;text-align:left">
181 + <div style="border-bottom:1px solid darkgray;padding:3px"><a style=width:50px;padding-right:5px;float:left;cursor:pointer title="Sort by process id" onclick=sortProcess(0)>PID</a><a style=cursor:pointer title="Sort by name" onclick=sortProcess(1)>Name</a></div>
182 + <div id="DeskToolsProcesses" style="overflow-y:scroll;position:absolute;top:24px;bottom:0px;width:100%"></div>
183 + </div>
184 + </div>
185 + </div>
186 + </div>
187 + <div id=deskarea4>
188 + <div style=padding-top:2px;padding-bottom:2px;background:#C0C0C0>
189 + <div style=float:right;text-align:right>
190 + <select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp;
191 + <input id=DeskToastButton type=button value=Toast title="Display a notification message on the remote computer" onkeypress="return false" onkeydown="return false" onclick="deviceToastFunction()">&nbsp;
192 + <!--<input id=DeskToolsButton type=button value=Tools title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;-->
193 + </div>
194 + <div>
195 + <input id="deskActionsBtn" type=button style="margin-left:3px" title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() />
196 + <input type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()">
197 + <input type="button" title="Change the power state of the remote machine" onkeypress="return false" onkeydown="return false" value="Power Actions..." onclick="showPowerActionDlg()" style="display:none">
198 + <input id="DeskCAD" type="button" value="Ctrl-Alt-Del" onkeypress="return false" onkeydown="return false" onclick="sendCAD()">
199 + </div>
200 + </div>
201 + </div>
202 + </div>
203 + <div id=p10files style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%;display:none">
204 +
205 + </div>
206 </div>
207 <div id=p20 style=display:none;position:absolute;bottom:0;top:0;width:100%>
208 <table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;">
@@ -178,12 +228,7 @@
228 </div>
229 </div>
230 <div id=footer style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
181 - <table cellpadding=0 cellspacing=6 style=width:100%>
182 - <tr>
183 - <td style=text-align:left;color:white>{{{footer}}}</td>
184 - <td style=text-align:right>{{{rootCertLink}}}&nbsp;<a href=terms>Terms &amp; Privacy</a></td>
185 - </tr>
186 - </table>
231 + <table id=footerMenu cellpadding=0 cellspacing=0 style="height:32px;width:100%;color:white;cursor:pointer;table-layout:fixed"></table>
232 </div>
233 </div>
234 <div id=dialog style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:90px;width:300px;display:none">
@@ -221,6 +266,11 @@
266 var serverinfo = null;
267 var users = null;
268 var nodeShortIdent = 0;
269 + var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}";
270 + var debugmode = false;
271 + var features = {{{features}}};
272 + var attemptWebRTC = ((features & 128) != 0);
273 + var StatusStrs = ['Disconnected', 'Connecting...', 'Setup...', 'Connected', 'Intel&reg; AMT Connected'];
274
275 function startup() {
276 if ((features & 32) == 0) {
@@ -240,6 +290,11 @@
290 meshserver.onStateChanged = onStateChanged;
291 meshserver.onMessage = onMessage;
292 meshserver.Start();
293 +
294 + // Load desktop settings
295 + var t = localStorage.getItem('desktopsettings');
296 + if (t != null) { desktopsettings = JSON.parse(t); }
297 + applyDesktopSettings();
298 }
299
300 function onStateChanged(server, state) {
@@ -555,12 +610,18 @@
610 function goStack() {
611 if (backStack.length == 0) { go(2); return; }
612 var id = backStack[backStack.length - 1], idtype = id.split('/')[0];
558 - if (idtype == 'node') { gotoDevice(id); }
613 + if (idtype == 'node') { setupDeviceMenu(0); gotoDevice(id); }
614 if (idtype == 'mesh') { gotoMesh(id); }
615 if (idtype == 'account') { go(3); }
616 if (idtype == 'devices') { go(2); }
617 }
618
619 + function updateFooterMenu(options) {
620 + var x = '', count = 0;
621 + if (options != null) { for (var i in options) { x += '<td style="cursor:pointer' + (count == 0?'':';border-left:solid 1px white') + '" onclick="' + options[i].f + '">' + options[i].n; count++; } }
622 + QH('footerMenu', '<tr>' + x);
623 + }
624 +
625 //
626 // MY ACCOUNT
627 //
@@ -688,6 +749,7 @@
749
750 function gotoMesh(meshid) {
751 currentMesh = meshes[meshid];
752 + if (currentMesh == null) { goBack(); }
753 p20updateMesh();
754 go(20);
755 }
@@ -904,6 +966,7 @@
966 return mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
967 }
968
969 + var currentDevicePanel = 0;
970 var currentNode;
971 var powerTimelineNode = null;
972 var powerTimelineReq = null;
@@ -911,7 +974,10 @@
974 var powerTimeline = null;
975 function getCurrentNode() { return currentNode; };
976 function gotoDevice(nodeid, panel, refresh) {
914 - var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
977 + var node = getNodeFromId(nodeid);
978 + if (node == null) { goBack(); }
979 + var mesh = meshes[node.meshid];
980 + if (mesh == null) { goBack(); }
981 var meshrights = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
982 if (!currentNode || currentNode._id != node._id || refresh == true) {
983 currentNode = node;
@@ -921,14 +987,6 @@
987 if (nname.length == 0) { nname = '<i>None</i>'; }
988 if ((meshrights & 4) != 0) { nname = '<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + '</span>'; }
989 QH('p10deviceName', nname);
924 - /*
925 - QH('p11deviceName', nname);
926 - QH('p12deviceName', nname);
927 - QH('p13deviceName', nname);
928 - QH('p14deviceName', nname);
929 - QH('p15deviceName', nname);
930 - QH('p16deviceName', nname);
931 - */
990
991 // Node attributes
992 var x = '<table style=width:100%>';
@@ -979,7 +1037,7 @@
1037 else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>Unknown Version & State</i>'; }
1038 else {
1039 str += provisioningStates[node.intelamt.state];
982 - if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title="Intel AMT is activated in Client Control Mode">CCM</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title="Intel AMT is activated in Admin Control Mode">ACM</span>'; } }
1040 + if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span title="Intel AMT is activated in Client Control Mode">CCM</span>'; } else if (node.intelamt.flags & 4) { str = ' <span title="Intel AMT is activated in Admin Control Mode">ACM</span>'; } }
1041 str += (', v' + node.intelamt.ver);
1042 }
1043
@@ -1060,8 +1118,33 @@
1118 // Request the power timeline
1119 if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { QH('p10html2', ''); powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
1120 }
1121 + setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
1122 if (!panel) panel = 10;
1123 go(panel);
1124 +
1125 + // Update the footer menu
1126 + setupDeviceMenu();
1127 + }
1128 +
1129 + function deviceToastFunction() {
1130 + if (xxdialogMode) return;
1131 + setDialogMode(2, "Device Toast", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
1132 + }
1133 +
1134 + function deviceToastFunctionEx() {
1135 + meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
1136 + }
1137 +
1138 + function setupDeviceMenu(op) {
1139 + if (op != null) { currentDevicePanel = op; }
1140 + QV('p10general', currentDevicePanel == 0);
1141 + QV('p10desktop', currentDevicePanel == 1);
1142 + QV('p10files', currentDevicePanel == 2);
1143 + var menus = [];
1144 + if (currentDevicePanel != 0) { menus.push( { n:'General', f:'setupDeviceMenu(0)' } ); }
1145 + if (currentDevicePanel != 1) { menus.push( { n:'Desktop', f:'setupDeviceMenu(1)' } ); }
1146 + if (currentDevicePanel != 2) { menus.push( { n:'Files', f:'setupDeviceMenu(2)' } ); }
1147 + updateFooterMenu(menus);
1148 }
1149
1150 function deviceActionFunction() {
@@ -1255,6 +1338,337 @@
1338 if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
1339 }
1340
1341 + //
1342 + // DESKTOP
1343 + //
1344 +
1345 + var desktop;
1346 + var desktopNode;
1347 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 50 };
1348 + function setupDesktop() {
1349 + // Setup the remote desktop
1350 + if ((desktopNode != currentNode) && (desktop != null)) { desktop.Stop(); delete desktop; desktopNode = null; desktop = null; }
1351 +
1352 + // If the device desktop is already connected in multi-desktop, use that.
1353 + if ((desktopNode != currentNode) || (desktop == null)) {
1354 + // Device is not already connected, just setup a blank canvas
1355 + QH('DeskParent', '<canvas id=Desk width=640 height=200 style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
1356 + desktopNode = currentNode;
1357 + // Setup the mouse wheel
1358 + Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
1359 + Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
1360 + }
1361 + desktopNode = currentNode;
1362 + updateDesktopButtons();
1363 +
1364 + // On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
1365 + if (!Q('Desk')['toBlob']) { QV('deskSaveBtn', false); }
1366 + }
1367 +
1368 + // Show and enable the right buttons
1369 + function updateDesktopButtons() {
1370 + var mesh = meshes[currentNode.meshid];
1371 + var deskState = 0;
1372 + if (desktop != null) { deskState = desktop.State; }
1373 +
1374 + // Show the right buttons
1375 + QV('disconnectbutton1', (deskState != 0));
1376 + QV('connectbutton1', (deskState == 0) && (mesh.mtype == 2));
1377 + QV('connectbutton1h', (deskState == 0) && ((currentNode.intelamt != null) && (mesh.mtype == 1 || currentNode.intelamt.state == 2) && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))));
1378 +
1379 + // Show the right settings
1380 + QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2)));
1381 + QV('d7meshkvm', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1)));
1382 +
1383 + // Enable buttons
1384 + var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
1385 + QE('connectbutton1', online);
1386 + var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
1387 + QE('connectbutton1h', hwonline);
1388 + //QE('deskSaveBtn', deskState == 3);
1389 + QE('DeskCAD', deskState == 3);
1390 + QE('DeskWD', deskState == 3);
1391 + QE('deskkeys', deskState == 3);
1392 + QV('DeskWD', (currentNode.agent) && (currentNode.agent.id < 5));
1393 + QV('deskkeys', (currentNode.agent) && (currentNode.agent.id < 5));
1394 + QE('DeskToolsButton', online);
1395 + QV('DeskToastButton', (currentNode.agent) && (currentNode.agent.id < 5));
1396 + QE('DeskToastButton', online);
1397 + if (online == false) QV('DeskTools', false);
1398 + }
1399 +
1400 + function connectDesktop(e, contype) {
1401 + if (desktop == null) {
1402 + desktopNode = currentNode;
1403 + if (contype == 2) {
1404 + // Setup the Intel AMT remote desktop
1405 + if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; }
1406 + desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'));
1407 + desktop.debugmode = debugmode;
1408 + desktop.onStateChanged = onDesktopStateChange;
1409 + desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
1410 + desktop.m.useZRLE = (desktopsettings.encoding < 3);
1411 + desktop.m.showmouse = desktopsettings.showmouse;
1412 + desktop.m.onScreenSizeChange = deskAdjust;
1413 + desktop.Start(desktopNode._id, 16994, '*', '*', 0);
1414 + desktop.contype = 2;
1415 + } else {
1416 + // Setup the Mesh Agent remote desktop
1417 + desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort);
1418 + desktop.debugmode = debugmode;
1419 + desktop.m.debugmode = debugmode;
1420 + desktop.attemptWebRTC = attemptWebRTC;
1421 + desktop.onStateChanged = onDesktopStateChange;
1422 + desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
1423 + desktop.m.ScalingLevel = desktopsettings.scaling;
1424 + desktop.m.FrameRateTimer = desktopsettings.framerate;
1425 + desktop.m.onDisplayinfo = deskDisplayInfo;
1426 + desktop.m.onScreenSizeChange = deskAdjust;
1427 + desktop.Start(desktopNode._id);
1428 + desktop.contype = 1;
1429 + }
1430 + } else {
1431 + // Disconnect and clean up the remote desktop
1432 + desktop.Stop();
1433 + delete desktop;
1434 + desktopNode = desktop = null;
1435 + }
1436 + }
1437 +
1438 + function onDesktopStateChange(xdesktop, state) {
1439 + var xstate = state;
1440 + if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
1441 + var str = StatusStrs[xstate];
1442 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ', WebRTC'; }
1443 + //if (desktop.m.stopInput == true) { str += ', Loopback'; }
1444 + QH('deskstatus', str);
1445 + switch (state) {
1446 + case 0:
1447 + // Disconnect and clean up the remote desktop
1448 + desktop.Stop();
1449 + delete desktop;
1450 + desktopNode = desktop = null;
1451 + QV('termdisplays', false);
1452 + if (fullscreen == true) { deskToggleFull(); }
1453 + break;
1454 + case 2:
1455 + break;
1456 + }
1457 + updateDesktopButtons();
1458 + deskAdjust();
1459 + setTimeout(deskAdjust, 50);
1460 + }
1461 +
1462 + function showDesktopSettings() {
1463 + if (xxdialogMode) return;
1464 + applyDesktopSettings();
1465 + updateDesktopButtons();
1466 + setDialogMode(7, "Remote Desktop Settings", 3, showDesktopSettingsChanged);
1467 + }
1468 +
1469 + function showDesktopSettingsChanged() {
1470 + desktopsettings.encoding = d7desktopmode.value;
1471 + desktopsettings.showfocus = d7showfocus.checked;
1472 + desktopsettings.showmouse = d7showcursor.checked;
1473 + desktopsettings.quality = d7bitmapquality.value;
1474 + desktopsettings.scaling = d7bitmapscaling.value;
1475 + desktopsettings.framerate = d7framelimiter.value;
1476 + localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
1477 + applyDesktopSettings();
1478 + if (desktop) {
1479 + if (desktop.contype == 1) {
1480 + if (desktop.State != 0) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
1481 + }
1482 + if (desktop.contype == 2) {
1483 + if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
1484 + }
1485 + }
1486 + }
1487 +
1488 + function applyDesktopSettings() {
1489 + /*
1490 + var r = '', ops = (features & 512)?[90,70,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1];
1491 + for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
1492 + QH('d7bitmapquality', r);
1493 + d7desktopmode.value = desktopsettings.encoding;
1494 + d7showfocus.checked = desktopsettings.showfocus;
1495 + d7showcursor.checked = desktopsettings.showmouse;
1496 + d7bitmapquality.value = 40; // Default value
1497 + if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
1498 + d7bitmapscaling.value = desktopsettings.scaling;
1499 + if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; }
1500 + */
1501 + }
1502 +
1503 + var fullscreen = false;
1504 + /*
1505 + function deskToggleFull() {
1506 + fullscreen = !fullscreen;
1507 + QV('mastheadx', !fullscreen);
1508 + QV('masthead', !fullscreen);
1509 + QV('topbar', !fullscreen);
1510 + QV('p11deviceNameHeader', !fullscreen);
1511 + QV('footer', !fullscreen);
1512 + QV('column_l_bottomgap', !fullscreen);
1513 + QV('idx_deskFullBtn2', fullscreen);
1514 + QV('deskFullBtn', !fullscreen);
1515 + if (fullscreen) {
1516 + QS('container').width = '100%';
1517 + QS('container')['border-right'] = '0';
1518 + QS('container')['border-left'] = '0';
1519 + QS('column_l').padding = '0';
1520 + QS('column_l').width = '100%';
1521 + } else {
1522 + QS('container').width = '960px';
1523 + QS('container')['border-right'] = '1px solid #b7b7b7';
1524 + QS('container')['border-left'] = '1px solid #b7b7b7';
1525 + QS('column_l').padding = '0 15px';
1526 + QS('column_l').width = '930px';
1527 + toggleFullScreen();
1528 + }
1529 + deskAdjust();
1530 + }
1531 + */
1532 +
1533 + function deskAdjust() {
1534 + var x = (Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - (Q('deskarea1').clientHeight + Q('deskarea2').clientHeight + Q('Desk').clientHeight + Q('deskarea4').clientHeight + 2)) / 2;
1535 + if (fullscreen) {
1536 + document.documentElement.style.overflow = 'hidden';
1537 + //QS('deskarea3x').height = null;
1538 + if (x < 0) {
1539 + var mh = (Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - (Q('deskarea1').clientHeight + Q('deskarea2').clientHeight + Q('deskarea4').clientHeight));
1540 + var mw = 9999;
1541 + if (desktop) { mw = (desktop.m.width / desktop.m.height) * mh; }
1542 + QS('Desk')['max-height'] = mh + 'px';
1543 + QS('Desk')['max-width'] = mw + 'px';
1544 + x = 0;
1545 + } else {
1546 + QS('Desk')['max-height'] = null;
1547 + QS('Desk')['max-width'] = null;
1548 + }
1549 + QS('Desk')['margin-top'] = x + 'px';
1550 + QS('Desk')['margin-bottom'] = x + 'px';
1551 + } else {
1552 + document.documentElement.style.overflow = 'auto';
1553 + //QS('deskarea3x').height = (desktop)?'40px':'400px';
1554 + QS('Desk')['max-height'] = null;
1555 + QS('Desk')['max-width'] = null;
1556 + QS('Desk')['margin-top'] = '0';
1557 + QS('Desk')['margin-bottom'] = '0';
1558 + }
1559 + }
1560 +
1561 + // Remote desktop special key combos for Windows
1562 + function deskSendKeys() {
1563 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1564 + var ks = Q('deskkeys').value;
1565 + if (ks == 0) { // WIN+Down arrow
1566 + if (desktop.contype == 2) {
1567 + 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
1568 + } else {
1569 + 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
1570 + }
1571 + } else if (ks == 1) { // WIN+Up arrow
1572 + if (desktop.contype == 2) {
1573 + 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
1574 + } else {
1575 + 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
1576 + }
1577 + } else if (ks == 2) { // WIN+L arrow
1578 + if (desktop.contype == 2) {
1579 + desktop.m.sendkey([[0xffe7,1],[0x6c,1],[0x6c,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
1580 + } else {
1581 + 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
1582 + }
1583 + } else if (ks == 3) { // WIN+M arrow
1584 + if (desktop.contype == 2) {
1585 + desktop.m.sendkey([[0xffe7,1],[0x6d,1],[0x6d,0],[0xffe7,0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
1586 + } else {
1587 + 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
1588 + }
1589 + } else if (ks == 4) { // Shift+WIN+M arrow
1590 + if (desktop.contype == 2) {
1591 + 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
1592 + } else {
1593 + 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
1594 + }
1595 + }
1596 + }
1597 +
1598 + // Send CTRL-ALT-DEL
1599 + function sendCAD() {
1600 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1601 + desktop.m.sendcad();
1602 + }
1603 +
1604 + // Show process dialogs
1605 + function toggleDeskTools() {
1606 + if (xxdialogMode) return;
1607 + if (QS('DeskTools').display == 'none') {
1608 + QV('DeskTools', true);
1609 + Q('DeskTools').nodeid = currentNode._id;
1610 + refreshDeskTools();
1611 + } else {
1612 + QV('DeskTools', false);
1613 + }
1614 + }
1615 +
1616 + // Refresh all of the desktop tool panels
1617 + function refreshDeskTools() {
1618 + QV('DeskToolsRefreshButton', false);
1619 + setTimeout(refreshDeskToolsEx, 500);
1620 + meshserver.send({ action: 'msg', type:'ps', nodeid: currentNode._id });
1621 + }
1622 + function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
1623 + var deskTools = { sort: 1, msg: null };
1624 + function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
1625 + function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return 0; }
1626 + function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
1627 + function showDeskToolsProcesses(message) {
1628 + deskTools.msg = message;
1629 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
1630 + if (Q('DeskTools').nodeid != message.nodeid) return;
1631 + var p = [], processes = null;
1632 + try { processes = JSON.parse(message.value); } catch (e) { }
1633 + console.log(processes);
1634 + if (processes != null) {
1635 + for (var pid in processes) { p.push( { p:parseInt(pid), c:processes[pid].cmd, d:processes[pid].cmd.toLowerCase(), u: processes[pid].user } ); }
1636 + if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
1637 + var x = '';
1638 + for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer title="Stop process" onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u?p[i].u:'') + '</div><div>' + p[i].c + '</div></div>'; } }
1639 + QH('DeskToolsProcesses', x);
1640 + }
1641 + }
1642 +
1643 + // Save the desktop image to file
1644 + function deskSaveImage() {
1645 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1646 + var d = new Date(), n = 'Desktop-' + currentNode.name + '-' + d.getFullYear() + "-" + ("0" + (d.getMonth() + 1)).slice(-2) + "-" + ("0" + d.getDate()).slice(-2) + "-" + ("0" + d.getHours()).slice(-2) + "-" + ("0" + d.getMinutes()).slice(-2);
1647 + Q("Desk")['toBlob'](function (blob) { saveAs(blob, n + ".jpg"); });
1648 + }
1649 +
1650 + function deskDisplayInfo(sender, info, selDisplay, selItem) {
1651 + var txt = Q('termdisplays').value;
1652 + if (info.length > 0) { var options = ''; for (var x in info) { options += '<option' + ((txt == info[x])?' selected':'') + '>' + info[x] + '</option>'; } QH('termdisplays', options); }
1653 + QV('termdisplays', info.length > 0);
1654 + }
1655 +
1656 + function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
1657 +
1658 + function deskSetDisplay(e) {
1659 + var display = 0, txt = Q('termdisplays').value;
1660 + if (txt == "All Displays") display = 65535; else display = parseInt(txt.substring(8));
1661 + desktop.m.SetDisplay(display);
1662 + }
1663 +
1664 + function dmousedown(e) { if (!xxdialogMode && desktop != null) desktop.m.mousedown(e) }
1665 + function dmouseup(e) { if (!xxdialogMode && desktop != null) desktop.m.mouseup(e) }
1666 + function dmousemove(e) { if (!xxdialogMode && desktop != null) desktop.m.mousemove(e) }
1667 + function dmousewheel(e) { if (!xxdialogMode && desktop != null && desktop.m.mousewheel) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
1668 + function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
1669 + function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); }
1670 + function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type:'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
1671 +
1672 //
1673 // MY MESHS
1674 //
@@ -1450,6 +1864,7 @@
1864 var xxcurrentView = -1;
1865 function go(x) {
1866 if (xxdialogMode || xxcurrentView == x) return;
1867 + updateFooterMenu();
1868 setDialogMode(0);
1869 // Edit this line when adding a new screen
1870 for (var i = 0; i < 32; i++) { QV('p' + i, i == x); }
views/default.handlebars
+1
@@ -3475,6 +3475,7 @@
3475 }
3476
3477 function showDesktopSettings() {
3478 + if (xxdialogMode) return;
3479 applyDesktopSettings();
3480 updateDesktopButtons();
3481 setDialogMode(7, "Remote Desktop Settings", 3, showDesktopSettingsChanged);