Partial web page multi-language support done.

Ylian Saint-Hilaire committed Oct 17, 2019 at 17:13 UTC 3f02c8251a0808c2aa462bd3be4888a16c5a61e0
6 files changed +640 -646
public/player.htm
+18 -19
@@ -165,28 +165,28 @@
165 try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; }
166 if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
167 var x = '';
168 - x += addInfo('Time', recFileMetadata.time);
169 - if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo('Duration', secs + ' second' + ((secs > 1) ? 's' : '')); }
170 - x += addInfo('Username', recFileMetadata.username);
171 - x += addInfo('UserID', recFileMetadata.userid);
172 - x += addInfo('SessionID', recFileMetadata.sessionid);
173 - if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo('Addresses', recFileMetadata.ipaddr1 + ' to ' + recFileMetadata.ipaddr2); }
174 - if (recFileMetadata.devicename) { x += addInfo('DeviceName', recFileMetadata.devicename); }
175 - x += addInfo('NodeID', recFileMetadata.nodeid);
168 + x += addInfo("Time", recFileMetadata.time);
169 + if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo("Duration", format("{0} second{1}", secs, (secs > 1) ? 's' : '')); }
170 + x += addInfo("Username", recFileMetadata.username);
171 + x += addInfo("UserID", recFileMetadata.userid);
172 + x += addInfo("SessionID", recFileMetadata.sessionid);
173 + if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo("Addresses", format("{0} to {1}", recFileMetadata.ipaddr1, recFileMetadata.ipaddr2)); }
174 + if (recFileMetadata.devicename) { x += addInfo("DeviceName", recFileMetadata.devicename); }
175 + x += addInfo("NodeID", recFileMetadata.nodeid);
176 if (recFileMetadata.protocol) {
177 var p = recFileMetadata.protocol;
178 - if (p == 1) { p = 'MeshCentral Terminal'; }
179 - else if (p == 2) { p = 'MeshCentral Desktop'; }
180 - else if (p == 100) { p = 'Intel® AMT WSMAN'; }
181 - else if (p == 101) { p = 'Intel® AMT Redirection'; }
182 - x += addInfoNoEsc('Protocol', p);
178 + if (p == 1) { p = "MeshCentral Terminal"; }
179 + else if (p == 2) { p = "MeshCentral Desktop"; }
180 + else if (p == 100) { p = "Intel® AMT WSMAN"; }
181 + else if (p == 101) { p = "Intel® AMT Redirection"; }
182 + x += addInfoNoEsc("Protocol", p);
183 }
184 QV('DeskParent', true);
185 QV('TermParent', false);
186 if (recFileMetadata.protocol == 1) {
187 // MeshCentral remote terminal
188 recFileProtocol = 1;
189 - x += '<br /><br /><span style=color:gray>Press [space] to play/pause.</span>';
189 + x += '<br /><br /><span style=color:gray>' + "Press [space] to play/pause." + '</span>';
190 QE('PlayButton', true);
191 QE('PauseButton', false);
192 QE('RestartButton', false);
@@ -195,7 +195,7 @@
195 else if (recFileMetadata.protocol == 2) {
196 // MeshCentral remote desktop
197 recFileProtocol = 2;
198 - x += '<br /><br /><span style=color:gray>Press [space] to play/pause.</span>';
198 + x += '<br /><br /><span style=color:gray>' + "Press [space] to play/pause." + '</span>';
199 QE('PlayButton', true);
200 QE('PauseButton', false);
201 QE('RestartButton', false);
@@ -301,7 +301,7 @@
301 QS('progressbar').width = '0px';
302 QH('timespan', '00:00:00');
303 QV('metadatadiv', true);
304 - QH('metadatadiv', '<span style=\"font-family:Arial,Helvetica Neue,Helvetica,sans-serif;font-size:28px\">MeshCentral Session Player</span><br /><br /><span style=color:gray>Drag & drop a .mcrec file or click "Open File..."</span>');
304 + QH('metadatadiv', '<span style=\"font-family:Arial,Helvetica Neue,Helvetica,sans-serif;font-size:28px\">MeshCentral Session Player</span><br /><br /><span style=color:gray>' + "Drag & drop a .mcrec file or click \"Open File...\"" + '</span>');
305 QV('DeskParent', true);
306 QV('TermParent', false);
307 }
@@ -529,10 +529,9 @@
529
530 function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
531 function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
532 -
533 -
532 function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
535 - function pad2(num) { var s = "00" + num; return s.substr(s.length - 2); }
533 + function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }
534 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
535
536 start();
537 </script>
views/default.handlebars
+539 -544
@@ -983,15 +983,15 @@
983 'use strict';
984
985 // Process server-side web state
986 - var webState = "{{{webstate}}}";
987 - if (webState != "") { webState = JSON.parse(decodeURIComponent(webState)); }
986 + var webState = '{{{webstate}}}';
987 + if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
988 for (var i in webState) { localStorage.setItem(i, webState[i]); }
989 if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
990
991 var args;
992 var autoReconnect = true;
993 - var powerStatetable = ['', 'Powered', 'Sleep', 'Sleep', 'Sleep', 'Hibernating', 'Power off', 'Present'];
994 - var StatusStrs = ['Disconnected', 'Connecting...', 'Setup...', 'Connected', 'Intel&reg; AMT Connected'];
993 + var powerStatetable = ['', "Powered", "Sleep", "Sleep", "Sleep", "Hibernating", "Power off", "Present"];
994 + var StatusStrs = ["Disconnected", "Connecting...", "Setup...", "Connected", "Intel&reg; AMT Connected"];
995 var sort = 0;
996 var searchFocus = 0;
997 var mapSearchFocus = 0;
@@ -1014,23 +1014,23 @@
1014 var multidesktopsettings = { quality: 20, scaling: 128, framerate: 1000 };
1015 var terminal;
1016 var files;
1017 - var debugLevel = parseInt("{{{debuglevel}}}");
1018 - var features = parseInt("{{{features}}}");
1019 - var sessionTime = parseInt("{{{sessiontime}}}");
1020 - var domain = "{{{domain}}}";
1021 - var domainUrl = "{{{domainurl}}}";
1022 - var authCookie = "{{{authCookie}}}";
1023 - var authRelayCookie = "{{{authRelayCookie}}}";
1017 + var debugLevel = parseInt('{{{debuglevel}}}');
1018 + var features = parseInt('{{{features}}}');
1019 + var sessionTime = parseInt('{{{sessiontime}}}');
1020 + var domain = '{{{domain}}}';
1021 + var domainUrl = '{{{domainurl}}}';
1022 + var authCookie = '{{{authCookie}}}';
1023 + var authRelayCookie = '{{{authRelayCookie}}}';
1024 var authCookieRenewTimer = null;
1025 var multiDesktop = {};
1026 var multiDesktopFilter = null;
1027 - var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}";
1027 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
1028 var amtScanResults = null;
1029 var debugmode = 0;
1030 var clickOnce = (((features & 256) != 0) && detectClickOnce());
1031 var attemptWebRTC = ((features & 128) != 0);
1032 - var passRequirements = "{{{passRequirements}}}";
1033 - if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
1032 + var passRequirements = '{{{passRequirements}}}';
1033 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
1034 var deskAspectRatio = 0;
1035 try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
1036 var uiMode = parseInt(getstore('uiMode', 1));
@@ -1126,8 +1126,8 @@
1126 document.onkeypress = ondockeypress;
1127 document.onkeydown = ondockeydown;
1128 document.onkeyup = ondockeyup;
1129 - //window.addEventListener("focus", ondocfocus, false);
1130 - window.addEventListener("blur", ondocblur, false);
1129 + //window.addEventListener('focus', ondocfocus, false);
1130 + window.addEventListener('blur', ondocblur, false);
1131 window.onresize = function () { masterUpdate(512); }
1132 setTimeout(function() { masterUpdate(512); }, 200);
1133
@@ -1139,12 +1139,12 @@
1139 meshserver.Start();
1140
1141 // Setup page controls
1142 - Q('sortselect').selectedIndex = sort = getstore("sort", 0);
1143 - Q('sizeselect').selectedIndex = getstore("_viewsize", 1);
1144 - Q('SearchInput').value = getstore("_search", "");
1145 - showRealNames = (getstore("showRealNames", 0) == 1);
1142 + Q('sortselect').selectedIndex = sort = getstore('sort', 0);
1143 + Q('sizeselect').selectedIndex = getstore('_viewsize', 1);
1144 + Q('SearchInput').value = getstore('_search', '');
1145 + showRealNames = (getstore('showRealNames', 0) == 1);
1146 Q('RealNameCheckBox').checked = showRealNames;
1147 - Q('viewselect').value = getstore("_deviceView", 1);
1147 + Q('viewselect').value = getstore('_deviceView', 1);
1148 Q('DeskControl').checked = (getstore('DeskControl', 1) == 1);
1149 QV('accountChangeEmailAddressSpan', (features & 0x200000) == 0);
1150
@@ -1154,17 +1154,17 @@
1154 Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
1155
1156 // Setup upload drag & drop
1157 - Q('p5filetable').addEventListener("drop", p5fileDragDrop, false);
1158 - Q('p5filetable').addEventListener("dragover", p5fileDragOver, false);
1159 - Q('p5filetable').addEventListener("dragleave", p5fileDragLeave, false);
1160 - //Q('p5fileCatchAllInput').addEventListener("drop", p5fileDragDrop, false);
1161 - //Q('p5fileCatchAllInput').addEventListener("dragover", p5fileDragOver, false);
1162 - //Q('p5fileCatchAllInput').addEventListener("dragleave", p5fileDragLeave, false);
1157 + Q('p5filetable').addEventListener('drop', p5fileDragDrop, false);
1158 + Q('p5filetable').addEventListener('dragover', p5fileDragOver, false);
1159 + Q('p5filetable').addEventListener('dragleave', p5fileDragLeave, false);
1160 + //Q('p5fileCatchAllInput').addEventListener('drop', p5fileDragDrop, false);
1161 + //Q('p5fileCatchAllInput').addEventListener('dragover', p5fileDragOver, false);
1162 + //Q('p5fileCatchAllInput').addEventListener('dragleave', p5fileDragLeave, false);
1163
1164 // Setup upload drag & drop
1165 - Q('p13filetable').addEventListener("drop", p13fileDragDrop, false);
1166 - Q('p13filetable').addEventListener("dragover", p13fileDragOver, false);
1167 - Q('p13filetable').addEventListener("dragleave", p13fileDragLeave, false);
1165 + Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
1166 + Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
1167 + Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
1168
1169 // Timeline update interval
1170 setInterval(updateDeviceTimeline, 120000); // Check every 2 minutes
@@ -1178,7 +1178,7 @@
1178
1179 // Terminal special keys
1180 var x = '';
1181 - for (var c = 1; c < 27; c++) x += "<option value='" + c + "'>Ctrl-" + String.fromCharCode(64 + c) + " (" + c + ")</option>";
1181 + for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "Ctrl" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
1182 QH('specialkeylist', x);
1183
1184 // Setup server stats panels
@@ -1206,9 +1206,9 @@
1206 putstore('webPageStackMenu', webPageStackMenu);
1207 }
1208 if (webPageStackMenu == false) {
1209 - QC('body').remove("menu_stack");
1209 + QC('body').remove('menu_stack');
1210 } else {
1211 - QC('body').add("menu_stack");
1211 + QC('body').add('menu_stack');
1212 if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
1213 }
1214 deskAdjust();
@@ -1248,15 +1248,15 @@
1248 var hide = 0;
1249 if (args.hide) { hide = parseInt(args.hide); }
1250 if (webPageFullScreen == false) {
1251 - QC('body').remove("menu_stack");
1252 - QC('body').remove("fullscreen");
1253 - QC('body').remove("arg_hide");
1251 + QC('body').remove('menu_stack');
1252 + QC('body').remove('fullscreen');
1253 + QC('body').remove('arg_hide');
1254 if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
1255 QV('UserDummyMenuSpan', false);
1256 //QV('page_leftbar', false);
1257 } else {
1258 - QC('body').add("fullscreen");
1259 - if (hide & 16) QC('body').add("arg_hide"); // This is replacement for QV('page_leftbar', !(hide & 16));
1258 + QC('body').add('fullscreen');
1259 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
1260 QV('page_leftbar', !(hide & 16));
1261 QV('MainMenuSpan', !(hide & 16));
1262 if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
@@ -1288,8 +1288,8 @@
1288 hideContextMenu(); // Hide the context menu if present
1289 QV('verifyEmailId2', false);
1290 QV('logoutControl', false);
1291 - if (errorCode == 'noauth') { QH('p0span', 'Unable to perform authentication'); return; }
1292 - if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', 'Unable to connect web socket'); }
1291 + if (errorCode == 'noauth') { QH('p0span', "Unable to perform authentication"); return; }
1292 + if (prevState == 2) { if (autoReconnect) { setTimeout(serverPoll, 5000); } } else { QH('p0span', "Unable to connect web socket"); }
1293 if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
1294 } else if (state == 2) {
1295 // Fetch list of meshes, nodes, files
@@ -1306,7 +1306,7 @@
1306 var xdr = null;
1307 try { xdr = new XDomainRequest(); } catch (e) { }
1308 if (!xdr) xdr = new XMLHttpRequest();
1309 - xdr.open("HEAD", window.location.href);
1309 + xdr.open('HEAD', window.location.href);
1310 xdr.timeout = 15000;
1311 xdr.onload = function () { reload(); };
1312 xdr.onerror = xdr.ontimeout = function () { setTimeout(serverPoll, 10000); };
@@ -1315,13 +1315,13 @@
1315
1316 // Return true if this browser supports clickonce
1317 function detectClickOnce() {
1318 - for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == "application/x-ms-application") { return true; } }
1318 + for (var i in window.navigator.mimeTypes) { if (window.navigator.mimeTypes[i].type == 'application/x-ms-application') { return true; } }
1319 var userAgent = window.navigator.userAgent.toUpperCase();
1320 return (userAgent.indexOf('.NET CLR 3.5') >= 0) || (userAgent.indexOf('(WINDOWS NT ') >= 0);
1321 }
1322
1323 function updateSiteAdmin() {
1324 - var noServerBackup = "{{{noServerBackup}}}";
1324 + var noServerBackup = '{{{noServerBackup}}}';
1325 var siteRights = userinfo.siteadmin;
1326 if (noServerBackup == 1) { siteRights &= 0xFFFFFFFA; } // If not server backups allowed, remove server backup and restore permissions
1327
@@ -1401,7 +1401,7 @@
1401
1402 // Check if backup codes should really be enabled
1403 if ((backupCodesWarningDone == false) && !(userinfo.otpkeys > 0) && (((userinfo.otpsecret == 1) && !(userinfo.otphkeys > 0)) || ((userinfo.otpsecret != 1) && (userinfo.otphkeys == 1)))) {
1404 - var n = { text: 'Please add two-factor backup codes. If the current factor is lost, there is not way to recover this account.', title: 'Two factor authentication' };
1404 + var n = { text: "Please add two-factor backup codes. If the current factor is lost, there is not way to recover this account.", title: "Two factor authentication" };
1405 addNotification(n);
1406 backupCodesWarningDone = true;
1407 }
@@ -1414,13 +1414,13 @@
1414 QV('getStarted2', !newGroupsAllowed);
1415
1416 if (typeof userinfo.passchange == 'number') {
1417 - if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', ' - Reset on next login.'); }
1417 + if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
1418 else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
1419 var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
1420 - if (seconds < 0) { QH('p2nextPasswordUpdateTime', ' - Reset on next login.'); }
1421 - else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 60) + ' minute' + addLetterS(Math.floor(seconds / 60)) + '.'); }
1422 - else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 3600) + ' hour' + addLetterS(Math.floor(seconds / 3600)) + '.'); }
1423 - else { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 86400) + ' day' + addLetterS(Math.floor(seconds / 86400)) + '.'); }
1420 + if (seconds < 0) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
1421 + else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} minute{1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
1422 + else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} hour{1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
1423 + else { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} day{1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
1424 }
1425 }
1426 }
@@ -1432,10 +1432,10 @@
1432 if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
1433 var ds = Math.round((serverinfo.timeout - delta) / 1000);
1434 if (ds <= 60) {
1435 - QH('idleTimeoutNotify', '<br />' + ds + ' second' + addLetterS(ds) + ' until disconnect');
1435 + QH('idleTimeoutNotify', '<br />' + format("{0} second{1} until disconnect", ds, addLetterS(ds)));
1436 } else {
1437 ds = Math.round(ds / 60);
1438 - if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + ds + ' minute' + addLetterS(ds) + ' until disconnect'); }
1438 + if (ds <= 5) { QH('idleTimeoutNotify', '<br />' + format("{0} minute{1} until disconnect", ds, addLetterS(ds))); }
1439 }
1440 }
1441 }
@@ -1476,7 +1476,7 @@
1476 case 'serverinfo': {
1477 serverinfo = message.serverinfo;
1478 if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
1479 - if (debugmode == 1) { console.log("Server time: ", printDateTime(new Date(serverinfo.serverTime))); }
1479 + if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
1480 break;
1481 }
1482 case 'userinfo': {
@@ -1545,32 +1545,32 @@
1545 if (message.nodeid != powerTimelineReq) break;
1546 //console.log('getsysinfo', message); // ***********************
1547 if (message.noinfo === true) {
1548 - QH('p17info', 'No information for this device.');
1548 + QH('p17info', "No information for this device.");
1549 } else {
1550 var x = '', s = {};
1551 if (message.hardware) {
1552 if (message.hardware.identifiers) {
1553 var ident = message.hardware.identifiers;
1554 // BIOS
1555 - x += '<div class=DevSt style=margin-bottom:3px><b>BIOS</b></div>';
1556 - if (ident.bios_vendor) { x += addDetailItem('Vendor', ident.bios_vendor, s); }
1557 - if (ident.bios_version) { x += addDetailItem('Version', ident.bios_version, s); }
1555 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "BIOS" + '</b></div>';
1556 + if (ident.bios_vendor) { x += addDetailItem("Vendor", ident.bios_vendor, s); }
1557 + if (ident.bios_version) { x += addDetailItem("Version", ident.bios_version, s); }
1558 x += '<br />';
1559
1560 // Motherboard
1561 - x += '<div class=DevSt style=margin-bottom:3px><b>Motherboard</b></div>';
1562 - if (ident.board_vendor) { x += addDetailItem('Vendor', ident.board_vendor, s); }
1563 - if (ident.board_name) { x += addDetailItem('Name', ident.board_name, s); }
1564 - if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem('Serial', ident.board_serial, s); }
1565 - if (ident.board_version) { x += addDetailItem('Version', ident.board_version, s); }
1566 - if (ident.product_uuid) { x += addDetailItem('Identifier', ident.product_uuid, s); }
1561 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Motherboard" + '</b></div>';
1562 + if (ident.board_vendor) { x += addDetailItem("Vendor", ident.board_vendor, s); }
1563 + if (ident.board_name) { x += addDetailItem("Name", ident.board_name, s); }
1564 + if (ident.board_serial && (ident.board_serial != '')) { x += addDetailItem("Serial", ident.board_serial, s); }
1565 + if (ident.board_version) { x += addDetailItem("Version", ident.board_version, s); }
1566 + if (ident.product_uuid) { x += addDetailItem("Identifier", ident.product_uuid, s); }
1567 x += '<br />';
1568 }
1569
1570 if (message.hardware.windows) {
1571 if (message.hardware.windows.memory) {
1572 // Memory
1573 - x += '<div class=DevSt style=margin-bottom:3px><b>Memory</b></div>';
1573 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Memory" + '</b></div>';
1574
1575 // Sort Memory
1576 function memorySort(a, b) { if (a.BankLabel > b.BankLabel) return 1; if (a.BankLabel < b.BankLabel) return -1; return 0; }
@@ -1582,8 +1582,8 @@
1582 x += '<tr><td VALIGN=Top style=width:38px><img src="images/ram2.png" />'
1583 x += '<td><div style=background-color:lightgray;border-radius:5px;padding:8px>';
1584 x += '<div><b>' + m.BankLabel + '</b></div>';
1585 - if (m.Capacity) { x += addDetailItem('Capacity / Speed', ( m.Capacity / 1024 / 1024) + ' Mb, ' + m.Speed + ' Mhz', s); }
1586 - if (m.PartNumber) { x += addDetailItem('Part Number', ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
1585 + if (m.Capacity) { x += addDetailItem("Capacity / Speed", format("{0} Mb, {1} Mhz", (m.Capacity / 1024 / 1024), m.Speed), s); }
1586 + if (m.PartNumber) { x += addDetailItem("Part Number", ((m.Manufacturer && m.Manufacturer != 'Undefined')?(m.Manufacturer + ', '):'') + m.PartNumber, s); }
1587 x += '</div>';
1588 }
1589 x += '</table><br />';
@@ -1592,10 +1592,10 @@
1592 if (message.hardware.windows.osinfo) {
1593 // Operating System
1594 var m = message.hardware.windows.osinfo;
1595 - x += '<div class=DevSt style=margin-bottom:3px><b>Operating System</b></div>';
1596 - if (m.Caption) { x += addDetailItem('Name', m.Caption, s); }
1597 - if (m.Version) { x += addDetailItem('Version', m.Version, s); }
1598 - if (m.OSArchitecture) { x += addDetailItem('Architecture', m.OSArchitecture, s); }
1595 + x += '<div class=DevSt style=margin-bottom:3px><b>' + "Operating System" + '</b></div>';
1596 + if (m.Caption) { x += addDetailItem("Name", m.Caption, s); }
1597 + if (m.Version) { x += addDetailItem("Version", m.Version, s); }
1598 + if (m.OSArchitecture) { x += addDetailItem("Architecture", m.OSArchitecture, s); }
1599 x += '<br />';
1600 }
1601
@@ -1615,7 +1615,7 @@
1615 node.lastconnect = message.time;
1616 node.lastaddr = message.addr;
1617 if ((currentNode._id == node._id) && (Q('MainComputerState').innerHTML == '')) {
1618 - QH('MainComputerState', '<span>Last seen:<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
1618 + QH('MainComputerState', '<span>' + "Last seen:" + '<br />' + printDateTime(new Date(node.lastconnect)) + '</span>');
1619 }
1620 }
1621 break;
@@ -1644,7 +1644,7 @@
1644 Q('d2clipText').value = message.data;
1645 } else if ((message.type == 'setclip') && (xxdialogTag == 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
1646 // Display success/fail on the clipboard dialog box.
1647 - QH('dlgClipStatus', message.success ? '<span style=color:green>Success</span>' : '<span style=color:red>Failed</span>')
1647 + QH('dlgClipStatus', message.success ? '<span style=color:green>' + "Success" + '</span>' : '<span style=color:red>' + "Failed" + '</span>')
1648 setTimeout(function () { try { QH('dlgClipStatus', ''); } catch (ex) { } }, 2000);
1649 }
1650 }
@@ -1661,38 +1661,38 @@
1661 case 'getnetworkinfo': {
1662 if ((currentNode._id == message.nodeid) && (xxdialogMode == 2) && (xxdialogTag == 'if' + message.nodeid)) {
1663 if (message.netif == null) {
1664 - QH('d2netinfo', 'No network interface information available for this device.');
1664 + QH('d2netinfo', "No network interface information available for this device.");
1665 } else {
1666 var x = '<div class=dialogText>';
1667
1668 - if (currentNode.lastconnect) { x += addHtmlValue2('Last agent connection', printDateTime(new Date(currentNode.lastconnect))); }
1668 + if (currentNode.lastconnect) { x += addHtmlValue2("Last agent connection", printDateTime(new Date(currentNode.lastconnect))); }
1669 if (currentNode.lastaddr) {
1670 var splitip = currentNode.lastaddr.split(':');
1671 if (splitip.length > 2) {
1672 // IPv6
1673 - x += addHtmlValue2('Last agent address', currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
1673 + x += addHtmlValue2("Last agent address", currentNode.lastaddr + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(currentNode.lastaddr) + '\") width=10 height=10>');
1674 } else {
1675 // IPv4
1676 if (isPrivateIP(currentNode.lastaddr)) {
1677 - x += addHtmlValue2('Last agent address', splitip[0] + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1677 + x += addHtmlValue2("Last agent address", splitip[0] + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1678 } else {
1679 - x += addHtmlValue2('Last agent address', '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1679 + x += addHtmlValue2("Last agent address", '<a href="https://iplocation.com/?ip=' + splitip[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + splitip[0] + '</a> <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(splitip[0]) + '\") width=10 height=10>');
1680 }
1681 }
1682 }
1683
1684 - x += addHtmlValue2('Last interfaces update', printDateTime(new Date(message.updateTime)));
1684 + x += addHtmlValue2("Last interfaces update", printDateTime(new Date(message.updateTime)));
1685 for (var i in message.netif) {
1686 var net = message.netif[i];
1687 x += '<hr />'
1688 - if (net.name) { x += addHtmlValue2('Name', '<b>' + EscapeHtml(net.name) + '</b>'); }
1689 - if (net.desc) { x += addHtmlValue2('Description', EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
1690 - if (net.dnssuffix) { x += addHtmlValue2('DNS suffix', EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="Copy name to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
1691 - if (net.mac) { x += addHtmlValue2('MAC address', '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a> <img src="images/link4.png" title="Copy MAC address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
1692 - if (net.v4addr) { x += addHtmlValue2('IPv4 address', EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
1693 - if (net.v4mask) { x += addHtmlValue2('IPv4 mask', EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
1694 - if (net.v4gateway) { x += addHtmlValue2('IPv4 gateway', EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="Copy address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
1695 - if (net.gatewaymac) { x += addHtmlValue2('Gateway MAC', '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a> <img src="images/link4.png" title="Copy MAC address to clipboard" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
1688 + if (net.name) { x += addHtmlValue2("Name", '<b>' + EscapeHtml(net.name) + '</b>'); }
1689 + if (net.desc) { x += addHtmlValue2("Description", EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
1690 + if (net.dnssuffix) { x += addHtmlValue2("DNS suffix", EscapeHtml(net.dnssuffix) + ' <img src="images/link4.png" title="' + "Copy name to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.dnssuffix) + '\") width=10 height=10>'); }
1691 + if (net.mac) { x += addHtmlValue2("MAC address", '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copy MAC address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.mac.toLowerCase()) + '\") width=10 height=10>'); }
1692 + if (net.v4addr) { x += addHtmlValue2("IPv4 address", EscapeHtml(net.v4addr) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4addr) + '\") width=10 height=10>'); }
1693 + if (net.v4mask) { x += addHtmlValue2("IPv4 mask", EscapeHtml(net.v4mask) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4mask) + '\") width=10 height=10>'); }
1694 + if (net.v4gateway) { x += addHtmlValue2("IPv4 gateway", EscapeHtml(net.v4gateway) + ' <img src="images/link4.png" title="' + "Copy address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.v4gateway) + '\") width=10 height=10>'); }
1695 + if (net.gatewaymac) { x += addHtmlValue2("Gateway MAC", '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a> <img src="images/link4.png" title="' + "Copy MAC address to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2(\"' + encodeURIComponent(net.gatewaymac.toLowerCase()) + '\") width=10 height=10>'); }
1696 }
1697 x += '</div>';
1698 QH('d2netinfo', x);
@@ -1703,15 +1703,15 @@
1703 case 'serverversion': {
1704 if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerUpdate')) {
1705 var x = '<div class=dialogText>';
1706 - if (!message.current) { message.current = 'Unknown'; }
1707 - if (!message.latest) { message.latest = 'Unknown'; }
1708 - x += addHtmlValue2('Current Version', '<b>' + EscapeHtml(message.current) + '</b>');
1709 - x += addHtmlValue2('Latest Version', '<b>' + EscapeHtml(message.latest) + '</b>');
1706 + if (!message.current) { message.current = "Unknown"; }
1707 + if (!message.latest) { message.latest = "Unknown"; }
1708 + x += addHtmlValue2("Current Version", '<b>' + EscapeHtml(message.current) + '</b>');
1709 + x += addHtmlValue2("Latest Version", '<b>' + EscapeHtml(message.latest) + '</b>');
1710 x += '</div>';
1711 if ((message.latest.indexOf('.') == -1) || (message.current == message.latest) || ((features & 2048) == 0)) {
1712 setDialogMode(2, "MeshCentral Version", 1, null, x);
1713 } else {
1714 - setDialogMode(2, "MeshCentral Version", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> Check and click OK to start server self-update.</label>');
1714 + setDialogMode(2, "MeshCentral Version", 3, server_showVersionDlgEx, x + '<br /><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Check and click OK to start server self-update." + '</label>');
1715 server_showVersionDlgUpdate();
1716 }
1717 }
@@ -1720,10 +1720,10 @@
1720 case 'servererrors': {
1721 if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
1722 if (message.data == null) {
1723 - setDialogMode(2, "MeshCentral Server Errors", 1, null, 'Server has no error log.');
1723 + setDialogMode(2, "MeshCentral Server Errors", 1, null, "Server has no error log.");
1724 } else {
1725 var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + message.data + '<pre></div>';
1726 - setDialogMode(2, "MeshCentral Server Errors", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="Download error log" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> Check and click OK to clear error log.</label></div>');
1726 + setDialogMode(2, "MeshCentral Server Errors", 3, server_showErrorsDlgEx, x + '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Download error log" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div><div><label><input id=d2updateCheck type=checkbox onclick=server_showVersionDlgUpdate() /> ' + "Check and click OK to clear error log." + '</label></div>');
1727 server_showVersionDlgUpdate();
1728 }
1729 }
@@ -1748,8 +1748,8 @@
1748 }
1749 case 'getcookie': {
1750 if (message.tag == 'clickonce') {
1751 - var basicPort = "{{{serverRedirPort}}}" == "" ? "{{{serverPublicPort}}}" : "{{{serverRedirPort}}}";
1752 - var rdpurl = "http://" + window.location.hostname + ":" + basicPort + "/clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F" + window.location.hostname + "%2Fmeshrelay.ashx%3Fauth=" + message.cookie + "&CH={{{webcerthash}}}&AP=" + message.protocol + ((debugmode == 1) ? "" : "&HOL=1");
1751 + var basicPort = '{{{serverRedirPort}}}' == '' ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}';
1752 + var rdpurl = 'http://' + window.location.hostname + ':' + basicPort + '/clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1');
1753 var newWindow = window.open(rdpurl, '_blank');
1754 newWindow.opener = null;
1755 }
@@ -1774,8 +1774,8 @@
1774 var secret = message.secret;
1775 if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
1776 else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
1777 - QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application and scan the barcode, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.<br /><br />Secret<br /><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />Enter the token here for 2-step login: <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
1778 - new QRCode(Q("qrcode"), { text: message.url, width: 128, height: 128, colorDark: "#000000", colorLight: "#EEE", correctLevel: QRCode.CorrectLevel.H });
1777 + QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + "Install <a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" rel=\"noreferrer noopener\" target=_blank>Google Authenticator</a> or a compatible application and scan the barcode, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login." + '<br /><br />Secret<br /><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Enter the token here for 2-step login:" + ' <input type=text onkeypress=\"return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
1778 + new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
1779 QV('idx_dlgOkButton', true);
1780 QE('idx_dlgOkButton', false);
1781 Q('d2otpauthinput').focus();
@@ -1795,7 +1795,7 @@
1795 case 'otpauth-getpasswords': {
1796 if (xxdialogMode) return;
1797 var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
1798 - x += "<div style='border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px'><div style='padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold'><table class=selecttext style=width:100%;text-align:center>";
1798 + x += '<div style="border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px"><div style="padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold"><table class=selecttext style=width:100%;text-align:center>';
1799 if (message.passwords) {
1800 var j = 0, clipb = '';
1801 for (var i in message.passwords) {
@@ -1811,38 +1811,38 @@
1811 }
1812 }
1813 } else {
1814 - x += '<tr><td>No Active Tokens';
1814 + x += '<tr><td>' + "No Active Tokens";
1815 }
1816 - x += "</table></div></div><br />";
1817 - x += "<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>";
1818 - x += "<input type=button value='Generate New Tokens' onclick='account_manageOtp(1);'></input>";
1816 + x += '</table></div></div><br />';
1817 + x += '<div><input type=button value=' + "Close" + ' onclick=setDialogMode(0) style=float:right></input>';
1818 + x += '<input type=button value="' + "Generate New Tokens" + '" onclick="account_manageOtp(1);"></input>';
1819 if (message.passwords != null) {
1820 - x += "<input type=button value='Clear Tokens' onclick='account_manageOtp(2);'></input>";
1821 - x += '&nbsp;<img src=images/link4.png height=10 width=10 title="Copy valid codes to clipboard" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
1820 + x += '<input type=button value="' + "Clear Tokens" + '" onclick="account_manageOtp(2);"></input>';
1821 + x += '&nbsp;<img src=images/link4.png height=10 width=10 title="' + "Copy valid codes to clipboard" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponent(clipb) + '")>';
1822 }
1823 - x += "</div><br />";
1823 + x += '</div><br />';
1824 setDialogMode(2, "Manage Backup Codes", 8, null, x, 'otpauth-manage');
1825 break;
1826 }
1827 case 'otp-hkey-get': {
1828 if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
1829 - var start = "<div style='border-radius:6px;border:2px solid #CCC;background-color:#BBB;width:100%;box-sizing:border-box;margin-bottom:6px'><div style='margin:3px;font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold'><table style=width:100%;text-align:left>";
1830 - var end = "</table></div></div>";
1831 - var x = "<a href='https://www.yubico.com/' rel='noreferrer noopener' target='_blank'>Hardware keys</a> are used as secondary login authentication.";
1832 - x += "<div style='max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px'>";
1829 + var start = '<div style="border-radius:6px;border:2px solid #CCC;background-color:#BBB;width:100%;box-sizing:border-box;margin-bottom:6px"><div style="margin:3px;font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold"><table style=width:100%;text-align:left>';
1830 + var end = '</table></div></div>';
1831 + var x = "<a href=\"https://www.yubico.com/\" rel=\"noreferrer noopener\" target=\"_blank\">Hardware keys</a> are used as secondary login authentication.";
1832 + x += '<div style="max-height:150px;overflow-y:auto;overflow-x:hidden;margin-top:6px;margin-bottom:6px">';
1833 if (message.keys && message.keys.length > 0) {
1834 for (var i in message.keys) {
1835 var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
1836 - x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + "<td><input type=button value='Remove' onclick=account_removehkey(" + key.i + ")></input>" + end;
1836 + x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(" + key.i + ")></input>' + end;
1837 }
1838 } else {
1839 - x += start + '<tr style=text-align:center><td>No Keys Configured' + end;
1839 + x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
1840 }
1841 - x += "</div>";
1842 - x += "<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>";
1843 - if ((features & 0x00020000) != 0) { x += "<input id=d2addkey3 type=button value='Add Key' onclick='account_addhkey(3);'></input>"; }
1844 - if ((features & 0x00004000) != 0) { x += "<input id=d2addkey2 type=button value='Add YubiKey&reg; OTP' onclick='account_addhkey(2);'></input>"; }
1845 - x += "</div><br />";
1841 + x += '</div>';
1842 + x += '<div><input type=button value="' + "Close" + '" onclick=setDialogMode(0) style=float:right></input>';
1843 + if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Add Key" + '" onclick="account_addhkey(3);"></input>'; }
1844 + if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Add YubiKey&reg; OTP" + '" onclick="account_addhkey(2);"></input>'; }
1845 + x += '</div><br />';
1846 setDialogMode(2, "Manage Security Keys", 8, null, x, 'otpauth-hardware-manage');
1847 if (u2fSupported() == false) { QE('d2addkey1', false); }
1848 break;
@@ -1851,7 +1851,7 @@
1851 if (message.result) {
1852 meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
1853 } else {
1854 - setDialogMode(2, "Add Security Key", 1, null, '<br />Error, Unable to add key.<br /><br />');
1854 + setDialogMode(2, "Add Security Key", 1, null, '<br />' + "Error, Unable to add key." + '<br /><br />');
1855 }
1856 break;
1857 }
@@ -1860,13 +1860,13 @@
1860 if (message.result == true) {
1861 meshserver.send({ action: 'otp-hkey-get' }); // Success, ask for the full list of keys.
1862 } else {
1863 - setDialogMode(2, "Add Security Key", 1, null, '<br />ERROR: Unable to add key.<br /><br />', 'otpauth-hardware-manage');
1863 + setDialogMode(2, "Add Security Key", 1, null, '<br />' + "ERROR: Unable to add key." + '<br /><br />', 'otpauth-hardware-manage');
1864 }
1865 break;
1866 }
1867 case 'webauthn-startregister': {
1868 if (xxdialogMode && (xxdialogTag != 'otpauth-hardware-manage')) return;
1869 - var x = "Press the key button now.<br /><br /><div style=width:100%;text-align:center><img width=120 height=117 src='images/hardware-keypress-120.png' /></div><input id=dp1keyname style=display:none value=" + message.name + " />";
1869 + var x = "Press the key button now." + '<br /><br /><div style=width:100%;text-align:center><img width=120 height=117 src="images/hardware-keypress-120.png" /></div><input id=dp1keyname style=display:none value=' + message.name + ' />';
1870 setDialogMode(2, "Add Security Key", 2, null, x);
1871
1872 var publicKey = message.request;
@@ -1923,9 +1923,9 @@
1923
1924 // Update the web page
1925 if ((webstate.deskAspectRatio != null) && (webstate.deskAspectRatio != deskAspectRatio)) { deskAspectRatio = webstate.deskAspectRatio; deskAdjust(); }
1926 - if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == "1"); masterUpdate(6); }
1926 + if ((webstate.showRealNames != null) && (webstate.showRealNames != oldShowRealNames)) { showRealNames = Q('RealNameCheckBox').checked = (webstate.showRealNames == '1'); masterUpdate(6); }
1927 if ((webstate.uiMode != null) && (webstate.uiMode != oldUiMode)) { userInterfaceSelectMenu(parseInt(webstate.uiMode)); }
1928 - if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById("sortselect").selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
1928 + if ((webstate.sort != null) && (webstate.sort != oldSort)) { document.getElementById('sortselect').selectedIndex = sort = parseInt(webstate.sort); masterUpdate(6); }
1929 if ((webstate.loctag != null) && (webstate.loctag != oldLoctag)) { if (webstate.loctag != null) { args.locale = webstate.loctag; } else { delete args.locale; } masterUpdate(0xFFFFFFFF); }
1930 }
1931 break;
@@ -2187,16 +2187,16 @@
2187
2188 // Show the notification
2189 if (n & 2) {
2190 - if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: 'Agent connected', title: node.name, icon: node.icon, nodeid: node._id }); }
2191 - if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: 'Intel AMT detected', title: node.name, icon: node.icon, nodeid: node._id }); }
2192 - if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: 'Intel AMT CIRA connected', title: node.name, icon: node.icon, nodeid: node._id }); }
2193 - if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: 'MQTT connected', title: node.name, icon: node.icon, nodeid: node._id }); }
2190 + if (((node.conn & 1) == 0) && ((message.event.conn & 1) != 0)) { addNotification({ text: "Agent connected", title: node.name, icon: node.icon, nodeid: node._id }); }
2191 + if (((node.conn & 2) == 0) && ((message.event.conn & 2) != 0)) { addNotification({ text: "Intel AMT detected", title: node.name, icon: node.icon, nodeid: node._id }); }
2192 + if (((node.conn & 4) == 0) && ((message.event.conn & 4) != 0)) { addNotification({ text: "Intel AMT CIRA connected", title: node.name, icon: node.icon, nodeid: node._id }); }
2193 + if (((node.conn & 16) == 0) && ((message.event.conn & 16) != 0)) { addNotification({ text: "MQTT connected", title: node.name, icon: node.icon, nodeid: node._id }); }
2194 }
2195 if (n & 4) {
2196 - if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: 'Agent disconnected', title: node.name, icon: node.icon, nodeid: node._id }); }
2197 - if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: 'Intel AMT not detected', title: node.name, icon: node.icon, nodeid: node._id }); }
2198 - if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: 'Intel AMT CIRA disconnected', title: node.name, icon: node.icon, nodeid: node._id }); }
2199 - if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: 'MQTT disconnected', title: node.name, icon: node.icon, nodeid: node._id }); }
2196 + if (((node.conn & 1) != 0) && ((message.event.conn & 1) == 0)) { addNotification({ text: "Agent disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
2197 + if (((node.conn & 2) != 0) && ((message.event.conn & 2) == 0)) { addNotification({ text: "Intel AMT not detected", title: node.name, icon: node.icon, nodeid: node._id }); }
2198 + if (((node.conn & 4) != 0) && ((message.event.conn & 4) == 0)) { addNotification({ text: "Intel AMT CIRA disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
2199 + if (((node.conn & 16) != 0) && ((message.event.conn & 16) == 0)) { addNotification({ text: "MQTT disconnected", title: node.name, icon: node.icon, nodeid: node._id }); }
2200 }
2201
2202 // Change the node connection state
@@ -2234,7 +2234,7 @@
2234 var x = '';
2235 if (message.event.results == null) {
2236 // The scan could not occur because of an error. Likely the user range was invalid.
2237 - x = '<div style=width:100%;text-align:center;margin-top:12px>Unable to scan this address range.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100</div>';
2237 + x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Unable to scan this address range." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Sample IP range values<br />192.168.0.100<br />192.168.1.0/24<br />192.167.0.1-192.168.0.100" + '</div>';
2238 } else {
2239 // Go thru all the results and populate the dialog box
2240 amtScanResults = message.event.results;
@@ -2242,7 +2242,7 @@
2242 var r = message.event.results[i], shortname = r.hostname;
2243 if (shortname.length > 20) { shortname = shortname.substring(0, 20) + '...'; }
2244 var str = '<b title="' + EscapeHtml(r.hostname) + '">' + EscapeHtml(shortname) + '</b> - v' + r.ver;
2245 - if (r.state == 2) { if (r.tls == 1) { str += ' with TLS.'; } else { str += ' without TLS.'; } } else { str += ' not activated.'; }
2245 + if (r.state == 2) { if (r.tls == 1) { str += " with TLS."; } else { str += " without TLS."; } } else { str += ' not activated.'; }
2246 x += '<div style=width:100%;margin-bottom:2px;background-color:lightgray><div style=padding:4px><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox name=dp1checkbox tag="' + EscapeHtml(i) + '" type=checkbox onclick=addAmtScanToMeshCheckbox() /></div><div class=j1 style=display:inline-block></div><div style=display:inline-block;margin-left:5px;overflow-x:auto;white-space:nowrap>' + str + '</div></div></div>';
2247 }
2248 // If no results where found, display a nice message
@@ -2297,25 +2297,25 @@
2297 var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
2298 var url;
2299 if (serverinfo.https == true) {
2300 - var portStr = (serverinfo.port == 443) ? '' : (":" + serverinfo.port);
2301 - url = "https://" + servername + portStr + domainUrl + "agentinvite?c=" + message.cookie;
2300 + var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
2301 + url = 'https://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
2302 } else {
2303 - var portStr = (serverinfo.port == 80) ? '' : (":" + serverinfo.port);
2304 - url = "http://" + servername + portStr + domainUrl + "agentinvite?c=" + message.cookie;
2303 + var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
2304 + url = 'http://' + servername + portStr + domainUrl + 'agentinvite?c=' + message.cookie;
2305 }
2306 Q('agentInvitationLink').href = url;
2307 - var t = message.expire + ' hour' + addLetterS(message.expire);
2308 - if (message.expire == 24) { t = '1 day'; }
2309 - if (message.expire == 168) { t = '1 week'; }
2310 - if (message.expire == 5040) { t = '1 month'; }
2311 - if (message.expire == 0) { t = 'Unlimited'; }
2312 - QH('agentInvitationLink', 'Invitation Link (' + t + ')');
2307 + var t = format("{0} hour{1}", message.expire, addLetterS(message.expire));
2308 + if (message.expire == 24) { t = "1 day"; }
2309 + if (message.expire == 168) { t = "1 week"; }
2310 + if (message.expire == 5040) { t = "1 month"; }
2311 + if (message.expire == 0) { t = "Unlimited"; }
2312 + QH('agentInvitationLink', format("Invitation Link ({0})", t));
2313 QV('agentInvitationLinkDiv', true);
2314 break;
2315 }
2316 case 'getmqttlogin': {
2317 if ((currentNode == null) || (currentNode._id != message.nodeid) || (xxdialogMode != null)) return;
2318 - var x = "These settings can be used to connect MQTT for this device.<br /><br />";
2318 + var x = "These settings can be used to connect MQTT for this device." + '<br /><br />';
2319 delete message.action;
2320 delete message.nodeid;
2321 x += '<textarea readonly=readonly style=width:100%;resize:none;height:100px;overflow:auto;font-size:12px readonly>' + JSON.stringify(message) + '</textarea>';
@@ -2354,7 +2354,7 @@
2354
2355 function onRealNameCheckBox() {
2356 showRealNames = Q('RealNameCheckBox').checked;
2357 - putstore("showRealNames", showRealNames ? 1 : 0);
2357 + putstore('showRealNames', showRealNames ? 1 : 0);
2358 masterUpdate(6);
2359 return;
2360 }
@@ -2363,15 +2363,15 @@
2363 if (i != null) { Q('viewselect').value = i; }
2364 for (var j = 1; j < 5; j++) { Q('devViewButton' + j).classList.remove('viewSelectorSel'); }
2365 Q('devViewButton' + Q('viewselect').value).classList.add('viewSelectorSel');
2366 - putstore("_deviceView", Q('viewselect').value);
2367 - putstore("_viewsize", Q('sizeselect').value);
2366 + putstore('_deviceView', Q('viewselect').value);
2367 + putstore('_viewsize', Q('sizeselect').value);
2368 masterUpdate(4);
2369 setTimeout(function () { masterUpdate(512); }, 200);
2370 }
2371
2372 function ondockeypress(e) {
2373 setSessionActivity();
2374 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) {
2374 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2375 // Check what keys we are allows to send
2376 if (currentNode != null) {
2377 var mesh = meshes[currentNode.meshid];
@@ -2401,7 +2401,7 @@
2401 if (e.ctrlKey == true && e.charCode == 96) {
2402 showRealNames = !showRealNames;
2403 Q('RealNameCheckBox').value = showRealNames;
2404 - putstore("showRealNames", showRealNames ? 1 : 0);
2404 + putstore('showRealNames', showRealNames ? 1 : 0);
2405 masterUpdate(6)
2406 return;
2407 }
@@ -2431,7 +2431,7 @@
2431
2432 function ondockeydown(e) {
2433 setSessionActivity();
2434 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) {
2434 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2435 // Check what keys we are allows to send
2436 if (currentNode != null) {
2437 var mesh = meshes[currentNode.meshid];
@@ -2466,7 +2466,7 @@
2466
2467 function ondockeyup(e) {
2468 setSessionActivity();
2469 - if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) {
2469 + if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
2470 // Check what keys we are allows to send
2471 if (currentNode != null) {
2472 var mesh = meshes[currentNode.meshid];
@@ -2489,7 +2489,7 @@
2489
2490 //function ondocfocus() { }
2491 // TODO: Add handleReleaseKeys() for Intel AMT.
2492 - function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
2492 + function ondocblur() { if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked && desktop.m.handleReleaseKeys) { return desktop.m.handleReleaseKeys(); } }
2493
2494 // Highlights the device being hovered
2495 function devMouseHover(element, over) {
@@ -3853,7 +3853,7 @@
3853 }
3854 map_cm_nodemenu_items.forEach(function (item){
3855 if (item.text == 'Zoom-in to extent' || item.text == 'Zoom-out to extent') { item.data = feature; }
3856 - else { if (item != "-") { item.data = feature.getId(); } }
3856 + else { if (item != '-') { item.data = feature.getId(); } }
3857 });
3858 xxmap.contextmenu.extend(map_cm_nodemenu_items);
3859 }
@@ -4436,9 +4436,9 @@
4436
4437 // Update the web page title
4438 if ((currentNode) && (xxcurrentView >= 10) && (xxcurrentView < 20)) {
4439 - document.title = decodeURIComponent("{{{extitle}}}") + ' - ' + currentNode.name + ' - ' + mesh.name;
4439 + document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + mesh.name;
4440 } else {
4441 - document.title = decodeURIComponent("{{{extitle}}}");
4441 + document.title = decodeURIComponent('{{{extitle}}}');
4442 }
4443
4444 // Clear user consent status if present
@@ -4500,13 +4500,13 @@
4500 function deviceActionFunction() {
4501 if (xxdialogMode) return;
4502 var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
4503 - var x = "Select an operation to perform on this device.<br /><br />";
4503 + var x = "Select an operation to perform on this device." + '<br /><br />';
4504 var y = '<select id=d2deviceop style=float:right;width:250px>';
4505 - if ((meshrights & 64) != 0) { y += '<option value=100>Wake-up</option>'; } // Wake-up permission
4506 - if ((meshrights & 8) != 0) { y += '<option value=4>Sleep</option><option value=3>Reset</option><option value=2>Power off</option>'; } // Remote control permission
4507 - if ((currentNode.conn & 16) != 0) { y += '<option value=103>Send MQTT Message</option>'; }
4505 + if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
4506 + if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
4507 + if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
4508 y += '</select>';
4509 - x += addHtmlValue('Operation', y);
4509 + x += addHtmlValue("Operation", y);
4510 setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
4511 }
4512
@@ -4615,9 +4615,9 @@
4615 if (xxdialogMode) return;
4616 var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
4617 if ((meshrights & 4) == 0) return;
4618 - x += addHtmlValue('Username', '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4619 - x += addHtmlValue('Password', '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4620 - x += addHtmlValue('Security', '<select id=dp10tls style=width:236px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>');
4618 + x += addHtmlValue("Username", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4619 + x += addHtmlValue("Password", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4620 + x += addHtmlValue("Security", '<select id=dp10tls style=width:236px><option value=0>' + "No TLS security" + '</option><option value=1>' + "TLS security required" + '</option></select>');
4621 if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
4622 setDialogMode(2, "Edit Intel&reg; AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
4623 if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
@@ -4648,8 +4648,8 @@
4648
4649 function p10showSendMqttMsgDialog(nodeids) {
4650 if (xxdialogMode) return false;
4651 - var x = addHtmlValue('Topic', '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
4652 - x += addHtmlValue('Message', '<div style=width:230px;margin:0;padding:0><textarea id=dp2msg maxlength=4096 style=width:100%;height:150px;resize:none onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1)></textarea></div>');
4651 + var x = addHtmlValue("Topic", '<input id=dp2topic style=width:230px maxlength=64 onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1) />');
4652 + x += addHtmlValue("Message", '<div style=width:230px;margin:0;padding:0><textarea id=dp2msg maxlength=4096 style=width:100%;height:150px;resize:none onchange=p10validateSendMqttMsgDialog() onkeyup=p10validateSendMqttMsgDialog(event,1)></textarea></div>');
4653 setDialogMode(2, "Send MQTT message", 3, p10showSendMqttMsgDialogEx, x, nodeids);
4654 p10validateSendMqttMsgDialog();
4655 Q('dp2topic').focus();
@@ -4670,16 +4670,16 @@
4670 if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } }
4671
4672 // List all available alternative groups
4673 - var y = "<select id=p10newGroup style=width:236px>", count = 0;
4673 + var y = '<select id=p10newGroup style=width:236px>', count = 0;
4674 for (var i in meshes) {
4675 var meshrights = meshes[i].links[userinfo._id].rights;
4676 - if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += "<option value='" + meshes[i]._id + "'>" + meshes[i].name + "</option>"; }
4676 + if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
4677 }
4678 y += "</select>";
4679
4680 if (count > 0) {
4681 - var x = (nodeids.length == 1) ? "Select a new group for this device<br /><br />" : "Select a new group for selected devices<br /><br />";
4682 - x += addHtmlValue('New Device Group', y);
4681 + var x = (nodeids.length == 1) ? ("Select a new group for this device" + '<br /><br />') : ("Select a new group for selected devices" + '<br /><br />');
4682 + x += addHtmlValue("New Device Group", y);
4683 setDialogMode(2, "Change Group", 3, p10showChangeGroupDialogEx, x, nodeids);
4684 } else {
4685 setDialogMode(2, "Change Group", 1, null, "No other device group of same type exists.");
@@ -4693,8 +4693,8 @@
4693
4694 function p10showDeleteNodeDialog(nodeid) {
4695 if (xxdialogMode) return false;
4696 - var x = "Are you sure you want to delete node \"" + EscapeHtml(currentNode.name) + "\"?<br /><br />";
4697 - x += "<label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirm</label>";
4696 + var x = format("Are you sure you want to delete node {0}?", EscapeHtml(currentNode.name)) + '<br /><br />';
4697 + x += '<label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirm</label>';
4698 setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, x, nodeid);
4699 p10validateDeleteNodeDialog();
4700 return false;
@@ -4764,7 +4764,7 @@
4764 // Show network interfaces
4765 function p10showNodeNetInfoDialog() {
4766 if (xxdialogMode) return false;
4767 - setDialogMode(2, "Network Interfaces", 1, null, "<div id=d2netinfo>Loading...</div>", 'if' + currentNode._id );
4767 + setDialogMode(2, "Network Interfaces", 1, null, '<div id=d2netinfo>' + "Loading..." + '</div>', 'if' + currentNode._id );
4768 meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
4769 return false;
4770 }
@@ -4772,9 +4772,9 @@
4772 // Show MeshCentral Router dialog
4773 function p10showMeshRouterDialog() {
4774 if (xxdialogMode) return;
4775 - var x = "<div>MeshCentral Router is a Windows tool for TCP port mapping. You can, for example, RDP into a remote device thru this server.</div><br />";
4775 + var x = '<div>' + "MeshCentral Router is a Windows tool for TCP port mapping. You can, for example, RDP into a remote device thru this server." + '</div><br />';
4776 x += addHtmlValue('Win32 Executable', '<a style=cursor:pointer download href="meshagents?meshaction=winrouter" onclick="setDialogMode(0)">MeshCentralRouter.exe</a>');
4777 - setDialogMode(2, "MeshCentral Router", 1, null, x, "fileDownload");
4777 + setDialogMode(2, "MeshCentral Router", 1, null, x, 'fileDownload');
4778 }
4779
4780 // Request MQTT login credentials
@@ -4783,14 +4783,14 @@
4783 // Show MeshCmd dialog
4784 function p10showMeshCmdDialog(mode, nodeid) {
4785 if (xxdialogMode) return;
4786 - var y = "<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>";
4787 - y += "<option value=3>Windows (32bit)</option>";
4788 - y += "<option value=4>Windows (64bit)</option>";
4789 - y += "<option value=5>Linux x86 (32bit)</option>";
4790 - y += "<option value=6>Linux x86 (64bit)</option>";
4791 - y += "<option value=16>MacOS (64bit)</option>";
4792 - y += "<option value=25>Linux ARM, Raspberry Pi (32bit)</option>";
4793 - y += "</select>";
4786 + var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
4787 + y += '<option value=3>' + "Windows (32bit)" + '</option>';
4788 + y += '<option value=4>' + "Windows (64bit)" + '</option>';
4789 + y += '<option value=5>' + "Linux x86 (32bit)" + '</option>';
4790 + y += '<option value=6>' + "Linux x86 (64bit)" + '</option>';
4791 + y += '<option value=16>' + "MacOS (64bit)" + '</option>';
4792 + y += '<option value=25>' + "Linux ARM, Raspberry Pi (32bit)" + '</option>';
4793 + y += '</select>';
4794
4795 var x = "";
4796 if (mode == 0) { x += '<div>MeshCmd is a command line tool that performs lots of different operations. The action file can optionally be downloaded and edited to provide server information and credentials.<br /><br />'; }
@@ -4800,13 +4800,13 @@
4800 if (mode == 0) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=generic" download>MeshAction (.txt)</a>'); }
4801 if (mode == 1) { x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + nodeid + '" download>MeshAction (.txt)</a>'); }
4802 x += "</div>";
4803 - setDialogMode(2, ["Download MeshCmd","Network Router"][mode], 9, null, x, "fileDownload");
4803 + setDialogMode(2, [ "Download MeshCmd", "Network Router" ][mode], 9, null, x, 'fileDownload');
4804 meshCmdOsClick();
4805 }
4806
4807 function meshCmdOsClick() {
4808 var os = Q('aginsSelect').value, osn = '', osurl = '';
4809 - //Q('meshcmddownloadid').href = "meshagents?meshcmd=" + os;
4809 + //Q('meshcmddownloadid').href = 'meshagents?meshcmd=' + os;
4810 if (os == 3) { osn = 'MeshCmd (Win32 executable)'; }
4811 if (os == 4) { osn = 'MeshCmd (Win64 executable)'; }
4812 if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
@@ -4839,9 +4839,9 @@
4839 meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
4840 }
4841
4842 - var showEditNodeValueDialog_modes = ['Device Name', 'Hostname', 'Description', 'Tags'];
4842 + var showEditNodeValueDialog_modes = ["Device Name", "Hostname", "Description", "Tags"];
4843 var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
4844 - var showEditNodeValueDialog_modes3 = ['', '', '', 'Tag1, Tag2, Tag3'];
4844 + var showEditNodeValueDialog_modes3 = ['', '', '', "Tag1, Tag2, Tag3"];
4845 function showEditNodeValueDialog(mode) {
4846 if (xxdialogMode) return;
4847 var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
@@ -5008,7 +5008,7 @@
5008 // Switch to software KVM
5009 //if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
5010 console.log('WebRTC Data Channel Open');
5011 - Q('deskstatus').textContent = StatusStrs[desktop.State] + ', Soft-KVM';
5011 + Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
5012 desktop.m.hold(true);
5013 webRtcDesktop.webRtcActive = true;
5014 webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
@@ -5120,7 +5120,7 @@
5120 var xstate = state;
5121 if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
5122 var str = StatusStrs[xstate];
5123 - if ((desktop != null) && (desktop.webRtcActive == true)) { str += ', WebRTC'; }
5123 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
5124 //if (desktop.m.stopInput == true) { str += ', Loopback'; }
5125 QH('deskstatus', str);
5126 switch (state) {
@@ -5131,7 +5131,7 @@
5131 QV('DeskFocus', false);
5132 QV('termdisplays', false);
5133 QV('deskRecordIcon', false);
5134 - deskFocusBtn.value = 'All Focus';
5134 + deskFocusBtn.value = "All Focus";
5135 if (fullscreen == true) { deskToggleFull(); }
5136 webRtcDesktopReset();
5137 deskPreferedStickyDisplay = 0;
@@ -5198,7 +5198,7 @@
5198 }
5199 }
5200 if (desktop.contype == 2) {
5201 - if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; deskFocusBtn.value = 'All Focus'; }
5201 + if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; deskFocusBtn.value = "All Focus"; }
5202 if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
5203 }
5204 }
@@ -5262,7 +5262,7 @@
5262
5263 function deskToggleFocus() {
5264 desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
5265 - Q('deskFocusBtn').value = ['All Focus', 'Small Focus', 'Large Focus'][desktop.m.focusmode / 64];
5265 + Q('deskFocusBtn').value = ["All Focus", "Small Focus", "Large Focus"][desktop.m.focusmode / 64];
5266 }
5267
5268 function deskAdjust() {
@@ -5312,7 +5312,7 @@
5312 if (!mod || !sw || !sh || !cv) return;
5313
5314 // Check if we are in single desktop mode
5315 - if (cv.id == "Desk") { deskAdjust(); return; }
5315 + if (cv.id == 'Desk') { deskAdjust(); return; }
5316
5317 // Figure out and adjust the size to fill the width of the div
5318 var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
@@ -5418,7 +5418,7 @@
5418 function showDeskType() {
5419 if (xxdialogMode || desktop == null || desktop.State != 3) return;
5420 Q('DeskType').blur();
5421 - var x = '<div>Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding.<div>';
5421 + var x = '<div>' + "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding." + '<div>';
5422 x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
5423 setDialogMode(2, "Remote Keyboard Entry", 3, showDeskTypeEx, x);
5424 Q('d2typeText').focus();
@@ -5471,7 +5471,7 @@
5471 x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
5472 x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
5473 x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
5474 - x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>Remote clipboard is valid for 60 seconds.</span>&nbsp;</div><div></div>';
5474 + x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>' + "Remote clipboard is valid for 60 seconds." + '</span>&nbsp;</div><div></div>';
5475 setDialogMode(2, "Remote Clipboard", 8, null, x, 'clipboard');
5476 Q('d2clipText').focus();
5477 }
@@ -5591,20 +5591,20 @@
5591 var service = deskTools.services[index];
5592 if (service != null) {
5593 var x = '';
5594 - if (service.name) { x += addHtmlValue('Name', service.name); }
5595 - if (service.displayName) { x += addHtmlValue('Display name', service.displayName); }
5594 + if (service.name) { x += addHtmlValue("Name", service.name); }
5595 + if (service.displayName) { x += addHtmlValue("Display name", service.displayName); }
5596 if (service.status) {
5597 - if (service.status.state) { x += addHtmlValue('State', capitalizeFirstLetter(service.status.state.toLowerCase())); }
5598 - if (service.status.pid) { x += addHtmlValue('PID', service.status.pid); }
5597 + if (service.status.state) { x += addHtmlValue("State", capitalizeFirstLetter(service.status.state.toLowerCase())); }
5598 + if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
5599 var serviceTypes = [];
5600 - if (service.status.isFileSystemDriver === true) { serviceTypes.push('FileSystemDriver'); }
5601 - if (service.status.isInteractive === true) { serviceTypes.push('Interactive'); }
5602 - if (service.status.isKernelDriver === true) { serviceTypes.push('KernelDriver'); }
5603 - if (service.status.isOwnProcess === true) { serviceTypes.push('OwnProcess'); }
5604 - if (service.status.isSharedProcess === true) { serviceTypes.push('SharedProcess'); }
5605 - if (serviceTypes.length > 0) { x += addHtmlValue('Type', serviceTypes.join(', ')); }
5606 - }
5607 - x += '<br/><div style=float:right;margin-bottom:12px><input type=button value="Close" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value="Start" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value="Stop" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value="Restart" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
5600 + if (service.status.isFileSystemDriver === true) { serviceTypes.push("FileSystemDriver"); }
5601 + if (service.status.isInteractive === true) { serviceTypes.push("Interactive"); }
5602 + if (service.status.isKernelDriver === true) { serviceTypes.push("KernelDriver"); }
5603 + if (service.status.isOwnProcess === true) { serviceTypes.push("OwnProcess"); }
5604 + if (service.status.isSharedProcess === true) { serviceTypes.push("SharedProcess"); }
5605 + if (serviceTypes.length > 0) { x += addHtmlValue("Type", serviceTypes.join(', ')); }
5606 + }
5607 + x += '<br/><div style=float:right;margin-bottom:12px><input type=button value=\"' + "Close" + '\" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value=\"' + "Start" + '\" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value=\"' + "Stop" + '\" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value=\"' + "Restart" + '\" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
5608 setDialogMode(2, "Service Details", 8, null, x, name);
5609 }
5610 }
@@ -5627,8 +5627,8 @@
5627 // Save the desktop image to file
5628 function deskSaveImage() {
5629 if (xxdialogMode || desktop == null || desktop.State != 3) return;
5630 - 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);
5631 - Q("Desk")['toBlob'](function (blob) { saveAs(blob, n + ".jpg"); });
5630 + 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);
5631 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
5632 }
5633
5634 function deskDisplayInfo(sender, displays, selDisplay) {
@@ -5664,8 +5664,8 @@
5664 function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
5665 function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; }
5666 function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
5667 - function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); return false; }
5668 - function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type:'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
5667 + function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, format("Stop process #{0} \"{1}\"?", id, name), id); return false; }
5668 + function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
5669
5670 //
5671 // TERMINAL
@@ -5709,7 +5709,7 @@
5709 if (terminal) {
5710 Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
5711 Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
5712 - Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?'CR+LF':'LF';
5712 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR+LF":"LF";
5713 }
5714 }
5715
@@ -5718,7 +5718,7 @@
5718 var xstate = state;
5719 if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
5720 var str = StatusStrs[xstate];
5721 - if (terminal.webRtcActive == true) { str += ', WebRTC'; }
5721 + if (terminal.webRtcActive == true) { str += ", WebRTC"; }
5722 QH('termstatus', str);
5723 switch (state) {
5724 case 0:
@@ -5806,7 +5806,7 @@
5806 Q('connectbutton2').blur(); // Deselect the connect button so the button does not get key presses.
5807 }
5808
5809 - var terminalEmulations = ['UTF8 Terminal', 'Extended ASCII', 'Intel ASCII'];
5809 + var terminalEmulations = ["UTF8 Terminal", "Extended ASCII", "Intel ASCII"];
5810 function termToggleType() {
5811 if (!terminal || xxdialogMode) return;
5812 terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
@@ -5814,7 +5814,7 @@
5814 Q('id_ttypebutton').blur(); // Deselect the connect button so the button does not get key presses.
5815 }
5816
5817 - var fxEmulations = ['Intel (F10 = ESC+[OM)', 'Alternate (F10 = ESC+0)', 'VT100+ (F10 = ESC+[OY)'];
5817 + var fxEmulations = ["Intel (F10 = ESC+[OM)", "Alternate (F10 = ESC+0)", "VT100+ (F10 = ESC+[OY)"];
5818 function termToggleFx() {
5819 if (!terminal || xxdialogMode) return;
5820 terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3;
@@ -5825,7 +5825,7 @@
5825 function termToggleCr() {
5826 if (!terminal || xxdialogMode) return;
5827 if (terminal.m.lineFeed == '\n') { terminal.m.lineFeed = '\r\n'; } else { terminal.m.lineFeed = '\n'; }
5828 - Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? 'CR+LF' : 'LF';
5828 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? "CR+LF" : "LF";
5829 }
5830
5831 function termSendKey(key, id) {
@@ -5868,9 +5868,9 @@
5868 }
5869
5870 function onFilesStateChange(xfiles, state) {
5871 - p13Connect.value = (state == 0) ? 'Connect' : 'Disconnect';
5871 + p13Connect.value = (state == 0) ? "Connect" : "Disconnect";
5872 var str = StatusStrs[state];
5873 - if (files.webRtcActive == true) { str += ', WebRTC'; }
5873 + if (files.webRtcActive == true) { str += ", WebRTC"; }
5874 Q('p13Status').textContent = str;
5875 switch (state) {
5876 case 0:
@@ -5993,7 +5993,7 @@
5993
5994 // Figure out the date
5995 var fdatestr = '';
5996 - if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + "&nbsp;"; }
5996 + if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + '&nbsp;'; }
5997
5998 // Figure out the size
5999 var fsize = '';
@@ -6002,11 +6002,11 @@
6002 var h = '';
6003 if (f.t < 3) {
6004 var right = '', title = '';
6005 - h = "<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='" + f.nx + "'>&nbsp;<span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + " onclick=p13folderset(\"" + encodeURIComponent(f.nx) + "\")></div><a href=# style=cursor:pointer onclick='return p13folderset(\"" + encodeURIComponent(f.nx) + "\")'>" + shortname + "</a></span></div>";
6005 + h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p13folderset(\"' + encodeURIComponent(f.nx) + '\")></div><a href=# style=cursor:pointer onclick=\'return p13folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
6006 } else {
6007 var link = shortname;
6008 - if (f.s > 0) { link = "<a hrf=# rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"return p13downloadfile('" + encodeURIComponent(newlinkpath + '/' + name) + "','" + encodeURIComponent(name) + "'," + f.s + ")\">" + shortname + "</a>"; }
6009 - h = "<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='" + f.nx + "'>&nbsp;<span class=fsize>" + fdatestr + "</span><span style=float:right>" + fsize + "</span><span><div class=fileIcon" + f.t + "></div>" + link + "</span></div>";
6008 + if (f.s > 0) { link = '<a hrf=# rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"return p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
6009 + h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
6010 }
6011
6012 if (f.t < 3) { html1 += h; } else { html2 += h; }
@@ -6060,7 +6060,7 @@
6060 QE('p13RenameFileButton', false);
6061 QE('p13ViewFileButton', false);
6062 QE('p13SelectAllButton', false);
6063 - Q('p13SelectAllButton').value = 'Select All';
6063 + Q('p13SelectAllButton').value = "Select All";
6064 QE('p13RefreshButton', false);
6065 QE('p13CutButton', false);
6066 QE('p13CopyButton', false);
@@ -6074,7 +6074,7 @@
6074 QE('p13RenameFileButton', (cc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
6075 QE('p13ViewFileButton', (cc == 1) && (sfc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
6076 QE('p13SelectAllButton', tc > 0);
6077 - Q('p13SelectAllButton').value = (cc > 0 ? 'Select None' : 'Select All');
6077 + Q('p13SelectAllButton').value = (cc > 0 ? "Select None" : "Select All");
6078 QE('p13RefreshButton', true);
6079 QE('p13CutButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
6080 QE('p13CopyButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
@@ -6088,7 +6088,7 @@
6088 function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
6089 function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
6090 function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
6091 - function p13deletefile() { var cc = p13getFileSelCount(), rec = (p13getFileSelDirCount() > 0) ? "<br /><br /><label><input type=checkbox id=p13recdeleteinput>Recursive delete</label><br>" : "<input type=checkbox id=p13recdeleteinput style='display:none'>"; setDialogMode(2, "Delete", 3, p13deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?' + rec) : ('Delete selected item?' + rec)); }
6091 + function p13deletefile() { var cc = p13getFileSelCount(), rec = (p13getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p13recdeleteinput>' + "Recursive delete" + '</label><br>' : "<input type=checkbox id=p13recdeleteinput style='display:none'>"; setDialogMode(2, "Delete", 3, p13deletefileEx, (cc > 1) ? (format("Delete {0} selected items?", cc) + rec) : ("Delete selected item?" + rec)); }
6092 function p13deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p13filetree.dir[checkboxes[i].value].n); } } files.sendText({ action: 'rm', reqid: 1, path: p13filetreelocation.join('/'), delfiles: delfiles, rec: Q('p13recdeleteinput').checked }); p13folderup(999); }
6093 function p13renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p13filetree.dir[checkboxes[i].value].n; } } setDialogMode(2, "Rename", 3, p13renamefileEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p13filetreelocation.join('/'), oldname: renamefile}); focusTextBox('p13renameinput'); p13fileNameCheck(); }
6094 function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
@@ -6101,7 +6101,7 @@
6101 if (checkboxes[i].checked) {
6102 if (p13filetree.dir[checkboxes[i].value].s <= 204800) {
6103 p13downloadfile(encodeURIComponent(p13filetreelocation.join('/') + '/' + p13filetree.dir[checkboxes[i].value].n), encodeURIComponent(p13filetree.dir[checkboxes[i].value].n), p13filetree.dir[checkboxes[i].value].s, 'viewer');
6104 - } else { messagebox('File Editor', 'Only files less than 200k can be edited.'); }
6104 + } else { messagebox("File Editor", "Only files less than 200k can be edited."); }
6105 break;
6106 }
6107 }
@@ -6139,7 +6139,7 @@
6139
6140 function p13fileDragLeave(e) {
6141 haltEvent(e);
6142 - if (e.target.id != "p13filetable") {
6142 + if (e.target.id != 'p13filetable') {
6143 QV('p13bigfail', false);
6144 QV('p13bigok', false);
6145 } else {
@@ -6201,7 +6201,7 @@
6201
6202 function p13editSaveBack(b, tag) {
6203 var data = new TextEncoder().encode(Q('p13fileeditarea').value);
6204 - p13uploadFileContinue(1, [{ name: tag, size: data.byteLength, type: "text/plain", xdata: data }]);
6204 + p13uploadFileContinue(1, [{ name: tag, size: data.byteLength, type: 'text/plain', xdata: data }]);
6205 }
6206
6207 /*
@@ -6291,7 +6291,7 @@
6291 p13uploadFileContinue(1, files);
6292 } else {
6293 // Otherwise, prompt for confirmation
6294 - setDialogMode(2, "Upload File", 3, p13uploadFileContinue, 'Upload will overwrite ' + overWriteCount + ' file' + addLetterS(overWriteCount) + '. Continue?', files);
6294 + setDialogMode(2, "Upload File", 3, p13uploadFileContinue, format("Upload will overwrite {0} file{1}. Continue?", overWriteCount, addLetterS(overWriteCount)), files);
6295 }
6296 }
6297
@@ -6300,7 +6300,7 @@
6300 uploadFile.xpath = p13filetreelocation.join('/');
6301 uploadFile.xfiles = files;
6302 uploadFile.xfilePtr = -1;
6303 - setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>Connecting...</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
6303 + setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Connecting..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
6304 p13uploadReconnect();
6305 }
6306
@@ -6431,7 +6431,7 @@
6431 }
6432 }
6433 if (dateHeader != null) x += '</table>';
6434 - if (x == '') x = "<br><i>No Events Found</i><br><br>";
6434 + if (x == '') x = '<br><i>' + "No Events Found" + '</i><br><br>';
6435 QH('p16events', x);
6436 }
6437
@@ -6505,7 +6505,7 @@
6505 var samenode = (consoleNode == 'server');
6506 consoleNode = 'server';
6507
6508 - QH('p15deviceName', 'My Server Console');
6508 + QH('p15deviceName', "My Server Console");
6509 QE('p15consoleText', true);
6510 QH('p15statetext', '');
6511 QH('p15coreName', '');
@@ -6530,13 +6530,13 @@
6530 }
6531 var online = (((consoleNode.conn & 1) != 0) || ((consoleNode.conn & 16) != 0)) ? true : false;
6532 var onlineText = ((consoleNode.conn & 1) != 0) ? "Agent is online" : "Agent is offline"
6533 - if ((consoleNode.conn & 16) != 0) { onlineText += ', MQTT is online' }
6533 + if ((consoleNode.conn & 16) != 0) { onlineText += ", MQTT is online" }
6534 QH('p15statetext', onlineText);
6535 QE('p15consoleText', online);
6536 QE('p15uploadCore', ((consoleNode.conn & 1) != 0));
6537 QV('p15outputselecttd', (consoleNode.conn & 17) == 17);
6538 } else {
6539 - QH('p15statetext', 'Access Denied');
6539 + QH('p15statetext', "Access Denied");
6540 QE('p15consoleText', false);
6541 QE('p15uploadCore', false);
6542 QV('p15outputselecttd', false);
@@ -6568,7 +6568,7 @@
6568 } else {
6569 if (((consoleNode.conn & 16) != 0) && ((Q('p15outputselect').value == 2) || ((consoleNode.conn & 1) == 0))) {
6570 // Send the command to MQTT
6571 - t = '<div style=color:orange>MQTT&gt; ' + EscapeHtml(v) + '<br/></div>';
6571 + t = '<div style=color:orange>' + "MQTT" + '&gt; ' + EscapeHtml(v) + '<br/></div>';
6572 consoleNode.consoleText += t;
6573 meshserver.send({ action: 'sendmqttmsg', topic: 'console', nodeids: [ consoleNode._id ], msg: v });
6574 } else {
@@ -6604,7 +6604,7 @@
6604 }
6605 } else {
6606 // Agent console data
6607 - if (source == 'MQTT') { data = '<div style=color:red>MQTT&gt; ' + EscapeHtml(data) + '<br/></div>'; } else { data = '<div>' + data + '</div>' }
6607 + if (source == 'MQTT') { data = '<div style=color:red>' + "MQTT" + '&gt; ' + EscapeHtml(data) + '<br/></div>'; } else { data = '<div>' + data + '</div>' }
6608 if (node.consoleText == null) { node.consoleText = data; } else { node.consoleText += data; }
6609 if (consoleNode == node) {
6610 Q('p15agentConsoleText').innerHTML += data;
@@ -6624,7 +6624,7 @@
6624 if (e.shiftKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'default' }); } // Upload default core
6625 else if (e.altKey == true) { meshserver.send({ action: 'uploadagentcore', nodeid: consoleNode._id, type: 'clear' }); } // Clear the core
6626 else if (e.ctrlKey == true) { p15uploadCore2(); } // Upload the core from a file
6627 - else { setDialogMode(2, "Perform Agent Action", 3, p15uploadCoreEx, addHtmlValue('Action', '<select id=d3coreMode style=width:230px><option value=1>Upload default server core</option><option value=2>Clear the core</option><option value=6>Upload recovery core</option><option value=3>Upload a core file</option><option value=4>Soft disconnect agent</option><option value=5>Hard disconnect agent</option></select>')); }
6627 + else { setDialogMode(2, "Perform Agent Action", 3, p15uploadCoreEx, addHtmlValue("Action", '<select id=d3coreMode style=width:230px><option value=1>' + "Upload default server core" + '</option><option value=2>' + "Clear the core" + '</option><option value=6>' + "Upload recovery core" + '</option><option value=3>' + "Upload a core file" + '</option><option value=4>' + "Soft disconnect agent" + '</option><option value=5>' + "Hard disconnect agent" + '</option></select>')); }
6628 }
6629
6630 function p15uploadCoreEx() {
@@ -6714,12 +6714,12 @@
6714
6715 function account_addhkey(type) {
6716 if (type == 3) {
6717 - var x = "Type in the name of the key to add.<br /><br />";
6718 - x += addHtmlValue('Key Name', '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="MyKey" onkeyup=account_addhkeyValidate(event,2) />');
6717 + var x = "Type in the name of the key to add." + '<br /><br />';
6718 + x += addHtmlValue("Key Name", '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="' + "MyKey" + '" onkeyup=account_addhkeyValidate(event,2) />');
6719 } else if (type == 2) {
6720 - var x = "Type in a key name, select the OTP box and press the button on the YubiKey&trade;.<br /><br />";
6721 - x += addHtmlValue('Key Name', '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="MyKey" onkeyup=account_addhkeyValidate(event,1) />');
6722 - x += addHtmlValue('YubiKey&trade; OTP', '<input id=dp1key style=width:230px autocomplete=off onkeyup=account_addhkeyValidate(event,2) />');
6720 + var x = "Type in a key name, select the OTP box and press the button on the YubiKey&trade;." + '<br /><br />';
6721 + x += addHtmlValue("Key Name", '<input id=dp1keyname style=width:230px maxlength=20 autocomplete=off placeholder="' + "MyKey" + '" onkeyup=account_addhkeyValidate(event,1) />');
6722 + x += addHtmlValue("YubiKey&trade; OTP", '<input id=dp1key style=width:230px autocomplete=off onkeyup=account_addhkeyValidate(event,2) />');
6723 }
6724 setDialogMode(2, "Add Security Key", 3, account_addhkeyEx, x, type);
6725 Q('dp1keyname').focus();
@@ -6734,7 +6734,7 @@
6734 if (name == '') { name = 'MyKey'; }
6735 if (type == 2) {
6736 meshserver.send({ action: 'otp-hkey-yubikey-add', name: name, otp: Q('dp1key').value });
6737 - setDialogMode(2, "Add Security Key", 0, null, "<br />Checking...<br /><br /><br />", 'otpauth-hardware-manage');
6737 + setDialogMode(2, "Add Security Key", 0, null, '<br />' + "Checking..." + '<br /><br /><br />', 'otpauth-hardware-manage');
6738 } else if (type == 3) {
6739 meshserver.send({ action: 'webauthn-startregister', name: name });
6740 }
@@ -6745,14 +6745,14 @@
6745 meshserver.send({ action: 'otp-hkey-get' });
6746 }
6747
6748 - var loclist = { "af": "Afrikaans", "sq": "Albanian", "ar": "Arabic (Standard)", "ar-dz": "Arabic (Algeria)", "ar-bh": "Arabic (Bahrain)", "ar-eg": "Arabic (Egypt)", "ar-iq": "Arabic (Iraq)", "ar-jo": "Arabic (Jordan)", "ar-kw": "Arabic (Kuwait)", "ar-lb": "Arabic (Lebanon)", "ar-ly": "Arabic (Libya)", "ar-ma": "Arabic (Morocco)", "ar-om": "Arabic (Oman)", "ar-qa": "Arabic (Qatar)", "ar-sa": "Arabic (Saudi Arabia)", "ar-sy": "Arabic (Syria)", "ar-tn": "Arabic (Tunisia)", "ar-ae": "Arabic (U.A.E.)", "ar-ye": "Arabic (Yemen)", "an": "Aragonese", "hy": "Armenian", "as": "Assamese", "ast": "Asturian", "az": "Azerbaijani", "eu": "Basque", "bg": "Bulgarian", "be": "Belarusian", "bn": "Bengali", "bs": "Bosnian", "br": "Breton", "my": "Burmese", "ca": "Catalan", "ch": "Chamorro", "ce": "Chechen", "zh": "Chinese", "zh-hk": "Chinese (Hong Kong)", "zh-cn": "Chinese (PRC)", "zh-sg": "Chinese (Singapore)", "zh-tw": "Chinese (Taiwan)", "cv": "Chuvash", "co": "Corsican", "cr": "Cree", "hr": "Croatian", "cs": "Czech", "da": "Danish", "nl": "Dutch (Standard)", "nl-be": "Dutch (Belgian)", "en": "English", "en-au": "English (Australia)", "en-bz": "English (Belize)", "en-ca": "English (Canada)", "en-ie": "English (Ireland)", "en-jm": "English (Jamaica)", "en-nz": "English (New Zealand)", "en-ph": "English (Philippines)", "en-za": "English (South Africa)", "en-tt": "English (Trinidad & Tobago)", "en-gb": "English (United Kingdom)", "en-us": "English (United States)", "en-zw": "English (Zimbabwe)", "eo": "Esperanto", "et": "Estonian", "fo": "Faeroese", "fa": "Farsi (Persian)", "fj": "Fijian", "fi": "Finnish", "fr": "French (Standard)", "fr-be": "French (Belgium)", "fr-ca": "French (Canada)", "fr-fr": "French (France)", "fr-lu": "French (Luxembourg)", "fr-mc": "French (Monaco)", "fr-ch": "French (Switzerland)", "fy": "Frisian", "fur": "Friulian", "gd": "Gaelic (Scots)", "gd-ie": "Gaelic (Irish)", "gl": "Galacian", "ka": "Georgian", "de": "German (Standard)", "de-at": "German (Austria)", "de-de": "German (Germany)", "de-li": "German (Liechtenstein)", "de-lu": "German (Luxembourg)", "de-ch": "German (Switzerland)", "el": "Greek", "gu": "Gujurati", "ht": "Haitian", "he": "Hebrew", "hi": "Hindi", "hu": "Hungarian", "is": "Icelandic", "id": "Indonesian", "iu": "Inuktitut", "ga": "Irish", "it": "Italian (Standard)", "it-ch": "Italian (Switzerland)", "ja": "Japanese", "kn": "Kannada", "ks": "Kashmiri", "kk": "Kazakh", "km": "Khmer", "ky": "Kirghiz", "tlh": "Klingon", "ko": "Korean", "ko-kp": "Korean (North Korea)", "ko-kr": "Korean (South Korea)", "la": "Latin", "lv": "Latvian", "lt": "Lithuanian", "lb": "Luxembourgish", "mk": "FYRO Macedonian", "ms": "Malay", "ml": "Malayalam", "mt": "Maltese", "mi": "Maori", "mr": "Marathi", "mo": "Moldavian", "nv": "Navajo", "ng": "Ndonga", "ne": "Nepali", "no": "Norwegian", "nb": "Norwegian (Bokmal)", "nn": "Norwegian (Nynorsk)", "oc": "Occitan", "or": "Oriya", "om": "Oromo", "fa-ir": "Persian/Iran", "pl": "Polish", "pt": "Portuguese", "pt-br": "Portuguese (Brazil)", "pa": "Punjabi", "pa-in": "Punjabi (India)", "pa-pk": "Punjabi (Pakistan)", "qu": "Quechua", "rm": "Rhaeto-Romanic", "ro": "Romanian", "ro-mo": "Romanian (Moldavia)", "ru": "Russian", "ru-mo": "Russian (Moldavia)", "sz": "Sami (Lappish)", "sg": "Sango", "sa": "Sanskrit", "sc": "Sardinian", "sd": "Sindhi", "si": "Singhalese", "sr": "Serbian", "sk": "Slovak", "sl": "Slovenian", "so": "Somani", "sb": "Sorbian", "es": "Spanish", "es-ar": "Spanish (Argentina)", "es-bo": "Spanish (Bolivia)", "es-cl": "Spanish (Chile)", "es-co": "Spanish (Colombia)", "es-cr": "Spanish (Costa Rica)", "es-do": "Spanish (Dominican Republic)", "es-ec": "Spanish (Ecuador)", "es-sv": "Spanish (El Salvador)", "es-gt": "Spanish (Guatemala)", "es-hn": "Spanish (Honduras)", "es-mx": "Spanish (Mexico)", "es-ni": "Spanish (Nicaragua)", "es-pa": "Spanish (Panama)", "es-py": "Spanish (Paraguay)", "es-pe": "Spanish (Peru)", "es-pr": "Spanish (Puerto Rico)", "es-es": "Spanish (Spain)", "es-uy": "Spanish (Uruguay)", "es-ve": "Spanish (Venezuela)", "sx": "Sutu", "sw": "Swahili", "sv": "Swedish", "sv-fi": "Swedish (Finland)", "sv-sv": "Swedish (Sweden)", "ta": "Tamil", "tt": "Tatar", "te": "Teluga", "th": "Thai", "tig": "Tigre", "ts": "Tsonga", "tn": "Tswana", "tr": "Turkish", "tk": "Turkmen", "uk": "Ukrainian", "hsb": "Upper Sorbian", "ur": "Urdu", "ve": "Venda", "vi": "Vietnamese", "vo": "Volapuk", "wa": "Walloon", "cy": "Welsh", "xh": "Xhosa", "ji": "Yiddish", "zu": "Zulu" };
6748 + var loclist = { 'af': "Afrikaans", 'sq': "Albanian", 'ar': "Arabic (Standard)", 'ar-dz': "Arabic (Algeria)", 'ar-bh': "Arabic (Bahrain)", 'ar-eg': "Arabic (Egypt)", 'ar-iq': "Arabic (Iraq)", 'ar-jo': "Arabic (Jordan)", 'ar-kw': "Arabic (Kuwait)", 'ar-lb': "Arabic (Lebanon)", 'ar-ly': "Arabic (Libya)", 'ar-ma': "Arabic (Morocco)", 'ar-om': "Arabic (Oman)", 'ar-qa': "Arabic (Qatar)", 'ar-sa': "Arabic (Saudi Arabia)", 'ar-sy': "Arabic (Syria)", 'ar-tn': "Arabic (Tunisia)", 'ar-ae': "Arabic (U.A.E.)", 'ar-ye': "Arabic (Yemen)", 'an': "Aragonese", 'hy': "Armenian", 'as': "Assamese", 'ast': "Asturian", 'az': "Azerbaijani", 'eu': "Basque", 'bg': "Bulgarian", 'be': "Belarusian", 'bn': "Bengali", 'bs': "Bosnian", 'br': "Breton", 'my': "Burmese", 'ca': "Catalan", 'ch': "Chamorro", 'ce': "Chechen", 'zh': "Chinese", 'zh-hk': "Chinese (Hong Kong)", 'zh-cn': "Chinese (PRC)", 'zh-sg': "Chinese (Singapore)", 'zh-tw': "Chinese (Taiwan)", 'cv': "Chuvash", 'co': "Corsican", 'cr': "Cree", 'hr': "Croatian", 'cs': "Czech", 'da': "Danish", 'nl': "Dutch (Standard)", 'nl-be': "Dutch (Belgian)", 'en': "English", 'en-au': "English (Australia)", 'en-bz': "English (Belize)", 'en-ca': "English (Canada)", 'en-ie': "English (Ireland)", 'en-jm': "English (Jamaica)", 'en-nz': "English (New Zealand)", 'en-ph': "English (Philippines)", 'en-za': "English (South Africa)", 'en-tt': "English (Trinidad & Tobago)", 'en-gb': "English (United Kingdom)", 'en-us': "English (United States)", 'en-zw': "English (Zimbabwe)", 'eo': "Esperanto", 'et': "Estonian", 'fo': "Faeroese", 'fa': "Farsi (Persian)", 'fj': "Fijian", 'fi': "Finnish", 'fr': "French (Standard)", 'fr-be': "French (Belgium)", 'fr-ca': "French (Canada)", 'fr-fr': "French (France)", 'fr-lu': "French (Luxembourg)", 'fr-mc': "French (Monaco)", 'fr-ch': "French (Switzerland)", 'fy': "Frisian", 'fur': "Friulian", 'gd': "Gaelic (Scots)", 'gd-ie': "Gaelic (Irish)", 'gl': "Galacian", 'ka': "Georgian", 'de': "German (Standard)", 'de-at': "German (Austria)", 'de-de': "German (Germany)", 'de-li': "German (Liechtenstein)", 'de-lu': "German (Luxembourg)", 'de-ch': "German (Switzerland)", 'el': "Greek", 'gu': "Gujurati", 'ht': "Haitian", 'he': "Hebrew", 'hi': "Hindi", 'hu': "Hungarian", 'is': "Icelandic", 'id': "Indonesian", 'iu': "Inuktitut", 'ga': "Irish", 'it': "Italian (Standard)", 'it-ch': "Italian (Switzerland)", 'ja': "Japanese", 'kn': "Kannada", 'ks': "Kashmiri", 'kk': "Kazakh", 'km': "Khmer", 'ky': "Kirghiz", 'tlh': "Klingon", 'ko': "Korean", 'ko-kp': "Korean (North Korea)", 'ko-kr': "Korean (South Korea)", 'la': "Latin", 'lv': "Latvian", 'lt': "Lithuanian", 'lb': "Luxembourgish", 'mk': "FYRO Macedonian", 'ms': "Malay", 'ml': "Malayalam", 'mt': "Maltese", 'mi': "Maori", 'mr': "Marathi", 'mo': "Moldavian", 'nv': "Navajo", 'ng': "Ndonga", 'ne': "Nepali", 'no': "Norwegian", 'nb': "Norwegian (Bokmal)", 'nn': "Norwegian (Nynorsk)", 'oc': "Occitan", 'or': "Oriya", 'om': "Oromo", 'fa-ir': "Persian/Iran", 'pl': "Polish", 'pt': "Portuguese", 'pt-br': "Portuguese (Brazil)", 'pa': "Punjabi", 'pa-in': "Punjabi (India)", 'pa-pk': "Punjabi (Pakistan)", 'qu': "Quechua", 'rm': "Rhaeto-Romanic", 'ro': "Romanian", 'ro-mo': "Romanian (Moldavia)", 'ru': "Russian", 'ru-mo': "Russian (Moldavia)", 'sz': "Sami (Lappish)", 'sg': "Sango", 'sa': "Sanskrit", 'sc': "Sardinian", 'sd': "Sindhi", 'si': "Singhalese", 'sr': "Serbian", 'sk': "Slovak", 'sl': "Slovenian", 'so': "Somani", 'sb': "Sorbian", 'es': "Spanish", 'es-ar': "Spanish (Argentina)", 'es-bo': "Spanish (Bolivia)", 'es-cl': "Spanish (Chile)", 'es-co': "Spanish (Colombia)", 'es-cr': "Spanish (Costa Rica)", 'es-do': "Spanish (Dominican Republic)", 'es-ec': "Spanish (Ecuador)", 'es-sv': "Spanish (El Salvador)", 'es-gt': "Spanish (Guatemala)", 'es-hn': "Spanish (Honduras)", 'es-mx': "Spanish (Mexico)", 'es-ni': "Spanish (Nicaragua)", 'es-pa': "Spanish (Panama)", 'es-py': "Spanish (Paraguay)", 'es-pe': "Spanish (Peru)", 'es-pr': "Spanish (Puerto Rico)", 'es-es': "Spanish (Spain)", 'es-uy': "Spanish (Uruguay)", 'es-ve': "Spanish (Venezuela)", 'sx': "Sutu", 'sw': "Swahili", 'sv': "Swedish", 'sv-fi': "Swedish (Finland)", 'sv-sv': "Swedish (Sweden)", 'ta': "Tamil", 'tt': "Tatar", 'te': "Teluga", 'th': "Thai", 'tig': "Tigre", 'ts': "Tsonga", 'tn': "Tswana", 'tr': "Turkish", 'tk': "Turkmen", 'uk': "Ukrainian", 'hsb': "Upper Sorbian", 'ur': "Urdu", 've': "Venda", 'vi': "Vietnamese", 'vo': "Volapuk", 'wa': "Walloon", 'cy': "Welsh", 'xh': "Xhosa", 'ji': "Yiddish", 'zu': "Zulu" };
6749 function account_showLocalizationSettings() {
6750 if (xxdialogMode) return false;
6751 var n = getstore('loctag', 0);
6752 - var x = '<select id=d2locselect style=width:100%><option value="*">User browser value</option>';
6752 + var x = '<select id=d2locselect style=width:100%><option value="*">' + "User browser value" + '</option>';
6753 for (var i in loclist) { x += '<option value="' + i + '"' + ((n == i)?' selected':'') + '>' + i + ' - ' + loclist[i] + '</option>'; }
6754 x += '</select>';
6755 - var y = addHtmlValue('Localization', x);
6755 + var y = addHtmlValue("Localization", x);
6756 setDialogMode(2, "Localization Settings", 3, account_showLocalizationSettingsEx, y);
6757 return false;
6758 }
@@ -6775,10 +6775,10 @@
6775 function account_showAccountNotifySettings() {
6776 if (xxdialogMode) return false;
6777 var x = '';
6778 - x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />Notification sound.</label></div>';
6779 - x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />Device connections.</label></div>';
6780 - x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />Device disconnections.</label></div>';
6781 - x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />Intel&reg; AMT desktop and serial events.</label></div>';
6778 + x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Notification sound." + '</label></div>';
6779 + x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Device connections." + '</label></div>';
6780 + x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections." + '</label></div>';
6781 + x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events." + '</label></div>';
6782 setDialogMode(2, "Notification Settings", 3, account_showAccountNotifySettingsEx, x);
6783 var n = getstore('notifications', 0);
6784 Q('p2notifyPlayNotifySound').checked = (n & 1);
@@ -6799,7 +6799,7 @@
6799
6800 function account_showVerifyEmail() {
6801 if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return false;
6802 - var x = "Click ok to send a verification mail to:<br /><div style=padding:8px><b>" + EscapeHtml(userinfo.email) + "</b></div>Please wait a few minute to receive the verification.";
6802 + var x = "Click ok to send a verification mail to:" + '<br /><div style=padding:8px><b>' + EscapeHtml(userinfo.email) + '</b></div>' + "Please wait a few minute to receive the verification.";
6803 setDialogMode(2, "Email Verification", 3, account_showVerifyEmailEx, x);
6804 return false;
6805 }
@@ -6810,7 +6810,7 @@
6810
6811 function account_showChangeEmail() {
6812 if (xxdialogMode) return false;
6813 - var x = "Change your account email address here.<br /><br />";
6813 + var x = "Change your account email address here." + '<br /><br />';
6814 x += addHtmlValue('Email', '<input id=dp2email style=width:230px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
6815 setDialogMode(2, "Email Address Change", 3, account_changeEmail, x);
6816 if (userinfo.email != null) { Q('dp2email').value = userinfo.email; }
@@ -6830,10 +6830,10 @@
6830
6831 function account_showDeleteAccount() {
6832 if (xxdialogMode) return false;
6833 - var x = "To delete this account, type in the account password in both boxes below and hit ok.<br /><br />";
6834 - x += "<form method=post><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=" + authCookie + " /><table style=margin-left:80px><tr>";
6835 - x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
6836 - x += "</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
6833 + var x = "To delete this account, type in the account password in both boxes below and hit ok." + '<br /><br />';
6834 + x += '<form method=post><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=" + authCookie + " /><table style=margin-left:80px><tr>';
6835 + x += '<td align=right>' + "Password:" + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
6836 + x += '</tr><tr><td align=right>' + "Password:" + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
6837 x += '</tr></table><br /><div style=padding:10px;margin-bottom:4px>';
6838 x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
6839 x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
@@ -6848,13 +6848,13 @@
6848 if (xxdialogMode) return false;
6849 var x = "Change your account password by entering the old password and new password twice in the boxes below.";
6850 if (features & 0x00010000) { " Password hint can be used but is not recommanded."; }
6851 - x += "<br /><br />";
6851 + x += '<br /><br />';
6852 //x += "<form action='" + domainUrl + "changepassword' method=post>";
6853 - x += "<table style=margin-left:60px>";
6854 - x += "<tr><td align=right>Old password:</td><td><input id=apassword0 type=password name=apassword0 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b></b></td></tr>";
6855 - x += "<tr><td align=right>New password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td></tr>";
6856 - x += "<tr><td align=right>New password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>";
6857 - if (features & 0x00010000) { x += "<tr><td align=right>Password hint:</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>"; }
6853 + x += '<table style=margin-left:60px>';
6854 + x += '<tr><td align=right>Old password:</td><td><input id=apassword0 type=password name=apassword0 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b></b></td></tr>';
6855 + x += '<tr><td align=right>New password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td></tr>';
6856 + x += '<tr><td align=right>New password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>';
6857 + if (features & 0x00010000) { x += '<tr><td align=right>' + "Password hint:" + '</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>'; }
6858 x += '</table>'
6859 if (passRequirements) {
6860 var r = [], rc = 0;
@@ -6893,10 +6893,10 @@
6893 if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" tab and look at the \"Account Security\" section."); return false; }
6894
6895 // We are allowed, let's prompt to information
6896 - var x = "Create a new device group using the options below.<br /><br />";
6897 - x += addHtmlValue('Name', '<input id=dp2meshname style=width:230px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />');
6898 - x += addHtmlValue('Type', '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>Manage using a software agent</option><option value=1>Intel&reg; AMT only, no agent</option></select></div>');
6899 - x += addHtmlValue('Description', '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
6896 + var x = "Create a new device group using the options below." + '<br /><br />';
6897 + x += addHtmlValue("Name", '<input id=dp2meshname style=width:230px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />');
6898 + x += addHtmlValue("Type", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Manage using a software agent" + '</option><option value=1>' + "Intel&reg; AMT only, no agent" + '</option></select></div>');
6899 + x += addHtmlValue("Description", '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
6900 setDialogMode(2, "New Device Group", 3, account_createMeshEx, x);
6901 account_validateMeshCreate();
6902 Q('dp2meshname').focus();
@@ -6924,11 +6924,11 @@
6924 if (passRequirements == null || passRequirements == '') {
6925 // No password requirements, display password strength
6926 var passStrength = checkPasswordStrength(Q('apassword1').value);
6927 - if (passStrength >= 80) { r = '<span style=color:green>Strong<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>Good<span>'; } else { r = '<span style=color:red>Weak<span>'; }
6927 + if (passStrength >= 80) { r = '<span style=color:green>' + "Strong" + '<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>' + "Good" + '<span>'; } else { r = '<span style=color:red>' + "Weak" + '<span>'; }
6928 } else {
6929 // Password requirements provided, use that
6930 var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
6931 - if (passReq == false) { ok = false; r = '<span style=color:red>Policy<span>' }
6931 + if (passReq == false) { ok = false; r = '<span style=color:red>' + "Policy" + '<span>' }
6932 }
6933 }
6934 QH('dxPassWarn', r);
@@ -6976,8 +6976,8 @@
6976 // Mesh rights
6977 var meshrights = 0;
6978 if (meshes[i].links[userinfo._id]) { meshrights = meshes[i].links[userinfo._id].rights; }
6979 - var rights = 'Partial Rights';
6980 - if (meshrights == 0xFFFFFFFF) rights = 'Full Administrator'; else if (meshrights == 0) rights = 'No Rights';
6979 + var rights = "Partial Rights";
6980 + if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights";
6981
6982 // Print the mesh information
6983 r += '<div onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:431px;height:50px;padding-top:1px;padding-bottom:1px;float:left><div style=float:left;width:30px;height:100%></div><div tabindex=0 style=height:100%;cursor:pointer onclick=gotoMesh(\'' + i + '\') onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + i + '\')"><div class=mi style=float:left;width:50px;height:50px></div><div style=height:100%><div class=g1></div><div class=e2 style=width:300px><div class=e1>' + EscapeHtml(meshes[i].name) + '</div><div>' + rights + '</div></div><div class=g2 style=float:left></div></div></div></div>';
@@ -6997,12 +6997,12 @@
6997
6998 function server_showRestoreDlg() {
6999 if (xxdialogMode) return false;
7000 - var x = 'Restore the server using a backup, <span style=color:red>this will delete the existing server data</span>. Only do this if you know what you are doing.<br /><br />';
7000 + var x = "Restore the server using a backup, <span style=color:red>this will delete the existing server data</span>. Only do this if you know what you are doing." + '<br /><br />';
7001 x += '<form action="/restoreserver.ashx" enctype="multipart/form-data" method="post"><div>';
7002 x += '<input type=hidden name=auth value=' + authCookie + '>';
7003 x += '<input id=account_dlgFileInput type=file name=datafile style=width:100% accept=".zip,application/octet-stream,application/zip,application/x-zip,application/x-zip-compressed" onchange=account_validateServerRestore()>';
7004 - x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
7005 - x += '<input id=account_dlgOkButton type=submit value=OK style=float:right;width:80px onclick=dialogclose(1)>';
7004 + x += '<input id=account_dlgCancelButton type=button value=' + "Cancel" + ' style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
7005 + x += '<input id=account_dlgOkButton type=submit value=' + "OK" + ' style=float:right;width:80px onclick=dialogclose(1)>';
7006 x += '</div><br /><br /></form>';
7007 setDialogMode(2, "Restore Server", 0, null, x);
7008 account_validateServerRestore();
@@ -7031,7 +7031,7 @@
7031 }
7032 function server_showErrorsDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
7033 function server_showErrorsDlgEx() { meshserver.send({ action: 'serverclearerrorlog' }); }
7034 - function d2CopyServerErrorsToClip() { saveAs(new Blob([Q('d2ServerErrorsLogPre').innerText], { type: "application/octet-stream" }), "servererrors.txt"); }
7034 + function d2CopyServerErrorsToClip() { saveAs(new Blob([Q('d2ServerErrorsLogPre').innerText], { type: 'application/octet-stream' }), "servererrors.txt"); }
7035
7036 //
7037 // MY MESHS
@@ -7041,30 +7041,30 @@
7041 function p20updateMesh() {
7042 if (currentMesh == null) return;
7043 QH('p20meshName', EscapeHtml(currentMesh.name));
7044 - var meshtype = 'Unknown #' + currentMesh.mtype;
7044 + var meshtype = format("Unknown #{0}", currentMesh.mtype);
7045 var meshrights = 0;
7046 try { meshrights = currentMesh.links[userinfo._id].rights; } catch (ex) { }
7047 - if (currentMesh.mtype == 1) meshtype = 'Intel&reg; AMT only, no agent';
7048 - if (currentMesh.mtype == 2) meshtype = 'Managed using a software agent';
7047 + if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMT only, no agent";
7048 + if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
7049
7050 var x = '';
7051 - x += addHtmlValue('Name', addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
7052 - x += addHtmlValue('Description', addLinkConditional(((currentMesh.desc && currentMesh.desc != '')?EscapeHtml(currentMesh.desc):'<i>None</i>'), 'p20editmesh(2)', (meshrights & 1) != 0));
7051 + x += addHtmlValue("Name", addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
7052 + x += addHtmlValue("Description", addLinkConditional(((currentMesh.desc && currentMesh.desc != '')?EscapeHtml(currentMesh.desc):('<i>' + "None" + '</i>')), 'p20editmesh(2)', (meshrights & 1) != 0));
7053
7054 // Display group type
7055 - x += addHtmlValue('Type', meshtype);
7055 + x += addHtmlValue("Type", meshtype);
7056 //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
7057
7058 // Display features
7059 if (currentMesh.mtype == 2) {
7060 var meshFeatures = [];
7061 if (currentMesh.flags) {
7062 - if (currentMesh.flags & 1) { meshFeatures.push('Auto-Remove'); }
7063 - if (currentMesh.flags & 2) { meshFeatures.push('Hostname Sync'); }
7062 + if (currentMesh.flags & 1) { meshFeatures.push("Auto-Remove"); }
7063 + if (currentMesh.flags & 2) { meshFeatures.push("Hostname Sync"); }
7064 }
7065 meshFeatures = meshFeatures.join(', ');
7066 - if (meshFeatures == '') { meshFeatures = '<i>None</i>'; }
7067 - x += addHtmlValue('Features', addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1));
7066 + if (meshFeatures == '') { meshFeatures = '<i>' + "None" + '</i>'; }
7067 + x += addHtmlValue("Features", addLinkConditional(meshFeatures, 'p20editmeshfeatures()', meshrights & 1));
7068 }
7069
7070 // Display user consent
@@ -7073,64 +7073,64 @@
7073 var consent = 0;
7074 if (currentMesh.consent) { consent = currentMesh.consent; }
7075 if (serverinfo.consent) { consent |= serverinfo.consent; }
7076 - if ((consent & 0x0040) && (consent & 0x0008)) { meshFeatures.push('Desktop Prompt+Toolbar'); } else if (consent & 0x0040) { meshFeatures.push('Desktop Toolbar'); } else if (consent & 0x0008) { meshFeatures.push('Desktop Prompt'); } else { if (consent & 0x0001) { meshFeatures.push('Desktop Notify'); } }
7077 - if (consent & 0x0010) { meshFeatures.push('Terminal Prompt'); } else { if (consent & 0x0002) { meshFeatures.push('Terminal Notify'); } }
7078 - if (consent & 0x0020) { meshFeatures.push('Files Prompt'); } else { if (consent & 0x0004) { meshFeatures.push('Files Notify'); } }
7079 - if (consent == 7) { meshFeatures = ['Always Notify']; }
7080 - if ((consent & 56) == 56) { meshFeatures = ['Always Prompt']; }
7076 + if ((consent & 0x0040) && (consent & 0x0008)) { meshFeatures.push("Desktop Prompt+Toolbar"); } else if (consent & 0x0040) { meshFeatures.push("Desktop Toolbar"); } else if (consent & 0x0008) { meshFeatures.push("Desktop Prompt"); } else { if (consent & 0x0001) { meshFeatures.push("Desktop Notify"); } }
7077 + if (consent & 0x0010) { meshFeatures.push("Terminal Prompt"); } else { if (consent & 0x0002) { meshFeatures.push("Terminal Notify"); } }
7078 + if (consent & 0x0020) { meshFeatures.push("Files Prompt"); } else { if (consent & 0x0004) { meshFeatures.push("Files Notify"); } }
7079 + if (consent == 7) { meshFeatures = ["Always Notify"]; }
7080 + if ((consent & 56) == 56) { meshFeatures = ["Always Prompt"]; }
7081
7082 meshFeatures = meshFeatures.join(', ');
7083 - if (meshFeatures == '') { meshFeatures = '<i>None</i>'; }
7084 - x += addHtmlValue('User Consent', addLinkConditional(meshFeatures, 'p20editmeshconsent()', meshrights & 1));
7083 + if (meshFeatures == '') { meshFeatures = '<i>' + "None" + '</i>'; }
7084 + x += addHtmlValue("User Consent", addLinkConditional(meshFeatures, 'p20editmeshconsent()', meshrights & 1));
7085 }
7086
7087 // Display user consent
7088 var meshNotify = 0, meshNotifyStr = [];
7089 if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
7090 - if (meshNotify & 2) { meshNotifyStr.push('Connect'); }
7091 - if (meshNotify & 4) { meshNotifyStr.push('Disconnect'); }
7092 - if (meshNotify & 8) { meshNotifyStr.push('Intel&reg; AMT'); }
7093 - if (meshNotifyStr.length == 0) { meshNotifyStr.push('None'); }
7094 - x += addHtmlValue('Notifications', addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
7090 + if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
7091 + if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); }
7092 + if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); }
7093 + if (meshNotifyStr.length == 0) { meshNotifyStr.push("None"); }
7094 + x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
7095
7096 // Intel AMT setup
7097 - var intelAmtPolicy = 'No Policy';
7097 + var intelAmtPolicy = "No Policy";
7098 if (currentMesh.amt) {
7099 if (currentMesh.amt.type == 1) { intelAmtPolicy = 'Deactivate Client Control Mode (CCM)'; }
7100 else if (currentMesh.amt.type == 2) {
7101 - intelAmtPolicy = 'Simple Client Control Mode (CCM)';
7102 - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; }
7101 + intelAmtPolicy = "Simple Client Control Mode (CCM)";
7102 + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += " + CIRA"; }
7103 } else if (currentMesh.amt.type == 3) {
7104 - intelAmtPolicy = 'Simple Admin Control Mode (ACM)';
7105 - if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += ' + CIRA'; }
7104 + intelAmtPolicy = "Simple Admin Control Mode (ACM)";
7105 + if (currentMesh.amt.cirasetup == 2) { intelAmtPolicy += " + CIRA"; }
7106 }
7107 }
7108 - x += addHtmlValue('Intel&reg; AMT', addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1));
7108 + x += addHtmlValue("Intel&reg; AMT", addLinkConditional(intelAmtPolicy, 'p20editMeshAmt()', meshrights & 1));
7109
7110 // Display group note support
7111 - if (meshrights & 1) { x += '<br><input type=button value=Notes title="View notes about this device group" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />'; }
7111 + if (meshrights & 1) { x += '<br><input type=button value=Notes title=\"' + "View notes about this device group" + '\" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />'; }
7112
7113 x += '<br style=clear:both><br>';
7114 var currentMeshLinks = currentMesh.links[userinfo._id];
7115 - if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add Users</a>'; }
7115 + if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>'; }
7116
7117 if ((meshrights & 4) != 0) {
7118 if (currentMesh.mtype == 1) {
7119 - x += '<a href=# onclick=\'return addCiraDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Add a new Intel&reg; AMT computer that is located on the internet."><img src=images/icon-installmesh.png border=0 height=12 width=12> Install CIRA</a>';
7120 - x += '<a href=# onclick=\'return addDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Add a new Intel&reg; AMT computer that is located on the local network."><img src=images/icon-installmesh.png border=0 height=12 width=12> Install local</a>';
7119 + x += '<a href=# onclick=\'return addCiraDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel&reg; AMT computer that is located on the internet." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install CIRA" + '</a>';
7120 + x += '<a href=# onclick=\'return addDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel&reg; AMT computer that is located on the local network." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install local" + '</a>';
7121 if (currentMesh.amt && (currentMesh.amt.type == 2)) { // CCM activation
7122 - x += '<a href=# onclick=\'return showCcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Perform Intel AMT client control mode (CCM) activation."><img src=images/icon-installmesh.png border=0 height=12 width=12> Activation</a>';
7122 + x += '<a href=# onclick=\'return showCcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Perform Intel AMT client control mode (CCM) activation." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Activation" + '</a>';
7123 } else if (currentMesh.amt && (currentMesh.amt.type == 3) && ((features & 0x00100000) != 0)) { // ACM activation
7124 - x += '<a href=# onclick=\'return showAcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Perform Intel AMT admin control mode (ACM) activation."><img src=images/icon-installmesh.png border=0 height=12 width=12> Activation</a>';
7124 + x += '<a href=# onclick=\'return showAcmActivation(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Perform Intel AMT admin control mode (ACM) activation." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Activation" + '</a>';
7125 }
7126 }
7127 if (currentMesh.mtype == 2) {
7128 - x += '<a href=# onclick=\'return addAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Add a new computer to this mesh by installing the mesh agent."><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
7129 - x += '<a href=# onclick=\'return inviteAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title="Invite someone to install the mesh agent on this mesh."><img src=images/icon-addnew.png border=0 height=12 width=12> Invite</a>';
7128 + x += '<a href=# onclick=\'return addAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new computer to this mesh by installing the mesh agent." + '\"><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Install" + '</a>';
7129 + x += '<a href=# onclick=\'return inviteAgentToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Invite someone to install the mesh agent on this mesh." + '\"><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Invite" + '</a>';
7130 }
7131 }
7132
7133 - x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>User Authorizations</th><th scope=col style=text-align:left></th></tr>';
7133 + x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "User Authorizations" + '</th><th scope=col style=text-align:left></th></tr>';
7134
7135 // Sort the users for this mesh
7136 var count = 1, sortedusers = [];
@@ -7144,8 +7144,8 @@
7144
7145 // Display all users for this mesh
7146 for (var i in sortedusers) {
7147 - var trash = '', rights = 'Partial Rights', r = sortedusers[i].rights;
7148 - if (r == 0xFFFFFFFF) rights = 'Full Administrator'; else if (r == 0) rights = 'No Rights';
7147 + var trash = '', rights = "Partial Rights", r = sortedusers[i].rights;
7148 + if (r == 0xFFFFFFFF) rights = "Full Administrator"; else if (r == 0) rights = "No Rights";
7149 if ((sortedusers[i].id != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a href=# onclick=\'return p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '")\' title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
7150 x += '<tr tabindex=0 onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") onkeypress="if (event.key==\'Enter\') p20viewuser(\'' + encodeURIComponent(sortedusers[i].id) + '\')" style=cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td><div title="User" class=m2></div><div>&nbsp;' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
7151 ++count;
@@ -7154,7 +7154,7 @@
7154 x += '</tbody></table>';
7155
7156 // If we are full administrator on this mesh, allow deletion of the mesh
7157 - if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:x-small;text-align:right><span><a href=# onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Group</a></span></div>'; }
7157 + if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:x-small;text-align:right><span><a href=# onclick=p20showDeleteMeshDialog() style=cursor:pointer>' + "Delete Group" + '</a></span></div>'; }
7158
7159 QH('p20info', x);
7160 }
@@ -7162,11 +7162,11 @@
7162 function p20editMeshAmt() {
7163 if (xxdialogMode) return;
7164 var x = '', acmoption = '';
7165 - if ((features & 0x100000) != 0) { acmoption = '<option value=3>Simple Admin Control Mode (ACM)</option>'; }
7165 + if ((features & 0x100000) != 0) { acmoption = '<option value=3>' + "Simple Admin Control Mode (ACM)" + '</option>'; }
7166 if (currentMesh.mtype == 1) {
7167 - x += addHtmlValue('Type', '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>No Policy</option><option value=2>Simple Client Control Mode (CCM)</option>' + acmoption + '</select>');
7167 + x += addHtmlValue("Type", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "No Policy" + '</option><option value=2>' + "Simple Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
7168 } else {
7169 - x += addHtmlValue('Type', '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>No Policy</option><option value=1>Deactivate Client Control Mode (CCM)</option><option value=2>Simple Client Control Mode (CCM)</option>' + acmoption + '</select>');
7169 + x += addHtmlValue("Type", '<select id=dp20amtpolicy style=width:230px onchange=p20editMeshAmtChange()><option value=0>' + "No Policy" + '</option><option value=1>' + "Deactivate Client Control Mode (CCM)" + '</option><option value=2>' + "Simple Client Control Mode (CCM)" + '</option>' + acmoption + '</select>');
7170 }
7171 x += '<div id=dp20amtpolicydiv></div>';
7172 setDialogMode(2, "Intel&reg; AMT Policy", 3, p20editMeshAmtEx, x);
@@ -7186,23 +7186,23 @@
7186 function p20editMeshAmtChange() {
7187 var ptype = Q('dp20amtpolicy').value, x = '';
7188 if (ptype >= 2) {
7189 - x = addHtmlValue('Password*', '<input id=dp20amtpolicypass type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
7190 - x += addHtmlValue('Password*', '<input id=dp20amtpolicypass2 type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
7191 - if ((ptype == 2) && (currentMesh.mtype == 2)) { x += addHtmlValue('Password mismatch', "<select id=dp20amtbadpass style=width:230px><option value=0>Do nothing</option><option value=1>Reactivate Intel&reg; AMT</option></select>"); }
7189 + x = addHtmlValue("Password*", '<input id=dp20amtpolicypass type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
7190 + x += addHtmlValue("Password*", '<input id=dp20amtpolicypass2 type=password style=width:230px maxlength=32 onchange=dp20amtValidatePolicy() onkeyup=dp20amtValidatePolicy() autocomplete=off />')
7191 + if ((ptype == 2) && (currentMesh.mtype == 2)) { x += addHtmlValue("Password mismatch", '<select id=dp20amtbadpass style=width:230px><option value=0>' + "Do nothing" + '</option><option value=1>' + "Reactivate Intel&reg; AMT" + '</option></select>'); }
7192 if ((features & 0x400) == 0) {
7193 if (ptype == 2) {
7194 - x += addHtmlValue('<span title="Client Initiated Remote Access">CIRA</span>', "<select id=dp20amtcira style=width:230px><option value=0>Don't configure</option><option value=1>Don't connect to server</option><option value=2>Connect to server</option></select>");
7194 + x += addHtmlValue('<span title="' + "Client Initiated Remote Access" + '">' + "CIRA" + '</span>', '<select id=dp20amtcira style=width:230px><option value=0>' + "Don\'t configure" + '</option><option value=1>' + "Don\'t connect to server" + '</option><option value=2>' + "Connect to server" + '</option></select>');
7195 } else {
7196 - x += addHtmlValue('<span title="Client Initiated Remote Access">CIRA</span>', "<select id=dp20amtcira style=width:230px><option value=0>Don't configure</option><option value=2>Connect to server</option></select>");
7196 + x += addHtmlValue('<span title="' + "Client Initiated Remote Access" + '">' + "CIRA" + '</span>', '<select id=dp20amtcira style=width:230px><option value=0>' + "Don\'t configure" + '</option><option value=2>' + "Connect to server" + '</option></select>');
7197 }
7198 }
7199 - x += '<br/><span style="font-size:10px">* Leave blank to assign a random password to each device.</span><br/>';
7199 + x += '<br/><span style="font-size:10px">' + "* Leave blank to assign a random password to each device." + '</span><br/>';
7200 if (currentMesh.mtype == 2) {
7201 if (ptype == 2) {
7202 - x += '<span style="font-size:10px">This policy will not impact devices with Intel&reg; AMT in ACM mode.</span><br/>';
7203 - x += '<span style="font-size:10px">This is not a secure policy as agents will be performing activation.</span>';
7202 + x += '<span style="font-size:10px">' + "This policy will not impact devices with Intel&reg; AMT in ACM mode." + '</span><br/>';
7203 + x += '<span style="font-size:10px">' + "This is not a secure policy as agents will be performing activation." + '</span>';
7204 } else {
7205 - x += '<span style="font-size:10px">During activation, the agent will have access to admin password infomation.</span>';
7205 + x += '<span style="font-size:10px">' + "During activation, the agent will have access to admin password infomation." + '</span>';
7206 }
7207 }
7208 }
@@ -7234,8 +7234,8 @@
7234
7235 function p20showDeleteMeshDialog() {
7236 if (xxdialogMode) return false;
7237 - var x = "Are you sure you want to delete group \"" + EscapeHtml(currentMesh.name) + "\"? Deleting the device group will also delete all information about devices within this group.<br /><br />";
7238 - x += "<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />Confirm</label>";
7237 + var x = format("Are you sure you want to delete group {0}? Deleting the device group will also delete all information about devices within this group.", EscapeHtml(currentMesh.name)) + '<br /><br />';
7238 + x += '<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />' + "Confirm" + '</label>';
7239 setDialogMode(2, "Delete Group", 3, p20showDeleteMeshDialogEx, x);
7240 p20validateDeleteMeshDialog();
7241 return false;
@@ -7272,16 +7272,16 @@
7272 function p20editmeshconsent() {
7273 if (xxdialogMode) return;
7274 var x = '', consent = (currentMesh.consent) ? currentMesh.consent : 0;
7275 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px"><b>Desktop</b></div>';
7276 - x += "<div><label><input type=checkbox id=d20flag1 " + ((consent & 0x0001) ? 'checked' : '') + ">Notify user</label></div>";
7277 - x += "<div><label><input type=checkbox id=d20flag2 " + ((consent & 0x0008) ? 'checked' : '') + ">Prompt for user consent</label></div>";
7278 - if (debugmode) { x += "<div><label><input type=checkbox id=d20flag7 " + ((consent & 0x0040) ? 'checked' : '') + ">Show connection toolbar</label></div>"; }
7279 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>Terminal</b></div>';
7280 - x += "<div><label><input type=checkbox id=d20flag3 " + ((consent & 0x0002) ? 'checked' : '') + ">Notify user</label></div>";
7281 - x += "<div><label><input type=checkbox id=d20flag4 " + ((consent & 0x0010) ? 'checked' : '') + ">Prompt for user consent</label></div>";
7282 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>Files</b></div>';
7283 - x += "<div><label><input type=checkbox id=d20flag5 " + ((consent & 0x0004) ? 'checked' : '') + ">Notify user</label></div>";
7284 - x += "<div><label><input type=checkbox id=d20flag6 " + ((consent & 0x0020) ? 'checked' : '') + ">Prompt for user consent</label></div>";
7275 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px"><b>' + "Desktop" + '</b></div>';
7276 + x += "<div><label><input type=checkbox id=d20flag1 " + ((consent & 0x0001) ? 'checked' : '') + '>' + "Notify user" + '</label></div>';
7277 + x += "<div><label><input type=checkbox id=d20flag2 " + ((consent & 0x0008) ? 'checked' : '') + '>' + "Prompt for user consent" + '</label></div>';
7278 + if (debugmode) { x += "<div><label><input type=checkbox id=d20flag7 " + ((consent & 0x0040) ? 'checked' : '') + '>' + "Show connection toolbar" + '</label></div>'; }
7279 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>' + "Terminal" + '</b></div>';
7280 + x += "<div><label><input type=checkbox id=d20flag3 " + ((consent & 0x0002) ? 'checked' : '') + '>' + "Notify user" + '</label></div>';
7281 + x += "<div><label><input type=checkbox id=d20flag4 " + ((consent & 0x0010) ? 'checked' : '') + '>' + "Prompt for user consent" + '</label></div>';
7282 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:8px"><b>' + "Files" + '</b></div>';
7283 + x += "<div><label><input type=checkbox id=d20flag5 " + ((consent & 0x0004) ? 'checked' : '') + '>' + "Notify user" + '</label></div>';
7284 + x += "<div><label><input type=checkbox id=d20flag6 " + ((consent & 0x0020) ? 'checked' : '') + '>' + "Prompt for user consent" + '</label></div>';
7285 setDialogMode(2, "Edit Device Group User Consent", 3, p20editmeshconsentEx, x);
7286 if (serverinfo.consent) {
7287 if (serverinfo.consent & 0x0001) { Q('d20flag1').checked = true; }
@@ -7316,8 +7316,8 @@
7316 function p20editmeshfeatures() {
7317 if (xxdialogMode) return;
7318 var flags = (currentMesh.flags)?currentMesh.flags:0;
7319 - var x = "<div><label><input type=checkbox id=d20flag1 " + ((flags & 1) ? 'checked' : '') + ">Remove device on disconnect</label><br></div>";
7320 - x += "<div><label><input type=checkbox id=d20flag2 " + ((flags & 2) ? 'checked' : '') + ">Sync server device name to hostname</label><br></div>";
7319 + var x = '<div><label><input type=checkbox id=d20flag1 ' + ((flags & 1) ? 'checked' : '') + '>Remove device on disconnect</label><br></div>';
7320 + x += '<div><label><input type=checkbox id=d20flag2 ' + ((flags & 2) ? 'checked' : '') + '>Sync server device name to hostname</label><br></div>';
7321 setDialogMode(2, "Edit Device Group Features", 3, p20editmeshfeaturesEx, x);
7322 }
7323
@@ -7334,34 +7334,34 @@
7334 if (userid == null) {
7335 x += "Allow users to manage this device group and devices in this group.";
7336 if (features & 0x00080000) { x += " Users need to login to this server once before they can be added to a device group." }
7337 - x += "<br /><br /><div style='position:relative'>";
7338 - x += addHtmlValue('User Names', '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() placeholder="user1, user2, user3" />');
7339 - x += "<div id=dp20usersuggest class=suggestionBox style='top:30px;left:130px;display:none'></div>";
7337 + x += '<br /><br /><div style=\'position:relative\'>';
7338 + x += addHtmlValue("User Names", '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() placeholder="user1, user2, user3" />');
7339 + x += '<div id=dp20usersuggest class=suggestionBox style=\'top:30px;left:130px;display:none\'></div>';
7340 x += '</div><br>';
7341 } else {
7342 userid = decodeURIComponent(userid);
7343 var uname = userid.split('/')[2];
7344 if (users && users[userid]) { uname = users[userid].name; }
7345 if (userinfo._id == userid) { uname = userinfo.name; }
7346 - x += "Group permissions for user " + uname + ".<br /><br />";
7346 + x += format("Group permissions for user {0}.", uname) + '<br /><br />';
7347 }
7348 x += '<div style="height:120px;overflow-y:scroll;border:1px solid gray">';
7349 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator</label><br>';
7350 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Device Group</label><br>';
7351 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>Manage Device Group Users</label><br>';
7352 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>Manage Device Group Computers</label><br>';
7353 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>Remote Control</label><br>';
7354 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>Remote View Only</label><br>';
7355 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>Limited Input Only</label><br>';
7356 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>No Terminal Access</label><br>';
7357 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>No File Access</label><br>';
7358 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>No Intel&reg; AMT</label><br>';
7359 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console</label><br>';
7360 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Server Files</label><br>';
7361 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices</label><br>';
7362 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes</label><br>';
7363 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>Show Only Own Events</label><br>';
7364 - x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>Chat & Notify</label><br>';
7349 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>' + "Full Administrator" + '</label><br>';
7350 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>' + "Edit Device Group" + '</label><br>';
7351 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "Manage Device Group Users" + '</label><br>';
7352 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "Manage Device Group Computers" + '</label><br>';
7353 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Remote Control" + '</label><br>';
7354 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "Remote View Only" + '</label><br>';
7355 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "Limited Input Only" + '</label><br>';
7356 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>' + "No Terminal Access" + '</label><br>';
7357 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>' + "No File Access" + '</label><br>';
7358 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>' + "No Intel&reg; AMT" + '</label><br>';
7359 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>' + "Mesh Agent Console" + '</label><br>';
7360 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>' + "Server Files" + '</label><br>';
7361 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>' + "Wake Devices" + '</label><br>';
7362 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Edit Device Notes" + '</label><br>';
7363 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Show Only Own Events" + '</label><br>';
7364 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Notify" + '</label><br>';
7365 x += '</div>';
7366 if (userid == null) {
7367 setDialogMode(2, "Add Users to Device Group", 3, p20showAddMeshUserDialogEx, x);
@@ -7494,33 +7494,32 @@
7494 if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) {
7495 p20showAddMeshUserDialog(userid);
7496 } else {
7497 - var r = ''
7498 - if (meshrights == 0xFFFFFFFF) r = ', Full Administrator (all rights)'; else {
7499 - if ((meshrights & 1) != 0) r += ', Edit Device Group';
7500 - if ((meshrights & 2) != 0) r += ', Manage Device Group Users';
7501 - if ((meshrights & 4) != 0) r += ', Manage Device Group Computers';
7502 - if ((meshrights & 8) != 0) r += ', Remote Control';
7503 - if ((meshrights & 16) != 0) r += ', Agent Console';
7504 - if ((meshrights & 32) != 0) r += ', Server Files';
7505 - if ((meshrights & 64) != 0) r += ', Wake Devices';
7506 - if ((meshrights & 128) != 0) r += ', Edit Notes';
7507 - if (((meshrights & 8) != 0) && (meshrights & 256) != 0) r += ', Remote View Only';
7508 - if (((meshrights & 8) != 0) && (meshrights & 512) != 0) r += ', No Terminal';
7509 - if (((meshrights & 8) != 0) && (meshrights & 1024) != 0) r += ', No Files';
7510 - if (((meshrights & 8) != 0) && (meshrights & 2048) != 0) r += ', No Intel&reg; AMT';
7511 - if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r += ', Limited Input';
7512 - if ((meshrights & 8192) != 0) r += ', Self Events Only';
7513 - if ((meshrights & 16384) != 0) r += ', Chat & Notify';
7514 - }
7515 - r = r.substring(2);
7516 - if (r == '') { r = 'No Rights'; }
7497 + var r = [];
7498 + if (meshrights == 0xFFFFFFFF) r.push("Full Administrator (all rights)"); else {
7499 + if ((meshrights & 1) != 0) r.push("Edit Device Group");
7500 + if ((meshrights & 2) != 0) r.push("Manage Device Group Users");
7501 + if ((meshrights & 4) != 0) r.push("Manage Device Group Computers");
7502 + if ((meshrights & 8) != 0) r.push("Remote Control");
7503 + if ((meshrights & 16) != 0) r.push("Agent Console");
7504 + if ((meshrights & 32) != 0) r.push("Server Files");
7505 + if ((meshrights & 64) != 0) r.push("Wake Devices");
7506 + if ((meshrights & 128) != 0) r.push("Edit Notes");
7507 + if (((meshrights & 8) != 0) && (meshrights & 256) != 0) r.push("Remote View Only");
7508 + if (((meshrights & 8) != 0) && (meshrights & 512) != 0) r.push("No Terminal");
7509 + if (((meshrights & 8) != 0) && (meshrights & 1024) != 0) r.push("No Files");
7510 + if (((meshrights & 8) != 0) && (meshrights & 2048) != 0) r.push("No Intel&reg; AMT");
7511 + if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Limited Input");
7512 + if ((meshrights & 8192) != 0) r.push("Self Events Only");
7513 + if ((meshrights & 16384) != 0) r.push("Chat & Notify");
7514 + }
7515 + if (r.length == 0) { r.push("No Rights"); }
7516 var uname = xuserid.split('/')[2];
7517 if (users && users[xuserid]) { uname = users[xuserid].name; }
7518 if (userinfo._id == xuserid) { uname = userinfo.name; }
7520 - var buttons = 1, x = addHtmlValue('User Name', EscapeHtml(decodeURIComponent(uname)));
7521 - if (xuserid.split('/')[2] != uname) { x += addHtmlValue('User Identifier', EscapeHtml(xuserid.split('/')[2])); }
7519 + var buttons = 1, x = addHtmlValue("User Name", EscapeHtml(decodeURIComponent(uname)));
7520 + if (xuserid.split('/')[2] != uname) { x += addHtmlValue("User Identifier", EscapeHtml(xuserid.split('/')[2])); }
7521
7523 - x += addHtmlValue('Permissions', r);
7522 + x += addHtmlValue("Permissions", r);
7523 if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
7524 setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, xuserid);
7525 }
@@ -7531,7 +7530,7 @@
7530 var uname = userid.split('/')[2];
7531 if (users && users[userid]) { uname = users[userid].name; }
7532 if (userinfo._id == userid) { uname = userinfo.name; }
7534 - setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + EscapeHtml(decodeURIComponent(uname)) + "?", userid);
7533 + setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, format("Confirm removal of user {0}?", EscapeHtml(decodeURIComponent(uname))), userid);
7534 }
7535 function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); return false; }
7536 function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
@@ -7596,7 +7595,7 @@
7595 }
7596 }
7597 filetreelocation = filetreelocation2; // In case we could not go down the full path, we set the new path location here.
7599 - var publicfolder = fullPath.toLowerCase().startsWith("root / " + userinfo._id + " / public");
7598 + var publicfolder = fullPath.toLowerCase().startsWith('root / ' + userinfo._id + ' / public');
7599
7600 // Sort the files
7601 var filetreexx = p5sort_files(filetreex.f);
@@ -7611,7 +7610,7 @@
7610
7611 // Figure out the date
7612 var fdatestr = '';
7614 - if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + "&nbsp;"; }
7613 + if (f.d != null) { var fdate = new Date(f.d), fdatestr = printDateTime(fdate) + '&nbsp;'; }
7614
7615 // Figure out the size
7616 var fsize = '';
@@ -7620,12 +7619,12 @@
7619 var h = '';
7620 if (f.t < 3 || f.t == 4) {
7621 var right = (f.t == 1 || f.t == 4)?p5getQuotabar(f):'', title = '';
7623 - h = "<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='" + name + "'>&nbsp;<span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + " onclick=p5folderset(\"" + encodeURIComponent(f.nx) + "\")></div><a href=# style=cursor:pointer onclick='return p5folderset(\"" + encodeURIComponent(f.nx) + "\")'>" + shortname + "</a></span></div>";
7622 + h = '<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + name + '\'>&nbsp;<span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p5folderset(\"' + encodeURIComponent(f.nx) + '\")></div><a href=# style=cursor:pointer onclick=\'return p5folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
7623 } else {
7624 var link = shortname, publiclink = '';
7626 - if (publicfolder) { publiclink = ' (<a style=cursor:pointer title=\"Display public link\" onclick=\'return p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>Link</a>)'; }
7627 - if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" download href=\"downloadfile.ashx?link=" + encodeURIComponent(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>" + publiclink; }
7628 - h = "<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='" + f.nx + "'>&nbsp;<span class=fsize>" + fdatestr + "</span><span style=float:right>" + fsize + "</span><span><div class=fileIcon" + f.t + "></div>" + link + "</span></div>";
7625 + if (publicfolder) { publiclink = ' (<a style=cursor:pointer title=\"Display public link\" onclick=\'return p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>' + "Link" + '</a>)'; }
7626 + if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" download href=\"downloadfile.ashx?link=' + encodeURIComponent(filetreelinkpath + '/' + f.nx) + '\">' + shortname + '</a>' + publiclink; }
7627 + h = '<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + f.nx + '\'>&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
7628 }
7629
7630 if (f.t < 3) { html1 += h; } else { html2 += h; }
@@ -7642,28 +7641,26 @@
7641 // Re-check all boxes if needed
7642 if (oldlinkpath == filetreelinkpath) {
7643 checkboxes = document.getElementsByName('fc');
7645 - for (var i = 0; i < checkboxes.length; i++) {
7646 - checkboxes[i].checked = (checkedBoxes.indexOf(checkboxes[i].value) >= 0);
7647 - }
7644 + for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = (checkedBoxes.indexOf(checkboxes[i].value) >= 0); }
7645 }
7646
7647 p5setActions();
7648 }
7649
7650 function getNiceSize(bytes) {
7654 - if (bytes <= 0) return 'Storage limit exceed';
7655 - if (bytes < 2048) return bytes + ' bytes remaining';
7656 - if (bytes < 2097152) return Math.round(bytes / 1024) + ' kilobytes remaining';
7657 - if (bytes < 2147483648) return Math.round(bytes / 1024 / 1024) + ' megabytes remaining';
7658 - return Math.round(bytes / 1024 / 1024 / 1024) + ' gigabytes remaining';
7651 + if (bytes <= 0) return "Storage limit exceed";
7652 + if (bytes < 2048) return format("{0} bytes remaining", bytes);
7653 + if (bytes < 2097152) return format('{0} kilobytes remaining', Math.round(bytes / 1024));
7654 + if (bytes < 2147483648) return format('{0} megabytes remaining', Math.round(bytes / 1024 / 1024));
7655 + return format('{0} gigabytes remaining', Math.round(bytes / 1024 / 1024 / 1024));
7656 }
7657
7658 function getNiceSize2(bytes) {
7662 - if (bytes <= 0) return 'None';
7663 - if (bytes < 2048) return bytes + ' b';
7664 - if (bytes < 2097152) return Math.round(bytes / 1024) + ' Kb';
7665 - if (bytes < 2147483648) return Math.round(bytes / 1024 / 1024) + ' Mb';
7666 - return Math.round(bytes / 1024 / 1024 / 1024) + ' Gb';
7659 + if (bytes <= 0) return "None";
7660 + if (bytes < 2048) return format("{0} b", bytes);
7661 + if (bytes < 2097152) return format("{0} Kb", Math.round(bytes / 1024));
7662 + if (bytes < 2147483648) return format("{0} Mb", Math.round(bytes / 1024 / 1024));
7663 + return format("{0} Gb", Math.round(bytes / 1024 / 1024 / 1024));
7664 }
7665
7666 function p5getQuotabar(f) {
@@ -7699,7 +7696,7 @@
7696 QE('p5RenameFileButton', (cc == 1) && (filetreelocation.length > 0));
7697 //QE('p5ViewFileButton', (cc == 1) && (sfc == 1) && (filetreelocation.length > 0));
7698 QE('p5SelectAllButton', tc > 0);
7702 - Q('p5SelectAllButton').value = (cc > 0 ? 'Select None' : 'Select All');
7699 + Q('p5SelectAllButton').value = (cc > 0 ? "Select None" : "Select All");
7700 QE('p5CutButton', (sfc > 0) && (cc == sfc));
7701 QE('p5CopyButton', (sfc > 0) && (cc == sfc));
7702 QE('p5PasteButton', (p5clipboard != null) && (p5clipboard.length > 0) && (filetreelocation.length > 0));
@@ -7710,12 +7707,12 @@
7707 function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
7708 function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
7709 function setupBackPointers(x) { if (x.f != null) { var fs = 0, fc = 0; for (var i in x.f) { setupBackPointers(x.f[i]); x.f[i].parent = x; if (x.f[i].s) { fs += x.f[i].s; } if (x.f[i].c) { fc += x.f[i].c; } if (x.f[i].t == 3) { fc++; } } x.s = fs; x.c = fc; } return x; }
7713 - function getFileSizeStr(size) { if (size == 1) return "1 byte"; return "" + size + " bytes"; }
7710 + function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} bytes", size); }
7711 function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); return false; }
7712 function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); return false; }
7713 function p5createfolder() { setDialogMode(2, "New Folder", 3, p5createfolderEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />'); focusTextBox('p5renameinput'); p5fileNameCheck(); }
7714 function p5createfolderEx() { meshserver.send({ action: 'fileoperation', fileop: 'createfolder', path: filetreelocation, newfolder: Q('p5renameinput').value}); }
7718 - function p5deletefile() { var cc = getFileSelCount(), rec = (getFileSelDirCount() > 0) ? "<br /><br /><label><input type=checkbox id=p5recdeleteinput>Recursive delete</label><br>" : "<input type=checkbox id=p5recdeleteinput style='display:none'>"; setDialogMode(2, "Delete", 3, p5deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?' + rec) : ('Delete selected item?' + rec)); }
7715 + function p5deletefile() { var cc = getFileSelCount(), rec = (getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p5recdeleteinput>' + "Recursive delete" + '</label><br>' : '<input type=checkbox id=p5recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Delete", 3, p5deletefileEx, (cc > 1) ? (format("Delete {0} selected items?", cc) + rec) : ("Delete selected item?" + rec)); }
7716 function p5deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(checkboxes[i].value); } } meshserver.send({ action: 'fileoperation', fileop: 'delete', path: filetreelocation, delfiles: delfiles, rec: Q('p5recdeleteinput').checked }); }
7717 function p5renamefile() { var renamefile, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = checkboxes[i].value; } } setDialogMode(2, "Rename", 3, p5renamefileEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'fileoperation', fileop: 'rename', path: filetreelocation, oldname: renamefile}); focusTextBox('p5renameinput'); p5fileNameCheck(); }
7718 function p5renamefileEx(b, t) { t.newname = Q('p5renameinput').value; meshserver.send(t); }
@@ -7738,9 +7735,9 @@
7735
7736 var p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0;
7737 function p5copyFile(cut) { var checkboxes = document.getElementsByName('fc'); p5clipboard = []; p5clipboardCut = cut, p5clipboardFolder = Clone(filetreelocation); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == "3")) { p5clipboard.push(checkboxes[i].value); } } p5updateClipview(); }
7741 - function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = 'Confim ' + (p5clipboardCut == 0?'copy':'move') + ' of ' + p5clipboard.length + ' entrie' + ((p5clipboard.length > 1)?'s':'') + ' to this location?' } setDialogMode(2, "Paste", 3, p5pasteFileEx, x); }
7738 + function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Confim {0} of {1} entrie{2} to this location?", (p5clipboardCut == 0?'copy':'move'), p5clipboard.length, ((p5clipboard.length > 1)?'s':'')) } setDialogMode(2, "Paste", 3, p5pasteFileEx, x); }
7739 function p5pasteFileEx() { meshserver.send({ action: 'fileoperation', fileop: (p5clipboardCut == 0?'copy':'move'), scpath: p5clipboardFolder, path: filetreelocation, names: p5clipboard }); p5folderup(999); if (p5clipboardCut == 1) { p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0; p5updateClipview(); } }
7743 - function p5updateClipview() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = 'Holding ' + p5clipboard.length + ' entrie' + ((p5clipboard.length > 1)?'s':'') + ' for ' + (p5clipboardCut == 0?'copy':'move') + ', <a href=# onclick="return p5clearClip()" style=cursor:pointer>Clear</a>.' } QH('p5bottomstatus', x); p5setActions(); }
7740 + function p5updateClipview() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = format("Holding {0} entrie{1} for {2}", p5clipboard.length, ((p5clipboard.length > 1)?'s':''), (p5clipboardCut == 0?"copy":"move")) + ', <a href=# onclick="return p5clearClip()" style=cursor:pointer>' + "Clear" + '</a>.' } QH('p5bottomstatus', x); p5setActions(); }
7741 function p5clearClip() { p5clipboard = null; p5clipboardFolder = null; p5clipboardCut = 0; p5updateClipview(); return false; }
7742
7743 function p5fileDragDrop(e) {
@@ -7773,7 +7770,7 @@
7770 p5PerformUpload(1, files);
7771 } else {
7772 // Otherwise, prompt for confirmation
7776 - setDialogMode(2, "Upload File", 3, p5PerformUpload, 'Upload will overwrite ' + overWriteCount + ' file' + addLetterS(overWriteCount) + '. Continue?', files);
7773 + setDialogMode(2, "Upload File", 3, p5PerformUpload, format('Upload will overwrite {0} file{1}. Continue?', overWriteCount, addLetterS(overWriteCount)), files);
7774 }
7775 }
7776
@@ -7892,7 +7889,7 @@
7889 }
7890 }
7891 if (dateHeader != null) x += '</table>';
7895 - if (x == '') x = "<br><i>No Events Found</i><br><br>";
7892 + if (x == '') x = '<br><i>' + "No Events Found" + '</i><br><br>';
7893 QH('p3events', x);
7894 }
7895
@@ -7902,9 +7899,9 @@
7899
7900 function p3showDownloadEventsDialog(mode) {
7901 if (xxdialogMode) return;
7905 - var x = 'Download the list of events with one of the file formats below.<br /><br />';
7906 - x += addHtmlValue('CSV Format', '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogCSV(' + mode + ')">eventslist.csv</a>');
7907 - x += addHtmlValue('JSON Format', '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogJSON(' + mode + ')">eventslist.json</a>');
7902 + var x = "Download the list of events with one of the file formats below." + '<br /><br />';
7903 + x += addHtmlValue("CSV Format", '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogCSV(' + mode + ')">' + "eventslist.csv" + '</a>');
7904 + x += addHtmlValue("JSON Format", '<a href=# style=cursor:pointer onclick="return p3downloadEventsDialogJSON(' + mode + ')">' + "eventslist.json" + '</a>');
7905 setDialogMode(2, "Event List Export", 1, null, x, mode);
7906 }
7907
@@ -7913,9 +7910,9 @@
7910 if (mode == 1) { eventList = currentDeviceEvents; }
7911 if (mode == 2) { eventList = events; }
7912 if (mode == 3) { eventList = currentUserEvents; }
7916 - csv = "time, type, action, user, message\r\n"
7913 + csv = "time, type, action, user, message" + '\r\n';
7914 for (var i in eventList) { csv += '\"' + eventList[i].time + '\",\"' + eventList[i].etype + '\",\"' + ((eventList[i].action != null) ? eventList[i].action : '') + '\",\"' + ((eventList[i].username != null) ? eventList[i].username : '') + '\",\"' + ((eventList[i].msg != null) ? eventList[i].msg : '') + '\"\r\n'; }
7918 - saveAs(new Blob([csv], { type: "application/octet-stream" }), "eventslist.csv");
7915 + saveAs(new Blob([csv], { type: 'application/octet-stream' }), "eventslist.csv");
7916 return false;
7917 }
7918
@@ -7925,7 +7922,7 @@
7922 if (mode == 2) { eventList = events; }
7923 if (mode == 3) { eventList = currentUserEvents; }
7924 for (var i in eventList) { r.push(events[i]); }
7928 - saveAs(new Blob([JSON.stringify(r)], { type: "application/octet-stream" }), "eventslist.json");
7925 + saveAs(new Blob([JSON.stringify(r)], { type: 'application/octet-stream' }), "eventslist.json");
7926 return false;
7927 }
7928
@@ -7954,7 +7951,7 @@
7951
7952 // Display the users using the sorted list
7953 var x = '<table class=p3usersTable cellpadding=0 cellspacing=0>', addHeader = true;
7957 - x += '<th>Name<th style=width:80px>Groups<th style=width:120px>Last&nbsp;Access<th style=width:120px>Permissions';
7954 + x += '<th>' + "Name" + '<th style=width:80px>Groups<th style=width:120px>' + "Last&nbsp;Access" + '<th style=width:120px>' + "Permissions";
7955
7956 // Online users
7957 for (var i in sortedUserIds) {
@@ -7965,7 +7962,7 @@
7962 ((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
7963 ) {
7964 if (maxUsers > 0) {
7968 - if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Online Users'; addHeader = false; }
7965 + if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>' + "Online Users"; addHeader = false; }
7966 x += addUserHtml(user, sessions);
7967 maxUsers--;
7968 } else {
@@ -7983,7 +7980,7 @@
7980 ((emailSearch != null) && ((user.email != null) && (user.email.toLowerCase().indexOf(emailSearch) >= 0))))
7981 ) {
7982 if (maxUsers > 0) {
7986 - if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>Offline Users'; addHeader = false; }
7983 + if (addHeader) { x += '<tr><td class=userTableHeader colspan=4>' + "Offline Users"; addHeader = false; }
7984 x += addUserHtml(user, sessions);
7985 maxUsers--;
7986 } else {
@@ -7992,9 +7989,9 @@
7989 }
7990 }
7991 x += '</table>';
7995 - if (hiddenUsers == 1) { x += '<br />1 more user not shown, use search box to look for users...<br />'; }
7996 - else if (hiddenUsers > 1) { x += '<br />' + hiddenUsers + ' more users not shown, use search box to look for users...<br />'; }
7997 - if (maxUsers == 100) { x += '<br />No users found.<br />'; }
7992 + if (hiddenUsers == 1) { x += '<br />' + "1 more user not shown, use search box to look for users..." + '<br />'; }
7993 + else if (hiddenUsers > 1) { x += '<br />' + format("{0} more users not shown, use search box to look for users...", hiddenUsers) + '<br />'; }
7994 + if (maxUsers == 100) { x += '<br />' + "No users found." + '<br />'; }
7995 QH('p3users', x);
7996
7997 // Update current user panel if needed
@@ -8006,16 +8003,16 @@
8003 if (sessions != null) {
8004 gray = '';
8005 if (self) {
8009 - msg = "<span style=float:right;margin-top:1px;margin-right:4px title=Chat><a href=# onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>";
8010 - msg += "<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Notify><a href=# onclick='return showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")'><img src='images/icon-notify.png' height=16 width=16 style=padding-top:2px /></a></span>";
8006 + msg = '<span style=float:right;margin-top:1px;margin-right:4px title=' + "Chat" + '><a href=# onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src=\'images/icon-chat.png\' height=16 width=16 style=padding-top:2px /></a></span>';
8007 + msg += '<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Notify><a href=# onclick=\'return showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")\'><img src=\'images/icon-notify.png\' height=16 width=16 style=padding-top:2px /></a></span>';
8008 }
8012 - if (sessions == 1) { lastAccess += '1&nbsp;session'; } else { lastAccess += sessions + '&nbsp;sessions'; }
8009 + if (sessions == 1) { lastAccess += "1&nbsp;session"; } else { lastAccess += format("{0}&nbsp;sessions", sessions); }
8010 } else {
8014 - if (user.login) { lastAccess += '<span title="Last login: ' + printDateTime(new Date(user.login * 1000)) + '">' + printDate(new Date(user.login * 1000)) + '</span>'; }
8011 + if (user.login) { lastAccess += '<span title=\"' + format("Last login: {0}", printDateTime(new Date(user.login * 1000))) + '\">' + printDate(new Date(user.login * 1000)) + '</span>'; }
8012 }
8013 if (self) { permissions += "<a href=# style=cursor:pointer onclick='return showUserAdminDialog(event,\"" + encodeURIComponent(user._id) + "\")'>"; }
8017 - if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { permissions += "Locked,&nbsp;"; }
8018 - permissions += "<span title='Server Permissions'>";
8014 + if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { permissions += "Locked" + ',&nbsp;'; }
8015 + permissions += '<span title=\'' + "Server Permissions" + '\'>';
8016
8017 var urights = user.siteadmin & (0xFFFFFFFF - 224);
8018 if ((user.siteadmin == null) || (urights == 0)) {
@@ -8047,7 +8044,6 @@
8044 // Username & email are the same
8045 username += ' <a href=# onclick=\'return doemail(event,\"' + user.email + '\")\'><img src="images/mail12.png" height=9 width=12 title="Send email to user" style="margin-top:2px" /></a>' + emailVerified;
8046 }
8050 -
8047 }
8048
8049 if ((user.otpsecret > 0) || (user.otphkeys > 0)) { username += ' <img src="images/key12.png" height=12 width=11 title="2nd factor authentication enabled" style="margin-top:2px" />'; }
@@ -8082,7 +8078,7 @@
8078 function showUserAlertDialog(e, userid) {
8079 if (xxdialogMode) return;
8080 haltEvent(e);
8085 - setDialogMode(2, "Notify " + EscapeHtml(users[decodeURIComponent(userid)].name), 3, showUserAlertDialogEx, 'Send a text notification to this user.<textarea id=d2notifyText maxlength=2048 style="width:100%;height:184px;resize:none"></textarea>', userid);
8081 + setDialogMode(2, format("Notify {0}", EscapeHtml(users[decodeURIComponent(userid)].name)), 3, showUserAlertDialogEx, "Send a text notification to this user." + '<textarea id=d2notifyText maxlength=2048 style="width:100%;height:184px;resize:none"></textarea>', userid);
8082 Q('d2notifyText').focus();
8083 return false;
8084 }
@@ -8092,13 +8088,13 @@
8088 function doemail(e, addr) {
8089 if (xxdialogMode) return false;
8090 haltEvent(e);
8095 - window.open("mailto:" + addr);
8091 + window.open('mailto:' + addr);
8092 return false;
8093 }
8094
8095 function p4batchAccountCreate() {
8096 if (xxdialogMode) return;
8101 - var x = 'Create many accounts at once by importing a JSON file with the following format:<br /><pre>[\r\n {"user":"x1","pass":"x","email":"x1@x"},\r\n {"user":"x2","pass":"x","resetNextLogin":true}\r\n]</pre><input style=width:370px type=file id=d4importFile accept=".json" onchange=p4batchAccountCreateValidate() />';
8097 + var x = "Create many accounts at once by importing a JSON file with the following format:" + '<br /><pre>[\r\n {"user":"x1","pass":"x","email":"x1@x"},\r\n {"user":"x2","pass":"x","resetNextLogin":true}\r\n]</pre><input style=width:370px type=file id=d4importFile accept=".json" onchange=p4batchAccountCreateValidate() />';
8098 setDialogMode(2, "User Account Import", 3, p4batchAccountCreateEx, x);
8099 QE('idx_dlgOkButton', false);
8100 }
@@ -8111,7 +8107,7 @@
8107 var fr = new FileReader();
8108 fr.onload = function (r) {
8109 var j = null;
8114 - try { j = JSON.parse(r.target.result); } catch (ex) { setDialogMode(2, "User Account Import", 1, null, "Invalid JSON file: " + ex + "."); return; }
8110 + try { j = JSON.parse(r.target.result); } catch (ex) { setDialogMode(2, "User Account Import", 1, null, format("Invalid JSON file: {0}.", ex)); return; }
8111 if ((j != null) && (Array.isArray(j))) {
8112 var ok = true;
8113 for (var i in j) {
@@ -8128,38 +8124,38 @@
8124
8125 function p4downloadUserInfo() {
8126 if (xxdialogMode) return;
8131 - var x = 'Download the list of users with one of the file formats below.<br /><br />';
8132 - x += addHtmlValue('CSV Format', '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoCSV()\'>userlist.csv</a>');
8133 - x += addHtmlValue('JSON Format', '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoJSON()\'>userlist.json</a>');
8127 + var x = "Download the list of users with one of the file formats below." + '<br /><br />';
8128 + x += addHtmlValue("CSV Format", '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoCSV()\'>' + "userlist.csv" + '</a>');
8129 + x += addHtmlValue("JSON Format", '<a href=# style=cursor:pointer onclick=\'return p4downloadUserInfoJSON()\'>' + "userlist.json" + '</a>');
8130 setDialogMode(2, "User List Export", 1, null, x);
8131 }
8132
8133 function p4downloadUserInfoCSV() {
8138 - var csv = "id, name, email, creation, lastlogin, groups, authfactors\r\n";
8134 + var csv = "id, name, email, creation, lastlogin, groups, authfactors" + '\r\n';
8135 for (var i in users) {
8136 var multiFactor = false, factors = [];
8137 if ((users[i].otpsecret > 0) || (users[i].otphkeys > 0)) {
8138 multiFactor = true;
8143 - if (users[i].otpsecret > 0) { factors.push('AuthApp'); }
8144 - if (users[i].otphkeys > 0) { factors.push('SecurityKey'); }
8145 - if (users[i].otpkeys > 0) { factors.push('BackupCodes'); }
8139 + if (users[i].otpsecret > 0) { factors.push("AuthApp"); }
8140 + if (users[i].otphkeys > 0) { factors.push("SecurityKey"); }
8141 + if (users[i].otpkeys > 0) { factors.push("BackupCodes"); }
8142 }
8143 csv += '\"' + users[i]._id + '\",\"' + users[i].name + '\",\"' + (users[i].email ? users[i].email : '') + '\",\"' + (users[i].creation ? new Date(users[i].creation * 1000) : '') + '\",\"' + (users[i].login ? new Date(users[i].login * 1000) : '') + '\",\"' + (users[i].groups ? users[i].groups.join(',') : '') + '\",\"' + (multiFactor ? factors.join(',') : '') + '\"\r\n';
8144 }
8149 - saveAs(new Blob([csv], { type: "application/octet-stream" }), "userlist.csv");
8145 + saveAs(new Blob([csv], { type: 'application/octet-stream' }), "userlist.csv");
8146 return false;
8147 }
8148
8149 function p4downloadUserInfoJSON() {
8150 var r = []
8151 for (var i in users) { r.push(users[i]); }
8156 - saveAs(new Blob([JSON.stringify(r)], { type: "application/octet-stream" }), "userlist.json");
8152 + saveAs(new Blob([JSON.stringify(r)], { type: 'application/octet-stream' }), "userlist.json");
8153 return false;
8154 }
8155
8156 function showUserBroadcastDialog() {
8157 if (xxdialogMode) return;
8162 - var x = 'Broadcast a message to all connected users.<textarea id=broadcastMessage value="" maxlength="256"/></textarea>';
8158 + var x = "Broadcast a message to all connected users." + '<textarea id=broadcastMessage value="" maxlength="256"/></textarea>';
8159 setDialogMode(2, "Broadcast Message", 3, showUserBroadcastDialogEx, x);
8160 Q('broadcastMessage').focus();
8161 }
@@ -8171,21 +8167,21 @@
8167 function showCreateNewAccountDialog() {
8168 if (xxdialogMode) return;
8169 var x = '';
8174 - if ((features & 0x200000) == 0) { x += addHtmlValue('Name', '<input id=p4name maxlength=64 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />'); }
8175 - x += addHtmlValue('Email', '<input id=p4email maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8176 - x += addHtmlValue('Password', '<input id=p4pass1 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8177 - x += addHtmlValue('Password', '<input id=p4pass2 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8178 - x += '<div><label><input id=p4randomPassword onchange=showCreateNewAccountDialogValidate() type=checkbox />Randomize the password.</label></div>';
8179 - x += '<div><label><input id=p4resetNextLogin onchange=showCreateNewAccountDialogValidate() type=checkbox />Force password reset on next login.</label></div>';
8170 + if ((features & 0x200000) == 0) { x += addHtmlValue("Name", '<input id=p4name maxlength=64 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />'); }
8171 + x += addHtmlValue("Email", '<input id=p4email maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8172 + x += addHtmlValue("Password", '<input id=p4pass1 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8173 + x += addHtmlValue("Password", '<input id=p4pass2 type=password maxlength=256 onchange=showCreateNewAccountDialogValidate() onkeyup=showCreateNewAccountDialogValidate() />');
8174 + x += '<div><label><input id=p4randomPassword onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Randomize the password." + '</label></div>';
8175 + x += '<div><label><input id=p4resetNextLogin onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Force password reset on next login." + '</label></div>';
8176 if (serverinfo.emailcheck) {
8181 - x += '<div><label><input id=p4verifiedEmail onchange=showCreateNewAccountDialogValidate() type=checkbox />Email is verified.</label></div>';
8182 - x += '<div><label><input id=p4invitationEmail type=checkbox />Send invitation email.</label></div>';
8177 + x += '<div><label><input id=p4verifiedEmail onchange=showCreateNewAccountDialogValidate() type=checkbox />' + "Email is verified." + '</label></div>';
8178 + x += '<div><label><input id=p4invitationEmail type=checkbox />' + "Send invitation email." + '</label></div>';
8179 }
8180
8181 if (passRequirements) {
8182 var r = [], rc = 0;
8183 for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
8188 - if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>Requirements: ' + r.join(', ') + '.</div>'; }
8184 + if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>' + format("Requirements: {0}.", r.join(', ')) + '</div>'; }
8185 }
8186
8187 setDialogMode(2, "Create Account", 3, showCreateNewAccountDialogEx, x);
@@ -8228,8 +8224,8 @@
8224 userid = decodeURIComponent(userid);
8225 var user = users[userid.toLowerCase()], groups = "";
8226 if (user.groups != null) { groups = user.groups.join(', ') }
8231 - var x = 'Enter a comma seperate list of administrative realms names.<br /><br />';
8232 - x += addHtmlValue('Realms', '<input id=dp4usergroups style=width:230px value="' + groups + '" placeholder="Name1, Name2, Name3" maxlength=256 onchange=p4validateUserGroups() onkeyup=p4validateUserGroups() />');
8227 + var x = "Enter a comma seperate list of administrative realms names." + '<br /><br />';
8228 + x += addHtmlValue("Realms", '<input id=dp4usergroups style=width:230px value="' + groups + '" placeholder=\"' + "Name1, Name2, Name3" + '\" maxlength=256 onchange=p4validateUserGroups() onkeyup=p4validateUserGroups() />');
8229 setDialogMode(2, "Administrative Realms", 3, showUserGroupDialogEx, x, user);
8230 focusTextBox('dp4usergroups');
8231 p4validateUserGroups();
@@ -8255,15 +8251,15 @@
8251 haltEvent(e);
8252 userid = decodeURIComponent(userid);
8253 var x = '<div><div id=d2AdminPermissions>';
8258 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fileaccess>Server Files</label>, <input type=number onchange=showUserAdminDialogValidate() maxlength=10 id=ua_fileaccessquota>k max, blank for default<br><hr/>';
8259 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fulladmin>Full Administrator</label><br>';
8260 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverbackup>Server Backup</label><br>';
8261 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverrestore>Server Restore</label><br>';
8262 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverupdate>Server Updates</label><br>';
8263 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_manageusers>Manage Users</label><br>';
8264 - x += '<hr/></div><label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_lockedaccount>Lock Account</label><br>';
8265 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nonewgroups>No New Device Groups</label><br>';
8266 - x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nomeshcmd>No Tools (MeshCmd/Router)</label><br>';
8254 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fileaccess>' + "Server Files" + '</label>, <input type=number onchange=showUserAdminDialogValidate() maxlength=10 id=ua_fileaccessquota>k max, blank for default<br><hr/>';
8255 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_fulladmin>' + "Full Administrator" + '</label><br>';
8256 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverbackup>' + "Server Backup" + '</label><br>';
8257 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverrestore>' + "Server Restore" + '</label><br>';
8258 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_serverupdate>' + "Server Updates" + '</label><br>';
8259 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_manageusers>' + "Manage Users" + '</label><br>';
8260 + x += '<hr/></div><label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_lockedaccount>' + "Lock Account" + '</label><br>';
8261 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nonewgroups>' + "No New Device Groups" + '</label><br>';
8262 + x += '<label><input type=checkbox onchange=showUserAdminDialogValidate() id=ua_nomeshcmd>' + "No Tools (MeshCmd/Router)" + '</label><br>';
8263 x += '</div>';
8264 var user = users[userid.toLowerCase()];
8265 setDialogMode(2, "Server Permissions", 3, showUserAdminDialogEx, x, user);
@@ -8353,51 +8349,51 @@
8349
8350 // Show user attributes
8351 var x = '<div style=min-height:80px><table style=width:100%>';
8356 - var email = user.email?EscapeHtml(user.email):'<i>Not set</i>', everify = '';
8357 - if (serverinfo.emailcheck) { everify = ((user.emailVerified == true) ? '<b style=color:green;cursor:pointer title="Email is verified">&#x2713</b> ' : '<b style=color:red;cursor:pointer title="Email not verified">&#x2717;</b> '); }
8358 - if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute('User Identifier', user._id.split('/')[2]); }
8352 + var email = user.email?EscapeHtml(user.email):'<i>' + "Not set" + '</i>', everify = '';
8353 + if (serverinfo.emailcheck) { everify = ((user.emailVerified == true) ? '<b style=color:green;cursor:pointer title=\"' + "Email is verified" + '\">&#x2713</b> ' : '<b style=color:red;cursor:pointer title=\"' + "Email not verified" + '\">&#x2717;</b> '); }
8354 + if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute("User Identifier", user._id.split('/')[2]); }
8355 if (((features & 0x200000) == 0) && ((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF))) { // If we are not site admin, we can't change a admin email.
8360 - x += addDeviceAttribute('Email', everify + "<a href=# style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
8356 + x += addDeviceAttribute("Email", everify + "<a href=# style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
8357 } else {
8362 - x += addDeviceAttribute('Email', everify + email + ' <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
8358 + x += addDeviceAttribute("Email", everify + email + ' <a href=# style=cursor:pointer onclick=\'return doemail(event,\"' + user.email + '\")\'><img class=hoverButton src="images/link1.png" /></a>');
8359 }
8364 - x += addDeviceAttribute('Server Rights', premsg + "<a href=# style=cursor:pointer onclick=\'return showUserAdminDialog(event,\"" + userid + "\")\'>" + msg.join(', ') + "</a>");
8365 - if (user.quota) x += addDeviceAttribute('Server Quota', EscapeHtml(parseInt(user.quota) / 1024) + ' k');
8366 - x += addDeviceAttribute('Creation', printDateTime(new Date(user.creation * 1000)));
8367 - if (user.login) x += addDeviceAttribute('Last Login', printDateTime(new Date(user.login * 1000)));
8368 - if (user.passchange == -1) { x += addDeviceAttribute('Password', 'Will be changed on next login.'); }
8369 - else if (user.passchange) { x += addDeviceAttribute('Password', 'Last changed: ' + printDateTime(new Date(user.passchange * 1000))); }
8360 + x += addDeviceAttribute("Server Rights", premsg + "<a href=# style=cursor:pointer onclick=\'return showUserAdminDialog(event,\"" + userid + "\")\'>" + msg.join(', ') + "</a>");
8361 + if (user.quota) x += addDeviceAttribute("Server Quota", EscapeHtml(parseInt(user.quota) / 1024) + ' k');
8362 + x += addDeviceAttribute("Creation", printDateTime(new Date(user.creation * 1000)));
8363 + if (user.login) x += addDeviceAttribute("Last Login", printDateTime(new Date(user.login * 1000)));
8364 + if (user.passchange == -1) { x += addDeviceAttribute("Password", "Will be changed on next login."); }
8365 + else if (user.passchange) { x += addDeviceAttribute("Password", format("Last changed: {0}", printDateTime(new Date(user.passchange * 1000)))); }
8366
8367 // Device Groups
8372 - var linkCount = 0, linkCountStr = '<i>None<i>';
8368 + var linkCount = 0, linkCountStr = '<i>' + "None" + '<i>';
8369 if (user.links) {
8370 for (var i in user.links) { linkCount++; }
8375 - if (linkCount == 1) { linkCountStr = '1 group'; } else if (linkCount > 1) { linkCountStr = linkCount + ' groups'; }
8371 + if (linkCount == 1) { linkCountStr = "1 group"; } else if (linkCount > 1) { linkCountStr = format("{0} groups", linkCount); }
8372 }
8377 - x += addDeviceAttribute('Device Groups', linkCountStr);
8373 + x += addDeviceAttribute("Device Groups", linkCountStr);
8374
8375 // Administrative Realms
8376 if ((userinfo.siteadmin == 0xFFFFFFFF) || (userinfo.siteadmin & 2)) {
8381 - var userGroups = '<i>None</i>';
8377 + var userGroups = '<i>' + "None" + '</i>';
8378 if (user.groups) { userGroups = ''; for (var i in user.groups) { userGroups += '<span class="tagSpan">' + user.groups[i] + '</span>'; } }
8383 - x += addDeviceAttribute('Admin Realms', addLinkConditional(userGroups, 'showUserGroupDialog(event,\"' + userid + '\")', (userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.groups == null) && (userinfo._id != user._id) && (user.siteadmin != 0xFFFFFFFF))));
8379 + x += addDeviceAttribute("Admin Realms", addLinkConditional(userGroups, 'showUserGroupDialog(event,\"' + userid + '\")', (userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.groups == null) && (userinfo._id != user._id) && (user.siteadmin != 0xFFFFFFFF))));
8380 }
8381
8382 var multiFactor = 0;
8383 if ((user.otpsecret > 0) || (user.otphkeys > 0)) {
8384 multiFactor = 1;
8385 var factors = [];
8390 - if (user.otpsecret > 0) { factors.push('Authentication App'); }
8391 - if (user.otphkeys > 0) { factors.push('Security Key'); }
8392 - if (user.otpkeys > 0) { factors.push('Backup Codes'); }
8393 - x += addDeviceAttribute('Security', '<img src="images/key12.png" height=12 width=11 title="2nd factor authentication enabled" style="margin-top:2px" /> ' + factors.join(', '));
8386 + if (user.otpsecret > 0) { factors.push("Authentication App"); }
8387 + if (user.otphkeys > 0) { factors.push("Security Key"); }
8388 + if (user.otpkeys > 0) { factors.push("Backup Codes"); }
8389 + x += addDeviceAttribute("Security", '<img src="images/key12.png" height=12 width=11 title=\"' + "2nd factor authentication enabled" + '\" style="margin-top:2px" /> ' + factors.join(', '));
8390 }
8391
8392 x += '</table></div><br />';
8393
8394 // Add action buttons
8399 - x += '<input type=button value=Notes title="View notes about this user" onclick=showNotes(false,"' + userid + '") />';
8400 - if (!self && (activeSessions > 0)) { x += '<input type=button value=Notify title="Send user notification" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
8395 + x += '<input type=button value=\"' + "Notes" + '\" title=\"' + "View notes about this user" + '\" onclick=showNotes(false,"' + userid + '") />';
8396 + if (!self && (activeSessions > 0)) { x += '<input type=button value=\"' + "Notify" + '\" title=\"' + "Send user notification" + '\" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
8397
8398 // Setup the panel
8399 QH('p30html', x);
@@ -8420,7 +8416,7 @@
8416
8417 // Update user's connection state
8418 x = '';
8423 - if (activeSessions == 1) { x = '1 active session'; } else if (activeSessions > 1) { x = activeSessions + ' active sessions'; }
8419 + if (activeSessions == 1) { x = "1 active session"; } else if (activeSessions > 1) { x = format(" active sessions", activeSessions); }
8420 QH('MainUserState', x);
8421
8422 go(30);
@@ -8434,9 +8430,9 @@
8430 function p30showUserEmailChangeDialog(event) {
8431 if (xxdialogMode) return false;
8432 var x = '';
8437 - x += addHtmlValue('Email', '<input id=dp30email style=width:230px maxlength=32 onchange=p30validateEmail() onkeyup=p30validateEmail() />');
8438 - if (serverinfo.emailcheck) { x += addHtmlValue('Status', '<select id=dp30verified style=width:230px onchange=p30validateEmail()><option value=0>Not verified</option><option value=1>Verified</option></select>'); }
8439 - setDialogMode(2, "Change Email for " + EscapeHtml(currentUser.name), 3, p30showUserEmailChangeDialogEx, x);
8433 + x += addHtmlValue("Email", '<input id=dp30email style=width:230px maxlength=32 onchange=p30validateEmail() onkeyup=p30validateEmail() />');
8434 + if (serverinfo.emailcheck) { x += addHtmlValue("Status", '<select id=dp30verified style=width:230px onchange=p30validateEmail()><option value=0>Not verified</option><option value=1>Verified</option></select>'); }
8435 + setDialogMode(2, format("Change Email for {0}", EscapeHtml(currentUser.name)), 3, p30showUserEmailChangeDialogEx, x);
8436 Q('dp30email').focus();
8437 Q('dp30email').value = (currentUser.email?currentUser.email:'');
8438 if (serverinfo.emailcheck) { Q('dp30verified').value = currentUser.emailVerified?1:0; }
@@ -8462,19 +8458,19 @@
8458 function p30showUserChangePassDialog(multiFactor) {
8459 if (xxdialogMode) return;
8460 var x = '';
8465 - x += addHtmlValue('Password', '<input id=p4pass1 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
8466 - x += addHtmlValue('Password', '<input id=p4pass2 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
8467 - if (features & 0x00010000) { x += addHtmlValue('Password hint', '<input id=p4hint type=text style=width:230px maxlength=256></input>'); }
8461 + x += addHtmlValue("Password", '<input id=p4pass1 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
8462 + x += addHtmlValue("Password", '<input id=p4pass2 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
8463 + if (features & 0x00010000) { x += addHtmlValue("Password hint", '<input id=p4hint type=text style=width:230px maxlength=256></input>'); }
8464
8465 if (passRequirements) {
8466 var r = [], rc = 0;
8467 for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
8472 - if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>Requirements: ' + r.join(', ') + '.</div>'; }
8468 + if (rc > 0) { x += '<div style=font-size:x-small;padding:6px>' + format("Requirements: {0}.", r.join(', ')) + '</div>'; }
8469 }
8470
8475 - x += '<div><label><input id=p4resetNextLogin type=checkbox />Force password reset on next login.</label></div>';
8476 - if (multiFactor == 1) { x += '<div><label><input id=p4twoFactorRemove type=checkbox />Remove all 2nd factor authentication.</label></div>'; }
8477 - setDialogMode(2, "Change Password for " + EscapeHtml(currentUser.name), 3, p30showUserChangePassDialogEx, x, multiFactor);
8471 + x += '<div><label><input id=p4resetNextLogin type=checkbox />' + "Force password reset on next login." + '</label></div>';
8472 + if (multiFactor == 1) { x += '<div><label><input id=p4twoFactorRemove type=checkbox />' + "Remove all 2nd factor authentication." + '</label></div>'; }
8473 + setDialogMode(2, format("Change Password for {0}", EscapeHtml(currentUser.name)), 3, p30showUserChangePassDialogEx, x, multiFactor);
8474 p30showUserChangePassDialogValidate();
8475 Q('p4pass1').focus();
8476 if (currentUser.passchange == -1) { Q('p4resetNextLogin').checked = true; }
@@ -8502,7 +8498,7 @@
8498
8499 function p30showDeleteUserDialog() {
8500 if (xxdialogMode) return;
8505 - setDialogMode(2, "Delete User " + EscapeHtml(currentUser.name), 3, p30showDeleteUserDialogEx, 'Confirm deletion of user ' + EscapeHtml(currentUser.name) + '?');
8501 + setDialogMode(2, format("Delete User {0}", EscapeHtml(currentUser.name)), 3, p30showDeleteUserDialogEx, format('Confirm deletion of user {0}?', EscapeHtml(currentUser.name)));
8502 }
8503
8504 function p30showDeleteUserDialogEx() {
@@ -8598,7 +8594,7 @@
8594 }
8595 }
8596 if (dateHeader != null) x += '</table>';
8601 - if (x == '') x = "<br><i>No Events Found</i><br><br>";
8597 + if (x == '') x = '<br><i>' + "No Events Found" + '</i><br><br>';
8598 QH('p31events', x);
8599 }
8600
@@ -8670,11 +8666,11 @@
8666 var h = '';
8667 if (f.t < 3) {
8668 var title = '';
8673 - h = "<div class=filelist file=999><span style=float:right title=\"" + title + "\"></span><span><div class=fileIcon" + f.t + " onclick=d3folderset(\"" + encodeURIComponent(f.nx) + "\")></div>&nbsp;<a href=# style=cursor:pointer onclick=\'return d3folderset(\"" + encodeURIComponent(f.nx) + "\")\'>" + shortname + "</a></span></div>";
8669 + h = '<div class=filelist file=999><span style=float:right title=\"' + title + '\"></span><span><div class=fileIcon' + f.t + ' onclick=d3folderset(\"' + encodeURIComponent(f.nx) + '\")></div>&nbsp;<a href=# style=cursor:pointer onclick=\'return d3folderset(\"' + encodeURIComponent(f.nx) + '\")\'>' + shortname + '</a></span></div>';
8670 } else {
8671 var link = shortname;
8672 //if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=" + encodeURIComponent(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>"; }
8677 - h = "<div class=filelist file=3><input style=float:left name=fcx class=fcb type=checkbox onchange=d3setActions() value='" + f.nx + "'>&nbsp;<span style=float:right>" + fsize + "</span><span><div class=fileIcon" + f.t + "></div>" + link + "</span></div>";
8673 + h = '<div class=filelist file=3><input style=float:left name=fcx class=fcb type=checkbox onchange=d3setActions() value="' + f.nx + '">&nbsp;<span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
8674 }
8675
8676 if (f.t < 3) { html1 += h; } else { html2 += h; }
@@ -8722,7 +8718,7 @@
8718 function drawNotifications() {
8719 var r = '';
8720 if (notifications.length == 0) {
8725 - r = '<div style=margin:5px>There are currently no notifications</div>';
8721 + r = '<div style=margin:5px>' + "There are currently no notifications" + '</div>';
8722 } else {
8723 for (var i in notifications) {
8724 var n = notifications[i];
@@ -8735,7 +8731,7 @@
8731 if (node != null) { icon = node.icon; t = '<b>' + node.name + '</b>: ' }
8732 }
8733
8738 - r += '<div title="Occured at ' + printDateTime(d) + '" id="notifyx' + n.id + '" class=notification style="cursor:pointer;border-top:1px solid ' + ((r == '') ? 'transparent' : 'orange') + '">';
8734 + r += '<div title="' + format("Occured at {0}", printDateTime(d)) + '" id="notifyx' + n.id + '" class=notification style="cursor:pointer;border-top:1px solid ' + ((r == '') ? 'transparent' : 'orange') + '">';
8735 if (icon) { r += '<div class=j' + icon + ' onclick="notificationSelected(' + n.id + ')" style=margin:5px;float:left></div>'; }
8736 r += '<div onclick="notificationDelete(' + n.id + ')" class=unselectable title="Clear this notification" style=margin:5px;float:right;color:orange><b>X</b></div><div onclick="notificationSelected(' + n.id + ')" style=margin:5px>' + t + n.text + '</div></div>';
8737 }
@@ -8807,16 +8803,16 @@
8803
8804 // If web notifications are granted, use it.
8805 var notification = null;
8810 - if (Notification && (Notification.permission == "granted")) {
8806 + if (Notification && (Notification.permission == 'granted')) {
8807 var text = n.text.split('&reg;').join('').split('<b>').join('').split('</b>').join('').split('<br />').join('\r\n'); // Clean up any HTML codes
8808 if (n.nodeid) {
8809 var node = getNodeFromId(n.nodeid);
8814 - if (node) { notification = new Notification("{{{title}}} - " + node.name, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + node.icon + '.png' }); }
8810 + if (node) { notification = new Notification('{{{title}}} - ' + node.name, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + node.icon + '.png' }); }
8811 } else {
8812 if (n.icon == null) { n.icon = 0; }
8813 var title = n.title;
8814 if (title == null) { title = ''; } else { title = ' - ' + n.title; }
8819 - notification = new Notification("{{{title}}}" + title, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + n.icon + '.png' });
8815 + notification = new Notification('{{{title}}}' + title, { tag: n.tag, body: text, icon: '/images/notify/icons128-' + n.icon + '.png' });
8816 }
8817 notification.id = n.id;
8818 notification.xtag = n.tag;
@@ -8861,13 +8857,13 @@
8857 if (typeof message.cpuavg == 'object') {
8858 var m = Math.min(message.cpuavg[0], 1);
8859 window.serverStatCpu.config.data.datasets[0].data = [m, 1 - m];
8864 - QH('serverCpuChartText', '<div style=margin-bottom:5px>CPU Load</div><div><b title="CPU load in the last minute">' + (Math.round(message.cpuavg[0] * 100.0) / 100.0) + '</b>, <b title="CPU load in the last 5 minutes">' + (Math.round(message.cpuavg[1] * 100.0) / 100.0) + '</b>, <b title="CPU load in the 15 minutes">' + (Math.round(message.cpuavg[2] * 100.0) / 100.0) + '</b></div>');
8860 + QH('serverCpuChartText', '<div style=margin-bottom:5px>CPU Load</div><div><b title=\"' + "CPU load in the last minute" + '\">' + (Math.round(message.cpuavg[0] * 100.0) / 100.0) + '</b>, <b title=\"' + "CPU load in the last 5 minutes" + '\">' + (Math.round(message.cpuavg[1] * 100.0) / 100.0) + '</b>, <b title=\"' + "CPU load in the 15 minutes" + '\">' + (Math.round(message.cpuavg[2] * 100.0) / 100.0) + '</b></div>');
8861 QS('serverCpuChartView')['display'] = 'inline-block';
8862 window.serverStatCpu.update();
8863 }
8864 if ((typeof message.totalmem == 'number') && (typeof message.freemem == 'number')) {
8865 window.serverStatMemory.config.data.datasets[0].data = [message.totalmem - message.freemem, message.freemem];
8870 - QH('serverMemoryChartText', '<div style=margin-bottom:5px>Memory</div><div><b>' + getNiceSize2(message.freemem) + '</b> free, <b>' + getNiceSize2(message.totalmem) + '</b> total</div>');
8866 + QH('serverMemoryChartText', '<div style=margin-bottom:5px>Memory</div><div><b>' + getNiceSize2(message.freemem) + '</b> ' + "free" + ', <b>' + getNiceSize2(message.totalmem) + '</b> ' + "total" + '</div>');
8867 QS('serverMemoryChartView')['display'] = 'inline-block';
8868 window.serverStatMemory.update();
8869 }
@@ -8943,7 +8939,7 @@
8939 var data, chartType = Q('p40type').value, timeAfter = pastDate(Q('p40time').value);
8940 serverTimelineConfig.options.scales.xAxes[0].time = { min: timeAfter };
8941 if (chartType == 0) { // Connections
8946 - serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = 'Connection Count';
8942 + serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = "Connection Count";
8943 data = {
8944 labels: [pastDate(0), timeAfter],
8945 datasets: [
@@ -8965,7 +8961,7 @@
8961 }
8962 }
8963 } else if (chartType == 1) { // Memory
8968 - serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = 'Megabytes';
8964 + serverTimelineConfig.options.scales.yAxes[0].scaleLabel.labelString = "Megabytes";
8965 data = {
8966 labels: [pastDate(0), timeAfter],
8967 datasets: [
@@ -9004,13 +9000,13 @@
9000 }
9001
9002 function p40downloadEvents() {
9007 - var csv = "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss\r\n";
9003 + var csv = "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss" + '\r\n';
9004 for (var i = 0; i < serverTimelineStats.length; i++) {
9005 if (serverTimelineStats[i].conn && serverTimelineStats[i].mem) {
9006 csv += new Date(serverTimelineStats[i].time) + ', ' + serverTimelineStats[i].conn.ca + ', ' + serverTimelineStats[i].conn.cu + ', ' + serverTimelineStats[i].conn.us + ', ' + serverTimelineStats[i].conn.rs + ', ' + (serverTimelineStats[i].conn.am ? serverTimelineStats[i].conn.am : '') + ', ' + serverTimelineStats[i].mem.external + ', ' + serverTimelineStats[i].mem.heapUsed + ', ' + serverTimelineStats[i].mem.heapTotal + ', ' + serverTimelineStats[i].mem.rss + '\r\n';
9007 }
9008 }
9013 - saveAs(new Blob([csv], { type: "application/octet-stream" }), "ServerStats.csv");
9009 + saveAs(new Blob([csv], { type: 'application/octet-stream' }), "ServerStats.csv");
9010 }
9011
9012 //
@@ -9031,23 +9027,23 @@
9027
9028 function setServerTracing() {
9029 var x = '';
9034 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>Core Server</b></div>';
9035 - x += "<div><label><input type=checkbox id=p41c1 " + ((serverTraceSources.indexOf('cookie') >= 0) ? 'checked' : '') + ">Cookie encoder</label></div>";
9036 - x += "<div><label><input type=checkbox id=p41c2 " + ((serverTraceSources.indexOf('dispatch') >= 0) ? 'checked' : '') + ">Message Dispatcher</label></div>";
9037 - x += "<div><label><input type=checkbox id=p41c3 " + ((serverTraceSources.indexOf('main') >= 0) ? 'checked' : '') + ">Main Server Messages</label></div>";
9038 - x += "<div><label><input type=checkbox id=p41c4 " + ((serverTraceSources.indexOf('peer') >= 0) ? 'checked' : '') + ">MeshCentral Server Peering</label></div>";
9039 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>Web Server</b></div>';
9040 - x += "<div><label><input type=checkbox id=p41c5 " + ((serverTraceSources.indexOf('web') >= 0) ? 'checked' : '') + ">Web Server</label></div>";
9041 - x += "<div><label><input type=checkbox id=p41c6 " + ((serverTraceSources.indexOf('webrequest') >= 0) ? 'checked' : '') + ">Web Server Requests</label></div>";
9042 - x += "<div><label><input type=checkbox id=p41c7 " + ((serverTraceSources.indexOf('relay') >= 0) ? 'checked' : '') + ">Web Socket Relay</label></div>";
9043 - //x += "<div><label><input type=checkbox id=p41c8 " + ((serverTraceSources.indexOf('webrelaydata') >= 0) ? 'checked' : '') + ">Traffic Relay 2 Data</label></div>";
9044 - x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>Intel AMT</b></div>';
9045 - x += "<div><label><input type=checkbox id=p41c9 " + ((serverTraceSources.indexOf('webrelay') >= 0) ? 'checked' : '') + ">Connection Relay</label></div>";
9046 - x += "<div><label><input type=checkbox id=p41c10 " + ((serverTraceSources.indexOf('mps') >= 0) ? 'checked' : '') + ">CIRA Server</label></div>";
9047 - x += "<div><label><input type=checkbox id=p41c11 " + ((serverTraceSources.indexOf('mpscmd') >= 0) ? 'checked' : '') + ">CIRA Server Commands</label></div>";
9030 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Core Server" + '</b></div>';
9031 + x += '<div><label><input type=checkbox id=p41c1 ' + ((serverTraceSources.indexOf('cookie') >= 0) ? 'checked' : '') + '>' + "Cookie encoder" + '</label></div>';
9032 + x += '<div><label><input type=checkbox id=p41c2 ' + ((serverTraceSources.indexOf('dispatch') >= 0) ? 'checked' : '') + '>' + "Message Dispatcher" + '</label></div>';
9033 + x += '<div><label><input type=checkbox id=p41c3 ' + ((serverTraceSources.indexOf('main') >= 0) ? 'checked' : '') + '>' + "Main Server Messages" + '</label></div>';
9034 + x += '<div><label><input type=checkbox id=p41c4 ' + ((serverTraceSources.indexOf('peer') >= 0) ? 'checked' : '') + '>' + "MeshCentral Server Peering" + '</label></div>';
9035 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Web Server" + '</b></div>';
9036 + x += '<div><label><input type=checkbox id=p41c5 ' + ((serverTraceSources.indexOf('web') >= 0) ? 'checked' : '') + '>' + "Web Server" + '</label></div>';
9037 + x += '<div><label><input type=checkbox id=p41c6 ' + ((serverTraceSources.indexOf('webrequest') >= 0) ? 'checked' : '') + '>' + "Web Server Requests" + '</label></div>';
9038 + x += '<div><label><input type=checkbox id=p41c7 ' + ((serverTraceSources.indexOf('relay') >= 0) ? 'checked' : '') + '>' + "Web Socket Relay" + '</label></div>';
9039 + //x += '<div><label><input type=checkbox id=p41c8 ' + ((serverTraceSources.indexOf('webrelaydata') >= 0) ? 'checked' : '') + '>' + "Traffic Relay 2 Data" + '</label></div>';
9040 + x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>' + "Intel AMT" + '</b></div>';
9041 + x += '<div><label><input type=checkbox id=p41c9 ' + ((serverTraceSources.indexOf('webrelay') >= 0) ? 'checked' : '') + '>' + "Connection Relay" + '</label></div>';
9042 + x += '<div><label><input type=checkbox id=p41c10 ' + ((serverTraceSources.indexOf('mps') >= 0) ? 'checked' : '') + '>' + "CIRA Server" + '</label></div>';
9043 + x += '<div><label><input type=checkbox id=p41c11 ' + ((serverTraceSources.indexOf('mpscmd') >= 0) ? 'checked' : '') + '>' + "CIRA Server Commands" + '</label></div>';
9044 //x += '<div style="width:100%;border-bottom:1px solid gray;margin-bottom:5px;margin-top:5px"><b>Legacy</b></div>';
9049 - //x += "<div><label><input type=checkbox id=p41c12 " + ((serverTraceSources.indexOf('swarm') >= 0) ? 'checked' : '') + ">Legacy Swarm Server</label></div>";
9050 - //x += "<div><label><input type=checkbox id=p41c13 " + ((serverTraceSources.indexOf('swarmcmd') >= 0) ? 'checked' : '') + ">Legacy Swarm Server Commands</label></div>";
9045 + //x += '<div><label><input type=checkbox id=p41c12 ' + ((serverTraceSources.indexOf('swarm') >= 0) ? 'checked' : '') + ">' + "Legacy Swarm Server" + '</label></div>";
9046 + //x += '<div><label><input type=checkbox id=p41c13 ' + ((serverTraceSources.indexOf('swarmcmd') >= 0) ? 'checked' : '') + ">' + "Legacy Swarm Server Commands" + '</label></div>";
9047 setDialogMode(2, "Server Tracing", 7, setServerTracingEx, x);
9048 }
9049
@@ -9058,9 +9054,9 @@
9054 }
9055
9056 function p41downloadServerTrace() {
9061 - var csv = "time, source, message\r\n";
9057 + var csv = "time, source, message" + '\r\n';
9058 for (var i in serverTrace) { csv += '\"' + new Date(serverTrace[i].time).toLocaleTimeString() + '\",\"' + serverTrace[i].source + '\",\"' + serverTrace[i].args.join(', ') + '\"\r\n'; }
9063 - saveAs(new Blob([csv], { type: "application/octet-stream" }), "servertrace.csv");
9059 + saveAs(new Blob([csv], { type: 'application/octet-stream' }), "servertrace.csv");
9060 return false;
9061 }
9062
@@ -9226,9 +9222,9 @@
9222
9223 // Update the web page title
9224 if ((currentNode) && (x >= 10) && (x < 20)) {
9229 - document.title = decodeURIComponent("{{{extitle}}}") + ' - ' + currentNode.name + ' - ' + meshes[currentNode.meshid].name;
9225 + document.title = decodeURIComponent('{{{extitle}}}') + ' - ' + currentNode.name + ' - ' + meshes[currentNode.meshid].name;
9226 } else {
9231 - document.title = decodeURIComponent("{{{extitle}}}");
9227 + document.title = decodeURIComponent('{{{extitle}}}');
9228 }
9229 }
9230
@@ -9236,27 +9232,26 @@
9232 function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
9233 function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
9234 function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
9239 - //function addLink(x, f) { return "<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='" + f + "'>&diams; " + x + "</a>"; }
9240 - function addLink(x, f) { return "<span tabindex=0 style=cursor:pointer;text-decoration:none onclick='" + f + "' onkeypress=\"if (event.key=='Enter') {" + f + "} \">" + x + " <img class=hoverButton src=images/link5.png></span>"; }
9235 + function addLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=\'' + f + '\' onkeypress=\"if (event.key==\'Enter\') {' + f + '} \">' + x + ' <img class=hoverButton src=images/link5.png></span>'; }
9236 function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
9237 function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
9243 - function addOption(q, t, i) { var option = document.createElement("option"); option.text = t; option.value = i; Q(q).add(option); }
9238 + function addOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; Q(q).add(option); }
9239 function passwordcheck(p) { return (p.length > 7) && (/\d/.test(p)) && (/[a-z]/.test(p)) && (/[A-Z]/.test(p)) && (/\W/.test(p)); }
9245 - function methodcheck(r) { if (r && r != null && r.Body && r.Body.ReturnValueStr != "SUCCESS") { messagebox("Call Error", r.Header.Method + ": " + r.Body.ReturnValueStr.replace("_", " ")); return true; } return false; }
9246 - function TableStart() { return "<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=200px><p><td>"; }
9247 - function TableStart2() { return "<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td>"; }
9240 + function methodcheck(r) { if (r && r != null && r.Body && r.Body.ReturnValueStr != 'SUCCESS') { messagebox("Call Error", r.Header.Method + ': ' + r.Body.ReturnValueStr.replace('_', ' ')); return true; } return false; }
9241 + function TableStart() { return '<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=200px><p><td>'; }
9242 + function TableStart2() { return '<table cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td>'; }
9243 function TableEntry(n, v) { return "<tr><td><p>" + n + "<td>" + v; }
9244 function FullTable(x, e) { var r = TableStart(); for (i in x) { if (i && x[i]) r += TableEntry(i, x[i]); } return r + TableEnd(e); }
9250 - function TableEnd(n) { return "<tr><td colspan=2><p>" + (n?n:'') + "</table>"; }
9251 - function AddButton(v, f) { return "<input type=button value='" + v + "' onclick='" + f + "' style=margin:4px>"; }
9252 - function AddButton2(v, f) { return "<input type=button value='" + v + "' onclick='" + f + "'>"; }
9253 - function AddRefreshButton(f) { return "<input type=button name=refreshbtn value=Refresh onclick='refreshButtons(false);" + f + "' style=margin:4px " + (refreshButtonsState==false?"disabled":"") + ">"; }
9254 - function MoreStart() { return "<a href=# style=cursor:pointer;color:blue id=morexxx1 onclick=QV(\"morexxx1\",false);QV(\"morexxx2\",true)>&#x25BC; More</a><div id=morexxx2 style=display:none><br><hr>"; };
9255 - function MoreEnd() { return "<a href=# style=cursor:pointer;color:blue onclick=QV(\"morexxx2\",false);QV(\"morexxx1\",true)>&#x25B2; Less</a></div>"; };
9245 + function TableEnd(n) { return '<tr><td colspan=2><p>' + (n?n:'') + '</table>'; }
9246 + function AddButton(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '" style=margin:4px>'; }
9247 + function AddButton2(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '">'; }
9248 + function AddRefreshButton(f) { return '<input type=button name=refreshbtn value=Refresh onclick="refreshButtons(false);' + f + '" style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; }
9249 + function MoreStart() { return '<a href=# style=cursor:pointer;color:blue id=morexxx1 onclick=QV(\"morexxx1\",false);QV(\"morexxx2\",true)>&#x25BC; ' + "More" + '</a><div id=morexxx2 style=display:none><br><hr>'; };
9250 + function MoreEnd() { return '<a href=# style=cursor:pointer;color:blue onclick=QV(\"morexxx2\",false);QV(\"morexxx1\",true)>&#x25B2; ' + "Less" + '</a></div>'; };
9251 function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; }
9257 - function getInstance(x, y) { for (var i in x) { if (x[i]["InstanceID"] == y) return x[i]; } return null; }
9252 + function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
9253 function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
9259 - function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
9254 + function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + '-' + g.substring(10, 12) + g.substring(8, 10) + '-' + g.substring(14, 16) + g.substring(12, 14) + '-' + g.substring(16, 20) + '-' + g.substring(20); }
9255 function getUrlVars() { var j, hash, vars = [], hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { j = hashes[i].indexOf('='); if (j > 0) { vars[hashes[i].substring(0, j)] = hashes[i].substring(j + 1, hashes[i].length); } } return vars; }
9256 //function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
9257 //function addHtmlValue(t, v) { return '<div style=height:20px><div style=float:right;width:220px><b>' + v + '</b></div><div>' + t + '</div></div>'; }
@@ -9275,9 +9270,9 @@
9270 function printDate(d) { return d.toLocaleDateString(args.locale); }
9271 function printTime(d) { return d.toLocaleTimeString(args.locale); }
9272 function printDateTime(d) { return d.toLocaleString(args.locale); }
9278 - function addDetailItem(title, value, state) {
9279 - return '<div><span style=float:right>' + value + '</span><span>' + title + '</span></div>';
9280 - }
9273 + function addDetailItem(title, value, state) { return '<div><span style=float:right>' + value + '</span><span>' + title + '</span></div>'; }
9274 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
9275 +
9276 </script>
9277 </body>
9278 </html>
views/error404.handlebars
+9 -9
@@ -57,8 +57,8 @@
57 var webPageFullScreen = true;
58 var nightMode = (getstore('_nightMode', '0') == '1');
59
60 - var terms = "{{{terms}}}";
61 - if (terms != "") { QH('column_l', decodeURIComponent(terms)); }
60 + var terms = '{{{terms}}}';
61 + if (terms != '') { QH('column_l', decodeURIComponent(terms)); }
62 QV('column_l', true);
63 userInterfaceSelectMenu();
64
@@ -94,15 +94,15 @@
94 var hide = 0;
95 //if (args.hide) { hide = parseInt(args.hide); }
96 if (webPageFullScreen == false) {
97 - QC('body').remove("menu_stack");
98 - QC('body').remove("fullscreen");
99 - QC('body').remove("arg_hide");
97 + QC('body').remove('menu_stack');
98 + QC('body').remove('fullscreen');
99 + QC('body').remove('arg_hide');
100 //if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
101 //QV('UserDummyMenuSpan', false);
102 //QV('page_leftbar', false);
103 } else {
104 - QC('body').add("fullscreen");
105 - if (hide & 16) QC('body').add("arg_hide"); // This is replacement for QV('page_leftbar', !(hide & 16));
104 + QC('body').add('fullscreen');
105 + if (hide & 16) QC('body').add('arg_hide'); // This is replacement for QV('page_leftbar', !(hide & 16));
106 //QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
107 //QV('page_leftbar', true);
108 }
@@ -117,9 +117,9 @@
117 putstore('webPageStackMenu', webPageStackMenu);
118 }
119 if (webPageStackMenu == false) {
120 - QC('body').remove("menu_stack");
120 + QC('body').remove('menu_stack');
121 } else {
122 - QC('body').add("menu_stack");
122 + QC('body').add('menu_stack');
123 //if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
124 }
125 }
views/login-mobile.handlebars
+27 -28
@@ -267,12 +267,12 @@
267 </div>
268 <script>
269 'use strict';
270 - var passhint = "{{{passhint}}}";
270 + var passhint = '{{{passhint}}}';
271 var newAccountPass = parseInt('{{{newAccountPass}}}');
272 var emailCheck = ('{{{emailcheck}}}' == 'true');
273 var features = parseInt('{{{features}}}');
274 - var passRequirements = "{{{passRequirements}}}";
275 - if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
274 + var passRequirements = '{{{passRequirements}}}';
275 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
276 var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
277 var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
278 var currentpanel = 0;
@@ -297,8 +297,8 @@
297 }
298
299 if (features & 0x200000) { // Email is username
300 - QH('loginusername', 'Email:');
301 - QH('resetAccountSpan', 'Forgot password?');
300 + QH('loginusername', "Email:");
301 + QH('resetAccountSpan', "Forgot password?");
302 QV('nuUserRow', false);
303 }
304
@@ -311,10 +311,10 @@
311 validateCreate();
312 if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
313 QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
314 - if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV("showPassHintLink", true); }
315 - QV("newAccountPass", (newAccountPass == 1));
316 - QV("resetAccountDiv", (emailCheck == true));
317 - QV("hrAccountDiv", (emailCheck == true) || (newAccountPass == 1));
314 + if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
315 + QV('newAccountPass', (newAccountPass == 1));
316 + QV('resetAccountDiv', (emailCheck == true));
317 + QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
318
319 if ('{{loginmode}}' == '4') {
320 try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
@@ -396,7 +396,7 @@
396 function go(x) {
397 currentpanel = x;
398 setDialogMode(0);
399 - QV("showPassHintLink", false);
399 + QV('showPassHintLink', false);
400 QV('loginpanel', x == 1);
401 QV('createpanel', x == 2);
402 QV('resetpanel', x == 3);
@@ -432,9 +432,9 @@
432 if (!passRequirementsEx) {
433 // No password requirements, display password strength
434 var passStrength = checkPasswordStrength(Q('apassword1').value);
435 - if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>Strong Password</b><span>'); }
436 - else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>Good Password</b><span>'); }
437 - else { QH('passWarning', '<span style=color:red><b>Weak Password</b><span>'); }
435 + if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Strong Password" + '</b><span>'); }
436 + else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Good Password" + '</b><span>'); }
437 + else { QH('passWarning', '<span style=color:red><b>' + "Weak Password" + '</b><span>'); }
438 } else {
439 // Password requirements provided, use that
440 var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
@@ -442,7 +442,7 @@
442 ok = false;
443 //QS('nuPass1').color = '#7b241c';
444 //QS('nuPass2').color = '#7b241c';
445 - QH('passWarning', '<span style=color:red><b>Password Policy</b><span>'); // TODO: Display problem hint
445 + QH('passWarning', '<span style=color:red><b>' + "Password Policy" + '</b><span>'); // TODO: Display problem hint
446 QV('passwordPolicyCallout', true);
447 QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
448 } else {
@@ -480,9 +480,9 @@
480 if (!passRequirementsEx) {
481 // No password requirements, display password strength
482 var passStrength = checkPasswordStrength(Q('rapassword1').value);
483 - if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>Strong Password</b><span>'); }
484 - else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>Good Password</b><span>'); }
485 - else { QH('rpassWarning', '<span style=color:red><b>Weak Password</b><span>'); }
483 + if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Strong Password" + '</b><span>'); }
484 + else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Good Password" + '</b><span>'); }
485 + else { QH('rpassWarning', '<span style=color:red><b>' + "Weak Password" + '</b><span>'); }
486 } else {
487 // Password requirements provided, use that
488 var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
@@ -490,7 +490,7 @@
490 ok = false;
491 QS('rnuPass1').color = '#7b241c';
492 QS('rnuPass2').color = '#7b241c';
493 - QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>'); // This is also a link to the password policy
493 + QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Password Policy" + '</b><div>'); // This is also a link to the password policy
494 QV('rpasswordPolicyCallout', true);
495 QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
496 } else {
@@ -513,21 +513,19 @@
513 setDialogMode(0);
514 var x = validateEmail(Q('remail').value);
515 QE('eresetButton', x);
516 - if ((e != null) && (e.keyCode == 13) && (x == true)) {
517 - Q('eresetButton').click();
518 - }
516 + if ((e != null) && (e.keyCode == 13) && (x == true)) { Q('eresetButton').click(); }
517 if (e != null) { haltEvent(e); }
518 }
519
520 function passwordPolicyText(pass) {
521 var policy = '<div style=text-align:left>';
522 var counts = strCount(pass);
525 - if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += 'Minimum length of ' + passRequirements.min + '<br />'; }
526 - if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += 'Maximum length of ' + passRequirements.max + '<br />'; }
527 - if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += '' + passRequirements.upper + ' upper case<br />'; }
528 - if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += '' + passRequirements.lower + ' lower case<br />'; }
529 - if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += '' + passRequirements.numeric + ' numeric<br />'; }
530 - if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += passRequirements.nonalpha + ' non-alphanumeric<br />'; }
523 + if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Minimum length of {0}", passRequirements.min) + '<br />'; }
524 + if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Maximum length of {0}", passRequirements.max) + '<br />'; }
525 + if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} upper case", passRequirements.upper) + '<br />'; }
526 + if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} lower case", passRequirements.lower) + '<br />'; }
527 + if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numeric", passRequirements.numeric) + '<br />'; }
528 + if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} non-alphanumeric", passRequirements.nonalpha) + '<br />'; }
529 policy += '</div>';
530 return policy;
531 }
@@ -621,13 +619,14 @@
619 if (((b & 8) || x) && f) f(x, t);
620 }
621
624 - function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + "px"); }
622 + function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px'); }
623 function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
624 function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
625 function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
626 function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
627 function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
628 function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
629 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
630
631 </script>
632 </body>
views/login.handlebars
+28 -27
@@ -259,15 +259,15 @@
259 </div>
260 <script>
261 'use strict';
262 - var passhint = "{{{passhint}}}";
262 + var passhint = '{{{passhint}}}';
263 var newAccountPass = parseInt('{{{newAccountPass}}}');
264 var emailCheck = ('{{{emailcheck}}}' == 'true');
265 - var passRequirements = "{{{passRequirements}}}";
265 + var passRequirements = '{{{passRequirements}}}';
266 var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
267 - if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
267 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
268 var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
269 var features = parseInt('{{{features}}}');
270 - var welcomeText = decodeURIComponent("{{{welcometext}}}");
270 + var welcomeText = decodeURIComponent('{{{welcometext}}}');
271 var currentpanel = 0;
272 var uiMode = parseInt(getstore('uiMode', '1'));
273 var webPageFullScreen = true;
@@ -299,8 +299,8 @@
299 }
300
301 if (features & 0x200000) { // Email is username
302 - QH('loginusername', 'Email:');
303 - QH('resetAccountSpan', 'Forgot password?');
302 + QH('loginusername', "Email:");
303 + QH('resetAccountSpan', "Forgot password?");
304 QV('nuUserRow', false);
305 }
306
@@ -320,10 +320,10 @@
320 validateCreate();
321 if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
322 QV('newAccountDiv', ('{{{newAccount}}}' === '1') || ('{{{newAccount}}}' === 'true')); // If new accounts are not allowed, don't display the new account link.
323 - if ((passhint != null) && (passhint.length > 0)) { QV("showPassHintLink", true); }
324 - QV("newAccountPass", (newAccountPass == 1));
325 - QV("resetAccountDiv", (emailCheck == true));
326 - QV("hrAccountDiv", (emailCheck == true) || (newAccountPass == 1));
323 + if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
324 + QV('newAccountPass', (newAccountPass == 1));
325 + QV('resetAccountDiv', (emailCheck == true));
326 + QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
327
328 if ('{{loginmode}}' == '4') {
329 try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
@@ -414,7 +414,7 @@
414 function go(x) {
415 currentpanel = x;
416 setDialogMode(0);
417 - QV("showPassHintLink", false);
417 + QV('showPassHintLink', false);
418 QV('loginpanel', x == 1);
419 QV('createpanel', x == 2);
420 QV('resetpanel', x == 3);
@@ -461,9 +461,9 @@
461 if (!passRequirementsEx) {
462 // No password requirements, display password strength
463 var passStrength = checkPasswordStrength(Q('apassword1').value);
464 - if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>Strong Password</b><span>'); }
465 - else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>Good Password</b><span>'); }
466 - else { QH('passWarning', '<span style=color:red><b>Weak Password</b><span>'); }
464 + if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "Strong Password" + '</b><span>'); }
465 + else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "Good Password" + '</b><span>'); }
466 + else { QH('passWarning', '<span style=color:red><b>' + "Weak Password" + '</b><span>'); }
467 } else {
468 // Password requirements provided, use that
469 var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
@@ -471,7 +471,7 @@
471 ok = false;
472 QS('nuPass1').color = '#7b241c';
473 QS('nuPass2').color = '#7b241c';
474 - QH('passWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>'); // This is also a link to the password policy
474 + QH('passWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Password Policy" + '</b><div>'); // This is also a link to the password policy
475 QV('passwordPolicyCallout', true);
476 QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
477 } else {
@@ -510,9 +510,9 @@
510 if (!passRequirementsEx) {
511 // No password requirements, display password strength
512 var passStrength = checkPasswordStrength(Q('rapassword1').value);
513 - if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>Strong Password</b><span>'); }
514 - else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>Good Password</b><span>'); }
515 - else { QH('rpassWarning', '<span style=color:red><b>Weak Password</b><span>'); }
513 + if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "Strong Password" + '</b><span>'); }
514 + else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "Good Password" + '</b><span>'); }
515 + else { QH('rpassWarning', '<span style=color:red><b>' + "Weak Password" + '</b><span>'); }
516 } else {
517 // Password requirements provided, use that
518 var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
@@ -520,7 +520,7 @@
520 ok = false;
521 QS('rnuPass1').color = '#7b241c';
522 QS('rnuPass2').color = '#7b241c';
523 - QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>Password Policy</b><div>'); // This is also a link to the password policy
523 + QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "Password Policy" + '</b><div>'); // This is also a link to the password policy
524 QV('rpasswordPolicyCallout', true);
525 QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
526 } else {
@@ -542,12 +542,12 @@
542 function passwordPolicyText(pass) {
543 var policy = '<div style=text-align:left>';
544 var counts = strCount(pass);
545 - if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += 'Minimum length of ' + passRequirements.min + '<br />'; }
546 - if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += 'Maximum length of ' + passRequirements.max + '<br />'; }
547 - if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += '' + passRequirements.upper + ' upper case<br />'; }
548 - if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += '' + passRequirements.lower + ' lower case<br />'; }
549 - if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += '' + passRequirements.numeric + ' numeric<br />'; }
550 - if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += passRequirements.nonalpha + ' non-alphanumeric<br />'; }
545 + if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("Minimum length of {0}", passRequirements.min) + '<br />'; }
546 + if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("Maximum length of {0}", passRequirements.max) + '<br />'; }
547 + if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0} upper case", passRequirements.upper) + '<br />'; }
548 + if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0} lower case", passRequirements.lower) + '<br />'; }
549 + if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0} numeric", passRequirements.numeric) + '<br />'; }
550 + if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0} non-alphanumeric", passRequirements.nonalpha) + '<br />'; }
551 policy += '</div>';
552 return policy;
553 }
@@ -657,9 +657,9 @@
657 if (webPageFullScreen == false) {
658 // By adding body class, it will change a style of all ellements using CSS selector
659 // No need for JS anymore and it will be consistent style for all the templates.
660 - QC('body').remove("fullscreen");
660 + QC('body').remove('fullscreen');
661 } else {
662 - QC('body').add("fullscreen");
662 + QC('body').add('fullscreen');
663 }
664 QV('body', true);
665 center();
@@ -707,6 +707,7 @@
707 function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
708 function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
709 function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
710 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
711
712 </script>
713 </body>
views/messenger.handlebars
+19 -19
@@ -55,7 +55,7 @@
55 var userMediaSupport = 0;
56 var notification = null;
57 getUserMediaSupport(function (x) { userMediaSupport = x; })
58 - var webrtcconfiguration = "{{{webrtconfig}}}";
58 + var webrtcconfiguration = '{{{webrtconfig}}}';
59 if (webrtcconfiguration == '') { webrtcconfiguration = null; } else { try { webrtcconfiguration = JSON.parse(decodeURIComponent(webrtcconfiguration)); } catch (ex) { console.log('Invalid WebRTC config: \"' + webrtcconfiguration + '\".'); webrtcconfiguration = null; } }
60
61 // File transfer state
@@ -165,10 +165,10 @@
165
166 // If web notifications are granted, use it.
167 if (Notification) { QV('notifyButton', Notification.permission != 'granted'); }
168 - if (Notification && (Notification.permission == "granted")) {
168 + if (Notification && (Notification.permission == 'granted')) {
169 if (notification != null) { notification.close(); notification = null; }
170 if (args.title) {
171 - notification = new Notification("MeshMessenger - " + args.title, { body: msg });
171 + notification = new Notification("MeshMessenger" + ' - ' + args.title, { body: msg });
172 } else {
173 notification = new Notification("MeshMessenger", { body: msg });
174 }
@@ -243,7 +243,7 @@
243
244 // Initiate the WebRTC offer or handle the offer from the peer.
245 if (startDataChannel == true) {
246 - webchannel = webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
246 + webchannel = webrtc.createDataChannel('DataChannel', {}); // { ordered: false, maxRetransmits: 2 }
247 webchannel.onmessage = function (event) { processMessage(event.data, 2); };
248 webchannel.onopen = function () { webchannel.ok = true; updateControls(); sendws({ action: 'rtcSwitch', v: 0 }); };
249 webchannel.onclose = function (event) { if (webchannel && webchannel.ok) { disconnect(); } else { hangUpButtonClick(0); } }
@@ -276,7 +276,7 @@
276
277 // Disconnect everything
278 function disconnect() {
279 - if (state > 0) { displayControl('Connection closed.'); }
279 + if (state > 0) { displayControl("Connection closed."); }
280 if (state > 1) { setTimeout(start, 500); }
281 cancelAllFileTransfers();
282 hangUpButtonClick(0, true); // Data channel
@@ -369,9 +369,9 @@
369 // File sharing button
370 function fileButtonClick() {
371 var chooser = Q('uploadFileInput');
372 - if (chooser.getAttribute("eventset") != 1) {
373 - chooser.setAttribute("eventset", "1");
374 - chooser.addEventListener("change", fileSelect, false);
372 + if (chooser.getAttribute('eventset') != 1) {
373 + chooser.setAttribute('eventset', '1');
374 + chooser.addEventListener('change', fileSelect, false);
375 }
376 chooser.value = null;
377 chooser.click();
@@ -382,7 +382,7 @@
382 if (state != 2) return;
383 var x = Q('uploadFileInput');
384 if (x.files.length > 10) {
385 - displayControl('Limit of 10 file uploads at the same time.');
385 + displayControl("Limit of 10 file uploads at the same time.");
386 } else {
387 for (var i = 0; i < x.files.length; i++) {
388 if (x.files[i].size > 0) {
@@ -400,7 +400,7 @@
400 haltEvent(e);
401 if ((state != 2) || (e.dataTransfer == null)) return;
402 if (e.dataTransfer.files.length > 10) {
403 - displayControl('Limit of 10 file uploads at the same time.');
403 + displayControl("Limit of 10 file uploads at the same time.");
404 } else {
405 for (var i = 0; i < e.dataTransfer.files.length; i++) {
406 if (e.dataTransfer.files[i].size > 0) {
@@ -515,7 +515,7 @@
515
516 // Toggle notification
517 function enableNotificationsButtonClick() {
518 - if (Notification) { Notification.requestPermission().then(function (permission) { QV('notifyButton', permission != "granted"); }); }
518 + if (Notification) { Notification.requestPermission().then(function (permission) { QV('notifyButton', permission != 'granted'); }); }
519 return false;
520 }
521
@@ -559,13 +559,13 @@
559 }
560
561 if (id == 1) {
562 - localVideo.removeAttribute("src");
563 - localVideo.removeAttribute("srcObject");
562 + localVideo.removeAttribute('src');
563 + localVideo.removeAttribute('srcObject');
564 if (localStream != null) { localStream = null; }
565 displayLocalVideo(false);
566 } else if (id == 2) {
567 - remoteVideo.removeAttribute("src");
568 - remoteVideo.removeAttribute("srcObject");
567 + remoteVideo.removeAttribute('src');
568 + remoteVideo.removeAttribute('srcObject');
569 displayRemoteVideo(false);
570 }
571
@@ -605,10 +605,10 @@
605 // Get started
606 updateControls();
607 if ((typeof args.id == 'string') && (args.id.length > 0)) {
608 - var url = window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/meshrelay.ashx?id=' + args.id;
608 + var url = window.location.protocol.replace('http', 'ws') + '//' + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/meshrelay.ashx?id=' + args.id;
609 if ((args.auth != null) && (args.auth != '')) { url += '&auth=' + args.auth; }
610 socket = new WebSocket(url);
611 - socket.onopen = function () { state = 1; displayControl('Waiting for other user...'); }
611 + socket.onopen = function () { state = 1; displayControl("Waiting for other user..."); }
612 socket.onerror = function (e) { /*console.error(e);*/ }
613 socket.onclose = function () { disconnect(); }
614 socket.onmessage = function (msg) {
@@ -616,7 +616,7 @@
616 hangUpButtonClick(0, true);
617 hangUpButtonClick(1, true);
618 hangUpButtonClick(2, true);
619 - displayControl('Connected.');
619 + displayControl("Connected.");
620 state = 2;
621 updateControls();
622 sendws({ action: 'random', random: random }); // Send a random number. Higher number starts the WebRTC session.
@@ -625,7 +625,7 @@
625 if (state == 2) { processMessage(msg.data, 1); }
626 }
627 } else {
628 - displayControl('Error: No connection key specified.');
628 + displayControl("Error: No connection key specified.");
629 }
630 }
631