Improved localization of web app.

Ylian Saint-Hilaire committed Oct 20, 2019 at 19:31 UTC d91352e0ba9cb9a58372e14531e2fecee1400b0c
2 files changed +284 -266
views/default-mobile.handlebars
+274 -255
@@ -381,7 +381,7 @@
381 <a id=DeskToolsRefreshButton style="float:right;padding:3px;cursor:pointer" onclick="refreshDeskTools()">Refresh</a>
382 <div id=DeskToolsBar style="position:absolute;padding:3px;border-radius: 3px 3px 0px 0px;top:5px;left:4px;bottom:26px;background-color:lightgray;cursor:pointer">Processes</div>
383 <div style="position:absolute;top:26px;left:4px;right:4px;bottom:4px;background-color:lightgray;text-align:left">
384 - <div style="border-bottom:1px solid darkgray;padding:3px"><a style=width:50px;padding-right:5px;float:left;cursor:pointer title="Sort by process id" onclick=sortProcess(0)>PID</a><a style=cursor:pointer title="Sort by name" onclick=sortProcess(1)>Name</a></div>
384 + <div style="border-bottom:1px solid darkgray;padding:3px"><a style=width:50px;padding-right:5px;float:left;cursor:pointer onclick=sortProcess(0)>PID</a><a style=cursor:pointer onclick=sortProcess(1)>Name</a></div>
385 <div id="DeskToolsProcesses" style="overflow-y:scroll;position:absolute;top:24px;bottom:0px;width:100%"></div>
386 </div>
387 </div>
@@ -391,16 +391,16 @@
391 <div style=padding-top:2px;padding-bottom:2px;background:#C0C0C0>
392 <div style=float:right;text-align:right>
393 <select id=termdisplays style=display:none onchange=deskSetDisplay(event) onclick=deskGetDisplayNumbers(event)></select>&nbsp;
394 - <span id=DeskToastButton title="Display a notification on the remote computer"><img src='images/icon-notify.png' onclick=deviceToastFunction() height=16 width=16 style=padding-top:2px /></span>&nbsp;
395 - <!--<input id=DeskToolsButton type=button value=Tools title="Toggle tools view" onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;-->
394 + <span id=DeskToastButton><img src='images/icon-notify.png' onclick=deviceToastFunction() height=16 width=16 style=padding-top:2px /></span>&nbsp;
395 + <!--<input id=DeskToolsButton type=button value=Tools onkeypress="return false" onkeydown="return false" onclick="toggleDeskTools()">&nbsp;-->
396 </div>
397 <div>
398 - <input id="deskActionsBtn" type=button style="margin-left:3px" title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() />
399 - <input type="button" value="Settings" title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()">
400 - <input type="button" title="Change the power state of the remote machine" onkeypress="return false" onkeydown="return false" value="Power Actions..." onclick="showPowerActionDlg()" style="display:none">
398 + <input id="deskActionsBtn" type=button style="margin-left:3px" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() />
399 + <input type="button" value="Settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()">
400 + <input type="button" onkeypress="return false" onkeydown="return false" value="Power Actions..." onclick="showPowerActionDlg()" style="display:none">
401 <input id="DeskSpecialKeys" type="button" value="Special Keys" onkeypress="return false" onkeydown="return false" onclick="sendSpecialKeys()">
402 <input id="DeskSoftKeys" type="button" value="Keyboard" onkeypress="return false" onkeydown="return false" onclick="toggleSoftKeys(1)">
403 - <label><span id="DeskControlSpan" style="display:none" title="Toggle mouse and keyboard input"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false">Input</span></label>
403 + <label><span id="DeskControlSpan" style="display:none"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false">Input</span></label>
404 </div>
405 </div>
406 </div>
@@ -410,7 +410,7 @@
410 <tr>
411 <td style="background-color:#C0C0C0;border-bottom:2px solid black;padding:2px">
412 <div style="float:right;text-align:right">
413 - <input id="filesActionsBtn" type=button title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() style=margin-right:2px />
413 + <input id="filesActionsBtn" type=button onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() style=margin-right:2px />
414 </div>
415 <div style="margin-left:2px">
416 <input id=p13AutoConnect value="AutoConnect" onclick=autoConnectFiles(event) onkeypress="return false" onkeydown="return false" type="button" style="display:none">
@@ -591,19 +591,19 @@
591 'use strict';
592
593 // Process server-side web state
594 - var webState = "{{{webstate}}}";
595 - if (webState != "") { webState = JSON.parse(decodeURIComponent(webState)); }
594 + var webState = '{{{webstate}}}';
595 + if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
596 for (var i in webState) { localStorage.setItem(i, webState[i]); }
597 if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
598
599 var args = parseUriArgs();
600 var debugLevel = parseInt('{{{debuglevel}}}');
601 var features = parseInt('{{{features}}}');
602 - var sessionTime = parseInt("{{{sessiontime}}}");
603 - var domain = "{{{domain}}}";
604 - var domainUrl = "{{{domainurl}}}";
605 - var authCookie = "{{{authCookie}}}";
606 - var authRelayCookie = "{{{authRelayCookie}}}";
602 + var sessionTime = parseInt('{{{sessiontime}}}');
603 + var domain = '{{{domain}}}';
604 + var domainUrl = '{{{domainurl}}}';
605 + var authCookie = '{{{authCookie}}}';
606 + var authRelayCookie = '{{{authRelayCookie}}}';
607 var authCookieRenewTimer = null;
608 var meshserver = null;
609 var xdr = null;
@@ -615,13 +615,13 @@
615 var serverinfo = null;
616 var users = null;
617 var nodeShortIdent = 0;
618 - var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}";
618 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
619 var debugmode = false;
620 var attemptWebRTC = ((features & 128) != 0);
621 - var StatusStrs = ['Disconnected', 'Connecting...', 'Setup...', 'Connected', 'Intel&reg; AMT Connected'];
621 + var StatusStrs = ["Disconnected", "Connecting...", "Setup...", "Connected", "Intel&reg; AMT Connected"];
622 var files;
623 - var passRequirements = "{{{passRequirements}}}";
624 - if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
623 + var passRequirements = '{{{passRequirements}}}';
624 + if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
625 var sessionActivity = Date.now();
626
627 function startup() {
@@ -637,7 +637,7 @@
637 window.onresize = center;
638 center();
639 QV('changeEmailId', (features & 0x200000) == 0);
640 - QH('p1message', 'Connecting...');
640 + QH('p1message', "Connecting...");
641 go(1);
642
643 // Connect to the mesh server
@@ -657,8 +657,8 @@
657 // Control web socket disconnected
658 setDialogMode(0); // Close any dialog boxes if present
659 go(0); // Go to disconnection panel
660 - if (errorCode == 'noauth') { QH('p0span', 'Unable to perform authentication'); return; }
661 - if (prevState == 2) { setTimeout(serverPoll, 5000); } else { QH('p0span', 'Unable to connect web socket'); }
660 + if (errorCode == 'noauth') { QH('p0span', "Unable to perform authentication"); return; }
661 + if (prevState == 2) { setTimeout(serverPoll, 5000); } else { QH('p0span', "Unable to connect web socket"); }
662 // Clean up here
663 if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
664 } else if (state == 2) {
@@ -697,10 +697,10 @@
697 if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', ' - Reset on next login.'); }
698 else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
699 var seconds = (userinfo.passchange) + (passRequirements.reset * 86400) - Math.floor(Date.now() / 1000);
700 - if (seconds < 0) { QH('p2nextPasswordUpdateTime', ' - Reset on next login.'); }
701 - else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 60) + ' minute' + addLetterS(Math.floor(seconds / 60)) + '.'); }
702 - else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 3600) + ' hour' + addLetterS(Math.floor(seconds / 3600)) + '.'); }
703 - else { QH('p2nextPasswordUpdateTime', ' - Reset in ' + Math.floor(seconds / 86400) + ' day' + addLetterS(Math.floor(seconds / 86400)) + '.'); }
700 + if (seconds < 0) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
701 + else if (seconds < 3600) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} minute{1}.", Math.floor(seconds / 60), addLetterS(Math.floor(seconds / 60)))); }
702 + else if (seconds < 86400) { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} hour{1}.", Math.floor(seconds / 3600), addLetterS(Math.floor(seconds / 3600)))); }
703 + else { QH('p2nextPasswordUpdateTime', format(" - Reset in {0} day{1}."), Math.floor(seconds / 86400), addLetterS(Math.floor(seconds / 86400))); }
704 }
705 }
706 }
@@ -792,7 +792,7 @@
792 var secret = message.secret;
793 if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
794 else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
795 - QH('d2optinfo', '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, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.<br /><br /><div style=width:100%;text-align:center><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:15px>' + secret + '</tt><br /><br />Token: <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></div>');
795 + QH('d2optinfo', "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, use <a href=\"' + message.url + '\" rel=\"noreferrer noopener\" target=_blank> this link</a> or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login." + '<br /><br /><div style=width:100%;text-align:center><tt id=d2optsecret secret=\"' + message.secret + '\" style=font-size:15px>' + secret + '</tt><br /><br />Token: <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></div>');
796 QV('idx_dlgOkButton', true);
797 QE('idx_dlgOkButton', false);
798 Q('d2otpauthinput').focus();
@@ -812,7 +812,7 @@
812 case 'otpauth-getpasswords': {
813 if (xxdialogMode) return;
814 var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
815 - 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 style=width:100%;text-align:center>";
815 + 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 style=width:100%;text-align:center>';
816 if (message.passwords) {
817 var j = 0;
818 for (var i in message.passwords) {
@@ -822,13 +822,13 @@
822 if (message.passwords[i].u === true) { x += '<td>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); } else { x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + '&nbsp;' + p.substring(4); + '</strike>'; }
823 }
824 } else {
825 - x += '<tr><td>No Active Tokens';
825 + x += '<tr><td>' + "No Active Tokens";
826 }
827 - x += "</table></div></div><br />";
828 - x += "<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>";
829 - x += "<input type=button value='New Tokens' onclick='account_manageOtp(1);'></input>";
830 - if (message.passwords != null) { x += "<input type=button value='Clear' onclick='account_manageOtp(2);'></input>"; }
831 - x += "</div><br />";
827 + x += '</table></div></div><br />';
828 + x += '<div><input type=button value=\'' + "Close" + '\' onclick=setDialogMode(0) style=float:right></input>';
829 + x += '<input type=button value=\'' + "New Tokens" + '\' onclick=\'account_manageOtp(1);\'></input>';
830 + if (message.passwords != null) { x += '<input type=button value=\'' + "Clear" + '\' onclick=\'account_manageOtp(2);\'></input>'; }
831 + x += '</div><br />';
832 setDialogMode(2, "Manage Backup Codes", 8, null, x, 'otpauth-manage');
833 break;
834 }
@@ -1149,7 +1149,7 @@
1149
1150 function account_addOtp() {
1151 if (xxdialogMode || (userinfo.otpsecret == 1) || ((features & 4096) == 0)) return;
1152 - setDialogMode(2, "Authenticator App", 2, function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); }, "<div id=d2optinfo>Loading...</div>", 'otpauth-request');
1152 + setDialogMode(2, "Authenticator App", 2, function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); }, '<div id=d2optinfo>' + "Loading..." + '</div>', 'otpauth-request');
1153 meshserver.send({ action: 'otpauth-request' });
1154 }
1155
@@ -1172,7 +1172,7 @@
1172
1173 function account_showVerifyEmail() {
1174 if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
1175 - 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.";
1175 + 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.";
1176 setDialogMode(2, "Email Verification", 3, account_showVerifyEmailEx, x);
1177 }
1178
@@ -1200,12 +1200,12 @@
1200
1201 function account_showDeleteAccount() {
1202 if (xxdialogMode) return;
1203 - var x = "<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=" + authCookie + " /><tr>";
1204 - x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
1205 - 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>";
1203 + var x = '<form method=post><table style=margin-left:10px><input type=hidden name=action value=deleteaccount /><input type=hidden name=authcookie value=' + authCookie + ' /><tr>';
1204 + x += '<td align=right>' + "Password:" + '</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>';
1205 + 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>';
1206 x += '</tr></table><div style=padding:10px;margin-bottom:4px>';
1207 - x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
1208 - x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
1207 + x += '<input id=account_dlgCancelButton type=button value=\"' + "Cancel" + '\" style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
1208 + x += '<input id=account_dlgOkButton type=submit value=\"' + "OK" + '\" style="float:right;width:80px" onclick=dialogclose(1)>';
1209 x += '</div><br /></form>';
1210 setDialogMode(2, "Delete Account", 0, null, x);
1211 account_validateDeleteAccount();
@@ -1216,15 +1216,15 @@
1216 function account_showChangePassword() {
1217 if (xxdialogMode) return false;
1218 var x = "<table style=margin-left:10px>";
1219 - x += "<tr><td align=right>Old&nbsp;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>";
1220 - x += "<tr><td align=right>New&nbsp;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>";
1221 - x += "<tr><td align=right>New&nbsp;password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>";
1222 - 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>"; }
1219 + x += '<tr><td align=right>' + "Old&nbsp;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>';
1220 + x += '<tr><td align=right>' + "New&nbsp;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>';
1221 + x += '<tr><td align=right>' + "New&nbsp;password:" + '</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() onkeydown=account_validateNewPassword() /></td></tr>';
1222 + 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>'; }
1223 x += '</table>'
1224 if (passRequirements) {
1225 var r = [], rc = 0;
1226 for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
1227 - if (rc > 0) { x += '<br /><span style=font-size:x-small>Requirements: ' + r.join(', ') + '.</span>'; }
1227 + if (rc > 0) { x += '<br /><span style=font-size:x-small>' + format("Requirements: {0}.", r.join(', ')) + '</span>'; }
1228 }
1229 x += '<br />';
1230 setDialogMode(2, "Change Password", 3, account_showChangePasswordEx, x);
@@ -1254,9 +1254,9 @@
1254 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\" and look at the \"Account Security\" section."); return; }
1255
1256 // We are allowed, let's prompt to information
1257 - var x = addHtmlValue('Name', '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
1258 - x += addHtmlValue('Type', '<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>Software Agent Group</option><option value=1>Intel&reg; AMT only</option></select></div>');
1259 - x += addHtmlValue('Description', '<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
1257 + var x = addHtmlValue("Name", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
1258 + x += addHtmlValue("Type", '<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>' + "Software Agent Group" + '</option><option value=1>' + "Intel&reg; AMT only" + '</option></select></div>');
1259 + x += addHtmlValue("Description", '<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
1260 setDialogMode(2, "Create Device Group", 3, account_createMeshEx, x);
1261 account_validateMeshCreate();
1262 Q('dp3meshname').focus();
@@ -1285,7 +1285,7 @@
1285 } else {
1286 // Password requirements provided, use that
1287 var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
1288 - if (passReq == false) { ok = false; r = '<span style=color:red>Policy<span>' }
1288 + if (passReq == false) { ok = false; r = '<span style=color:red>' + "Policy" + '<span>' }
1289 }
1290 }
1291 QH('dxPassWarn', r);
@@ -1328,8 +1328,8 @@
1328
1329 // Mesh rights
1330 var meshrights = meshes[i].links[userinfo._id].rights;
1331 - var rights = 'Partial Rights';
1332 - if (meshrights == 0xFFFFFFFF) rights = 'Full Administrator'; else if (meshrights == 0) rights = 'No Rights';
1331 + var rights = "Partial Rights";
1332 + if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights";
1333
1334 // Print the mesh information
1335 r += '<div style=cursor:pointer onclick=goForward(\'' + i + '\')>';
@@ -1350,31 +1350,6 @@
1350 go(20);
1351 }
1352
1353 - function server_showRestoreDlg() {
1354 - if (xxdialogMode) return;
1355 - 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 />';
1356 - x += '<form action="/restoreserver.ashx" enctype="multipart/form-data" method="post"><div>';
1357 - 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()>';
1358 - x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
1359 - x += '<input id=account_dlgOkButton type=submit value=OK style=float:right;width:80px onclick=dialogclose(1)>';
1360 - x += '</div><br /><br /></form>';
1361 - setDialogMode(2, "Restore Server", 0, null, x);
1362 - account_validateServerRestore();
1363 - }
1364 -
1365 - function account_validateServerRestore() {
1366 - QE('account_dlgOkButton', Q('account_dlgFileInput').files.length == 1);
1367 - }
1368 -
1369 - function server_showVersionDlg() {
1370 - if (xxdialogMode) return;
1371 - setDialogMode(2, "MeshCentral Version", 1, null, "Loading...", 'MeshCentralServerUpdate');
1372 - meshserver.send({ action: 'serverversion' });
1373 - }
1374 -
1375 - function server_showVersionDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
1376 - function server_showVersionDlgEx() { meshserver.send({ action: 'serverupdate' }); }
1377 -
1353 //
1354 // MY FILES
1355 //
@@ -1387,7 +1362,7 @@
1362 function updateFiles() {
1363 QV('MainMenuMyFiles', ((features & 8) == 0));
1364 if ((features & 8) != 0) return; // If running on a server without files, exit now.
1390 - var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p5folderup(0)>Root</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
1365 + var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p5folderup(0)>' + "Root" + '</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
1366
1367 // Navigate to path location, build the paths at the same time
1368 var filetreelocation2 = [], oldlinkpath = filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');
@@ -1414,7 +1389,7 @@
1389 }
1390 }
1391 filetreelocation = filetreelocation2; // In case we could not go down the full path, we set the new path location here.
1417 - var publicfolder = fullPath.toLowerCase().startsWith("root / " + userinfo._id + " / public");
1392 + var publicfolder = fullPath.toLowerCase().startsWith('root / ' + userinfo._id + ' / public');
1393
1394 // Sort the files
1395 var filetreexx = p5sort_files(filetreex.f);
@@ -1424,7 +1399,7 @@
1399 // Figure out the name and shortname
1400 var f = filetreexx[i], name = f.n, shortname;
1401 shortname = name;
1427 - if (name.length > 40) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 40)) + "...</span>"; } else { shortname = EscapeHtml(name); }
1402 + if (name.length > 40) { shortname = EscapeHtml(name.substring(0, 40)) + "..."; } else { shortname = EscapeHtml(name); }
1403 name = EscapeHtml(name);
1404
1405 // Figure out the date
@@ -1437,14 +1412,14 @@
1412
1413 var h = '';
1414 if (f.t < 3 || f.t == 4) {
1440 - var right = (f.t == 1 || f.t == 4) ? p5getQuotabar(f) : '', title = '';
1441 - 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;padding-right:4px title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + "></div><a style=cursor:pointer onclick=p5folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
1415 + var right = (f.t == 1 || f.t == 4) ? p5getQuotabar(f) : '';
1416 + 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;padding-right:4px>' + right + "</span><span><div class=fileIcon" + f.t + '></div><a style=cursor:pointer onclick=p5folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
1417 } else {
1418 var link = shortname;
1419 var publiclink = '';
1445 - if (publicfolder) { publiclink = ' (<a style=cursor:pointer title=\"Display public link\" onclick=\'p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>Link</a>)'; }
1446 - if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=" + encodeURIComponent(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>" + publiclink; }
1447 - 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 style=float:right;padding-right:4px>" + fsize + "</span><span><div class=fileIcon" + f.t + "></div>" + link + "</span></div>";
1420 + if (publicfolder) { publiclink = ' (<a style=cursor:pointer onclick=\'p5showPublicLink(\"' + publicPath + '/' + f.nx + '\")\'>' + "Link" + '</a>)'; }
1421 + if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=' + encodeURIComponent(filetreelinkpath + '/' + f.nx) + '\">' + shortname + '</a>' + publiclink; }
1422 + 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 style=float:right;padding-right:4px>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
1423 }
1424
1425 if (f.t < 3) { html1 += h; } else { html2 += h; }
@@ -1472,8 +1447,7 @@
1447 function p5getQuotabar(f) {
1448 while (f.t > 1 && f.t != 4) { f = f.parent; }
1449 if ((f.t != 1 && f.t != 4) || (f.maxbytes == null)) return '';
1475 - var tf = Math.floor(f.s / 1024), tq = Math.floor((f.maxbytes - f.s) / 1024);
1476 - return '<span title="' + tf + "k in " + f.c + " file" + (f.c > 1 ? 's' : '') + ". " + (Math.floor(f.maxbytes / 1024)) + 'k maxinum">' + ((tq < 0) ? ('Storage limit exceed') : (tq + 'k remaining')) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' /></span>';
1450 + return getNiceSize(tq) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' />';
1451 }
1452
1453 function p5showPublicLink(u) { setDialogMode(2, "Public Link", 1, null, '<input type=text style=width:100% value="' + u + '" readonly />'); }
@@ -1501,31 +1475,33 @@
1475 QE('p5UploadButton', filetreelocation.length > 0);
1476 QE('p5RenameFileButton', (cc == 1) && (filetreelocation.length > 0));
1477 QE('p5SelectAllButton', tc > 0);
1504 - Q('p5SelectAllButton').value = (cc > 0 ? 'None' : 'All');
1478 + Q('p5SelectAllButton').value = (cc > 0 ? "None" : "All");
1479 QE('p5CutButton', (sfc > 0) && (cc == sfc));
1480 QE('p5CopyButton', (sfc > 0) && (cc == sfc));
1481 QE('p5PasteButton', (p5clipboard != null) && (p5clipboard.length > 0) && (filetreelocation.length > 0));
1482 }
1483
1510 - function getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
1484 + function getFileSelCount(includeDirs) { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
1485 + function getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
1486 function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
1487 function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
1488 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; }
1514 - function getFileSizeStr(size) { if (size == 1) return "1 byte"; return "" + size + " bytes"; }
1515 - function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); }
1516 - function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); }
1489 + function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} bytes", size); }
1490 + function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); return false; }
1491 + function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); return false; }
1492 function p5createfolder() { setDialogMode(2, "New Folder", 3, p5createfolderEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />'); focusTextBox('p5renameinput'); p5fileNameCheck(); }
1493 function p5createfolderEx() { meshserver.send({ action: 'fileoperation', fileop: 'createfolder', path: filetreelocation, newfolder: Q('p5renameinput').value }); }
1519 - function p5deletefile() { var cc = getFileSelCount(); setDialogMode(2, "Delete", 3, p5deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?') : ('Delete selected item?')); }
1520 - 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 }); }
1494 + 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)); }
1495 + 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 }); }
1496 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(); }
1497 function p5renamefileEx(b, t) { t.newname = Q('p5renameinput').value; meshserver.send(t); }
1523 - function p5fileNameCheck(e) { var x = isFilenameValid(Q('p5renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e.keyCode == 13)) { dialogclose(1); } }
1498 + function p5fileNameCheck(e) { var x = isFilenameValid(Q('p5renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e && e.keyCode == 13)) { dialogclose(1); } }
1499 var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
1525 - function p5uploadFile() { setDialogMode(2, "Upload File", 3, p5uploadFileEx, '<form method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input type=text name=link style=display:none id=p5uploadpath value=\"' + encodeURIComponent(filetreelinkpath) + '\" /><input type=file name=files id=p5uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p5uploadinput\')" /><input type=submit id=p5loginSubmit style=display:none /></form>'); updateUploadDialogOk('p5uploadinput'); }
1500 + function p5uploadFile() { setDialogMode(2, "Upload File", 3, p5uploadFileEx, '<form method=post enctype=multipart/form-data action=uploadfile.ashx target=fileUploadFrame><input type=text name=link style=display:none id=p5uploadpath value=\"' + encodeURIComponent(filetreelinkpath) + '\" /><input type=file name=files id=p5uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p5uploadinput\')" /><input type=hidden name=authCookie value=' + authCookie + ' /><input type=submit id=p5loginSubmit style=display:none /></form>'); updateUploadDialogOk('p5uploadinput'); }
1501 function p5uploadFileEx() { Q('p5loginSubmit').click(); }
1502 function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
1503
1504 +
1505 var p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0;
1506 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(); }
1507 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); }
@@ -1573,12 +1549,12 @@
1549
1550 function p5fileDragLeave(e) {
1551 haltEvent(e);
1576 - if (e.target.id != "p5filetable") {
1552 + if (e.target.id != 'p5filetable') {
1553 QV('bigfail', false);
1554 QV('bigok', false);
1555 //QV('p5fileCatchAllInput', false);
1556 } else {
1581 - p5dragtimer = setTimeout("QV('bigfail',false);QV('bigok',false);p5dragtimer=null;", 200);
1557 + p5dragtimer = setTimeout('QV(\'bigfail\',false);QV(\'bigok\',false);p5dragtimer=null;', 200);
1558 }
1559 }
1560
@@ -1682,7 +1658,7 @@
1658 if (nodes[i].meshid != current) {
1659 deviceHeaderSet();
1660 var extra = '';
1685 - if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>, Intel&reg; AMT only</span>'; }
1661 + if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>' + ", Intel&reg; AMT only" + '</span>'; }
1662 if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1663 r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
1664 //r += getMeshActions(mesh2, meshrights);
@@ -1707,11 +1683,11 @@
1683
1684 count++;
1685 var title = EscapeHtml(nodes[i].name);
1710 - if (title.length == 0) { title = '<i>None</i>'; }
1686 + if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
1687 if ((nodes[i].rname != null) && (nodes[i].rname.length > 0)) { title += " / " + EscapeHtml(nodes[i].rname); }
1688 var name = EscapeHtml(nodes[i].name);
1689 if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
1714 - if (name.length == 0) { name = '<i>None</i>'; }
1690 + if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
1691
1692 // Node
1693 var icon = nodes[i].icon, nodestate = NodeStateStr(nodes[i]);
@@ -1751,8 +1727,8 @@
1727 r += '<div><div colspan=3 class=DevSt><span style=float:right>';
1728 //r += getMeshActions(mesh, meshrights);
1729 r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
1754 - if (mesh.mtype == 1) { r += '<div style=padding:10px><i>No Intel&reg; AMT devices in this group'; }
1755 - if (mesh.mtype == 2) { r += '<div style=padding:10px><i>No devices in this group'; }
1730 + if (mesh.mtype == 1) { r += '<div style=padding:10px><i>' + "No Intel&reg; AMT devices in this group"; }
1731 + if (mesh.mtype == 2) { r += '<div style=padding:10px><i>' + "No devices in this group"; }
1732 r += '.</i></div></div>';
1733 current = mesh._id;
1734 count++;
@@ -1762,7 +1738,7 @@
1738 }
1739
1740 if (count == 0) {
1765 - QH('xdevices', '<div style="margin-top:50px;text-align:center"><span style="font-size:30px">No devices</span><br /><br />Use the desktop version of this website to add devices.</div>');
1741 + QH('xdevices', '<div style="margin-top:50px;text-align:center"><span style="font-size:30px">' + "No devices" + '</span><br /><br />' + "Use the desktop version of this website to add devices." + '</div>');
1742 } else {
1743 QH('xdevices', r);
1744 }
@@ -1772,18 +1748,18 @@
1748 }
1749
1750 var powerStatetable = ['', 'Powered', 'Sleep', 'Sleep', 'Sleep', 'Hibernating', 'Power off', 'Present'];
1775 - var powerStateStrings = ['', '<span title="Device is powered on.">Powered</span>', '<span title="Device is in sleep state (S1).">Sleeping</span>', '<span title="Device is in sleep state (S2).">Sleeping</span>', '<span title="Device is in deep sleep state (S3).">Deep Sleep</span>', '<span title="Device is in hibernating state (S4).">Hibernating</span>', '<span title="Device is in powered off state (S5).">Soft-Off</span>', '<span title="Device is detected but power state could not be obtained.">Present</span>'];
1776 - var powerStateStrings2 = ['', 'Device is powered', 'Device is in sleep state (S1)', 'Device is in sleep state (S2)', 'Device is in deep sleep state (S3)', 'Device is hibernating (S4)', 'Device is in soft-off state (S5)', 'Device is present, but power state cannot be determined'];
1751 + var powerStateStrings = ['', "Powered", "Sleeping", "Sleeping", "Deep Sleep", "Hibernating", "Soft-Off", "Present"];
1752 + var powerStateStrings2 = ['', "Device is powered", "Device is in sleep state (S1)", "Device is in sleep state (S2)", "Device is in deep sleep state (S3)", "Device is hibernating (S4)", "Device is in soft-off state (S5)", "Device is present, but power state cannot be determined"];
1753 var powerColorTable = ['#00000000', 'black', 'blue', 'blue', 'lightblue', 'blueviolet', 'darkgreen', 'lightseagreen', 'lightseagreen'];
1754 function NodeStateStr(node) {
1755 var states = [];
1756 if (node.state > 0 && node.state < powerStatetable.length) state.push(powerStatetable[node.state]);
1757 if (node.conn) {
1782 - if ((node.conn & 1) != 0) { states.push('<span title="Mesh agent is connected and ready for use.">Agent</span>'); }
1783 - if ((node.conn & 2) != 0) { states.push('<span title="Intel&reg; AMT CIRA is connected and ready for use.">CIRA</span>'); }
1784 - else if ((node.conn & 4) != 0) { states.push('<span title="Intel&reg; AMT is routable.">Intel&reg; AMT</span>'); }
1785 - if ((node.conn & 8) != 0) { states.push('<span title="Mesh agent is reachable using another agent as relay.">Relay</span>'); }
1786 - if ((node.conn & 16) != 0) { states.push('<span title="MQTT connection to the device is active.">MQTT</span>'); }
1758 + if ((node.conn & 1) != 0) { states.push('<span>' + "Agent" + '</span>'); }
1759 + if ((node.conn & 2) != 0) { states.push('<span>' + "CIRA" + '</span>'); }
1760 + else if ((node.conn & 4) != 0) { states.push('<span>' + "Intel&reg; AMT" + '</span>'); }
1761 + if ((node.conn & 8) != 0) { states.push('<span>' + "Relay" + '</span>'); }
1762 + if ((node.conn & 16) != 0) { states.push('<span>' + "MQTT" + '</span>'); }
1763 }
1764 if ((node.pwr != null) && (node.pwr != 0)) { states.push(powerStateStrings[node.pwr]); }
1765 return states.join(', ');
@@ -1796,21 +1772,21 @@
1772
1773 function PowerStateStr2(x) {
1774 if ((x != 0) && (x < powerStatetable.length)) return powerStatetable[x];
1799 - return 'Unknown';
1775 + return "Unknown";
1776 }
1777
1778 function onSortSelectChange(skipsave) {
1803 - sort = document.getElementById("sortselect").selectedIndex;
1804 - if (!skipsave) { putstore("sort", sort); }
1779 + sort = document.getElementById('sortselect').selectedIndex;
1780 + if (!skipsave) { putstore('sort', sort); }
1781 updateDevicesEx();
1782 }
1783
1784 function deviceHeaderSet() {
1785 if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
1810 - deviceHeaders["DevxHeader" + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? ' node' : ' nodes');
1786 + deviceHeaders['DevxHeader' + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? " node" : " nodes");
1787 var title = '';
1788 for (var x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
1813 - deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
1789 + deviceHeadersTitles['DevxHeader' + deviceHeaderId] = title;
1790 deviceHeaderId++;
1791 deviceHeaderCount = {};
1792 deviceHeaderTotal = 0;
@@ -1860,7 +1836,7 @@
1836
1837 // Add node name
1838 var nname = EscapeHtml(node.name);
1863 - if (nname.length == 0) { nname = '<i>None</i>'; }
1839 + if (nname.length == 0) { nname = '<i>' + "None" + '</i>'; }
1840 if ((meshrights & 4) != 0) { nname = '<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + '</span>'; }
1841 QH('p10deviceName', nname);
1842
@@ -1868,28 +1844,28 @@
1844 var x = '<table style=width:100%>';
1845
1846 // Attribute: Mesh
1871 - x += addDeviceAttribute('<span title="The name of the device group this computer belong to">Group</span>', '<a title="The name of the device group this computer belong to" onclick=goForward("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
1847 + x += addDeviceAttribute('<span>' + "Group" + '</span>', '<a onclick=goForward("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
1848
1849 // Attribute: Name
1874 - if (node.rname != null) { x += addDeviceAttribute('<span title="The name of this computer as set in the operating system">Name</span>', '<span title="The name of this computer as set in the operating system">' + EscapeHtml(node.rname) + '</span>'); }
1850 + if (node.rname != null) { x += addDeviceAttribute('<span>' + "Name" + '</span>', '<span>' + EscapeHtml(node.rname) + '</span>'); }
1851
1852 // Attribute: Host
1853 if ((mesh.mtype == 1) || (node.name != node.host)) {
1854 if ((meshrights & 4) != 0) {
1855 if (node.host) {
1880 - x += addDeviceAttribute('Hostname', '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
1856 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer>' + EscapeHtml(node.host) + '</span>');
1857 } else {
1882 - x += addDeviceAttribute('Hostname', '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>None</i></span>');
1858 + x += addDeviceAttribute("Hostname", '<span onclick=showEditNodeValueDialog(1) style=cursor:pointer><i>None</i></span>');
1859 }
1860 } else {
1885 - x += addDeviceAttribute('Hostname', EscapeHtml(node.host));
1861 + x += addDeviceAttribute("Hostname", EscapeHtml(node.host));
1862 }
1863 }
1864
1865 // Attribute: Description
1866 var description = node.desc ? EscapeHtml(node.desc) : '<i>' + "None" + '</i>';
1867 if ((meshrights & 4) != 0) {
1892 - x += addDeviceAttribute('Description', '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + '</span>');
1868 + x += addDeviceAttribute("Description", '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + '</span>');
1869 } else {
1870 x += addDeviceAttribute("Description", description);
1871 }
@@ -1906,36 +1882,36 @@
1882 // Attribute: Intel AMT
1883 if (node.intelamt != null) {
1884 var str = '';
1909 - var provisioningStates = { 0: 'Not&nbsp;Activated&nbsp;(Pre)', 1: 'Not&nbsp;Activated&nbsp;(In)', 2: 'Activated' };
1910 - if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>Unknown&nbsp;State</i>, v' + node.intelamt.ver; } else
1885 + var provisioningStates = { 0: "Not&nbsp;Activated&nbsp;(Pre)", 1: "Not&nbsp;Activated&nbsp;(In)", 2: "Activated" };
1886 + if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Unknown&nbsp;State" + '</i>, v' + node.intelamt.ver; } else
1887
1912 - if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>Activated</i>'; }
1913 - else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>Unknown Version & State</i>'; }
1888 + if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "Activated" + '</i>'; }
1889 + else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Unknown Version & State" + '</i>'; }
1890 else {
1891 str += provisioningStates[node.intelamt.state];
1916 - if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span title="Intel AMT is activated in Client Control Mode">CCM</span>'; } else if (node.intelamt.flags & 4) { str = ' <span title="Intel AMT is activated in Admin Control Mode">ACM</span>'; } }
1892 + if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span>' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str = ' <span>' + "ACM" + '</span>'; } }
1893 str += (', v' + node.intelamt.ver);
1894 }
1895
1920 - if (node.intelamt.tls == 1) { str += ', <span title="Intel AMT is setup with TLS network security">TLS</span>'; }
1896 + if (node.intelamt.tls == 1) { str += ', <span>' + "TLS" + '</span>'; }
1897 if (node.intelamt.state == 2) {
1898 if (node.intelamt.user == null || node.intelamt.user == '') {
1899 if ((meshrights & 4) != 0) {
1924 - str += ', <i style=color:#FF0000;cursor:pointer title="Edit Intel&reg; AMT credentials" onclick=editDeviceAmtSettings("' + node._id + '")>No&nbsp;Credentials</i>';
1900 + str += ', <i style=color:#FF0000;cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>' + "No&nbsp;Credentials" + '</i>';
1901 } else {
1926 - str += ', <i style=color:#FF0000>No Credentials</i>';
1902 + str += ', <i style=color:#FF0000>' + "No Credentials" + '</i>';
1903 }
1904 }
1905 str += ' ';
1906 if ((meshrights & 4) != 0) {
1931 - str += '<img src=images/link4.png height=10 width=10 title="Edit Intel&reg; AMT credentials" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
1907 + str += '<img src=images/link4.png height=10 width=10 style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
1908 }
1909 }
1910
1935 - var meName = 'Intel&reg; ME';
1911 + var meName = "Intel&reg; ME";
1912 if (typeof node.intelamt.sku == 'number') {
1937 - if ((node.intelamt.sku & 8) != 0) { meName = 'Intel&reg; AMT'; }
1938 - else if ((node.intelamt.sku & 16) != 0) { meName = 'Intel&reg; SM'; }
1913 + if ((node.intelamt.sku & 8) != 0) { meName = "Intel&reg; AMT"; }
1914 + else if ((node.intelamt.sku & 16) != 0) { meName = "Intel&reg; SM"; }
1915 }
1916 x += addDeviceAttribute(meName, str);
1917 }
@@ -1944,7 +1920,7 @@
1920 if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) {
1921 var tag = EscapeHtml(node.agent.tag);
1922 if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
1947 - x += addDeviceAttribute('Agent Tag', tag);
1923 + x += addDeviceAttribute("Agent Tag", tag);
1924 }
1925
1926 // Attribute: Intel AMT
@@ -1954,28 +1930,28 @@
1930 var connectivity = node.conn;
1931 if (connectivity && connectivity > 1) {
1932 var cstate = [];
1957 - if ((node.conn & 1) != 0) cstate.push('<span title="Software agent is connected and ready for use.">Agent</span>');
1958 - if ((node.conn & 2) != 0) cstate.push('<span title="Intel&reg; AMT CIRA is connected and ready for use.">Intel&reg; AMT CIRA</span>');
1959 - else if ((node.conn & 4) != 0) cstate.push('<span title="Intel&reg; AMT is routable and ready for use.">Intel&reg; AMT</span>');
1960 - if ((node.conn & 8) != 0) cstate.push('<span title="Software agent is reachable using another agent as relay.">Agent Relay</span>');
1961 - if ((node.conn & 16) != 0) cstate.push('<span title="MQTT connection to the device is active.">MQTT</span>');
1962 - x += addDeviceAttribute('Connectivity', cstate.join(', '));
1933 + if ((node.conn & 1) != 0) cstate.push('<span>' + "Agent" + '</span>');
1934 + if ((node.conn & 2) != 0) cstate.push('<span>' + "Intel&reg; AMT CIRA" + '</span>');
1935 + else if ((node.conn & 4) != 0) cstate.push('<span>' + "Intel&reg; AMT" + '</span>');
1936 + if ((node.conn & 8) != 0) cstate.push('<span>' + "Agent Relay" + '</span>');
1937 + if ((node.conn & 16) != 0) cstate.push('<span>' + "MQTT" + '</span>');
1938 + x += addDeviceAttribute("Connectivity", cstate.join(', '));
1939 }
1940
1941 // Node tags
1966 - var groupingTags = '<i>None</i>';
1942 + var groupingTags = '<i>' + "None" + '</i>';
1943 if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
1944 if ((meshrights & 4) != 0) {
1969 - x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
1945 + x += addDeviceAttribute("Tags", '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
1946 } else {
1971 - x += addDeviceAttribute('Tags', groupingTags);
1947 + x += addDeviceAttribute("Tags", groupingTags);
1948 }
1949
1950 x += '</table><br />';
1951 // Show action button, only show if we have permissions 4, 8, 64
1976 - if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
1977 - //x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
1978 - //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
1952 + if ((meshrights & 76) != 0) { x += '<input type=button value=Actions onclick=deviceActionFunction() />'; }
1953 + //x += '<input type=button value=Notes onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
1954 + //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast onclick=deviceToastFunction() />'; }
1955 QH('p10html', x);
1956
1957 // Show node last 7 days timeline
@@ -1984,10 +1960,10 @@
1960
1961 // Show bottom buttons
1962 x = '<div style=float:right;font-size:x-small;margin-right:10px>';
1987 - if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '") title="Remove this device">Delete Device</a>';
1963 + if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '")>' + "Delete Device" + '</a>';
1964 x += '</div><div style=font-size:x-small>';
1989 - //if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a>&nbsp;';
1990 - //if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a>&nbsp;';
1965 + //if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '")>Interfaces</a>&nbsp;';
1966 + //if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '")>Location</a>&nbsp;';
1967 x += '</div><br>'
1968
1969 QH('p10html3', x);
@@ -1995,10 +1971,10 @@
1971 // Set the node power state
1972 var powerstate = PowerStateStr(node.state);
1973 //if (node.state == 0) { powerstate = 'Unknown State'; }
1998 - if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Agent connected">Mesh Agent</span>'; }
1999 - if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Intel&reg; AMT connected">Intel&reg; AMT connected</span>'; }
2000 - else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Intel&reg; AMT detected">Intel&reg; AMT detected</span>'; }
2001 - if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title="MQTT connected">MQTT channel connected</span>'; }
1974 + if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Mesh Agent" + '</span>'; }
1975 + if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg; AMT connected" + '</span>'; }
1976 + else if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px>' + "Intel&reg; AMT detected" + '</span>'; }
1977 + if ((connectivity & 16) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px>' + "MQTT channel connected" + '</span>'; }
1978 QH('MainComputerState', powerstate);
1979
1980 // Set the node icon
@@ -2045,12 +2021,12 @@
2021 function deviceActionFunction() {
2022 if (xxdialogMode) return;
2023 var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
2048 - var x = "Select an operation to perform on this device.<br /><br />";
2024 + var x = "Select an operation to perform on this device." + '<br /><br />';
2025 var y = '<select id=d2deviceop style=float:right;width:170px>';
2050 - if ((meshrights & 64) != 0) { y += '<option value=100>Wake-up</option>'; } // Wake-up permission
2051 - if ((meshrights & 8) != 0) { y += '<option value=4>Sleep</option><option value=3>Reset</option><option value=2>Power off</option>'; } // Remote control permission
2026 + if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
2027 + if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
2028 y += '</select>';
2053 - x += addHtmlValue('Operation', y);
2029 + x += addHtmlValue("Operation", y);
2030 setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
2031 }
2032
@@ -2107,10 +2083,7 @@
2083 var ts = Math.max(start, block[0]);
2084 var te = Math.min(Math.min(end, block[1]), now);
2085 var width = Math.round(((te - ts) * totalWidth) / 86400000);
2110 - if (width > 0) {
2111 - var title = powerStateStrings2[block[2]] + ' from ' + printTime(new Date(ts)) + ' to ' + printTime(new Date(te)) + '.';
2112 - datavalue += '<div title="' + title + '" style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>';
2113 - }
2086 + if (width > 0) { datavalue += '<div style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>'; }
2087 }
2088 }
2089 x += '<tr style=' + (((count % 2) == 0) ? 'background-color:#DDD' : '') + '><td><div>&nbsp;' + printDate(date) + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
@@ -2139,9 +2112,9 @@
2112 if (xxdialogMode) return;
2113 var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
2114 if ((meshrights & 4) == 0) return;
2142 - x += addHtmlValue('Username', '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2143 - x += addHtmlValue('Password', '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2144 - x += addHtmlValue('Security', '<select id=dp10tls style=width:176px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>');
2115 + x += addHtmlValue("Username", '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2116 + x += addHtmlValue("Password", '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
2117 + x += addHtmlValue("Security", '<select id=dp10tls style=width:176px><option value=0>' + "No TLS security" + '</option><option value=1>' + "TLS security required" + '</option></select>');
2118 if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
2119 setDialogMode(2, "Edit Intel&reg; AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
2120 if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
@@ -2172,7 +2145,7 @@
2145
2146 function p10showDeleteNodeDialog(nodeid) {
2147 if (xxdialogMode) return;
2175 - setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, "Delete \"" + EscapeHtml(currentNode.name) + "\"?<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirm", nodeid);
2148 + setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, format("Delete {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm", nodeid);
2149 p10validateDeleteNodeDialog();
2150 }
2151
@@ -2206,9 +2179,9 @@
2179 meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
2180 }
2181
2209 - var showEditNodeValueDialog_modes = ['Device Name', 'Hostname', 'Description', 'Tags'];
2182 + var showEditNodeValueDialog_modes = ["Device Name", "Hostname", "Description", "Tags"];
2183 var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
2211 - var showEditNodeValueDialog_modes3 = ['', '', '', 'Group1, Group2, Group3'];
2184 + var showEditNodeValueDialog_modes3 = ['', '', '', "Group1, Group2, Group3"];
2185 function showEditNodeValueDialog(mode) {
2186 if (xxdialogMode) return;
2187 var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
@@ -2348,7 +2321,7 @@
2321 var xstate = state;
2322 if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
2323 var str = StatusStrs[xstate];
2351 - if ((desktop != null) && (desktop.webRtcActive == true)) { str += ', WebRTC'; }
2324 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
2325 //if (desktop.m.stopInput == true) { str += ', Loopback'; }
2326 QH('deskstatus', str);
2327 switch (state) {
@@ -2590,7 +2563,7 @@
2563 for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); }
2564 if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
2565 var x = '';
2593 - for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer title="Stop process" onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + p[i].c + '</div></div>'; } }
2566 + for (var i in p) { if (p[i].p != 0) { x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a style=float:right;padding-right:5px;cursor:pointer onclick=stopProcess(' + p[i].p + ',"' + p[i].c + '")><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + p[i].c + '</div></div>'; } }
2567 QH('DeskToolsProcesses', x);
2568 }
2569 }
@@ -2599,8 +2572,8 @@
2572 function deskSaveImage() {
2573 setSessionActivity();
2574 if (xxdialogMode || desktop == null || desktop.State != 3) return;
2602 - 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);
2603 - Q("Desk")['toBlob'](function (blob) { saveAs(blob, n + ".jpg"); });
2575 + 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);
2576 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.jpg'); });
2577 }
2578
2579 function deskDisplayInfo(sender, info, selDisplay, selItem) {
@@ -2623,7 +2596,7 @@
2596 function dmousemove(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null)) desktop.m.mousemove(e) }
2597 function dmousewheel(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && desktop.m.mousewheel) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
2598 function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
2626 - function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); }
2599 + function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, format("Stop process #{0} \"{1}\"?", id, name), id); return false; }
2600 function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); }
2601
2602 //
@@ -2642,9 +2615,9 @@
2615
2616 function onFilesStateChange(xfiles, state) {
2617 setSessionActivity();
2645 - p13Connect.value = (state == 0) ? 'Connect' : 'Disconnect';
2618 + p13Connect.value = (state == 0) ? "Connect" : "Disconnect";
2619 var str = StatusStrs[state];
2647 - if (files.webRtcActive == true) { str += ', WebRTC'; }
2620 + if (files.webRtcActive == true) { str += ", WebRTC"; }
2621 Q('p13Status').textContent = str;
2622 switch (state) {
2623 case 0:
@@ -2734,7 +2707,7 @@
2707 }
2708
2709 function p13updateFiles(checkedNames) {
2737 - var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p13folderup(0)>Root</a>', fullPath = 'Root';
2710 + var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p13folderup(0)>' + "Root" + '</a>', fullPath = 'Root';
2711
2712 // Work on parsing the file path
2713 var x = p13filetree.path.split('\\');
@@ -2751,7 +2724,7 @@
2724 // Figure out the name and shortname
2725 var f = filetreexx[i], name = f.n, shortname;
2726 shortname = name;
2754 - if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + "...</span>"; } else { shortname = EscapeHtml(name); }
2727 + if (name.length > 70) { shortname = EscapeHtml(name.substring(0, 70)) + "..."; } else { shortname = EscapeHtml(name); }
2728 name = EscapeHtml(name);
2729
2730 // Figure out the size
@@ -2760,12 +2733,12 @@
2733
2734 var h = '';
2735 if (f.t < 3) {
2763 - var right = '', title = '';
2764 - 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 + "></div><a style=cursor:pointer onclick=p13folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
2736 + var right = '';
2737 + 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>' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p13folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
2738 } else {
2739 var link = shortname;
2767 - if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"p13downloadfile('" + encodeURIComponent(newlinkpath + '/' + name) + "','" + encodeURIComponent(name) + "'," + f.s + ")\">" + shortname + "</a>"; }
2768 - 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 style=float:right;padding-right:4px>" + fsize + "</span><span><div class=fileIcon" + f.t + "></div>" + link + "</span></div>";
2740 + if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
2741 + 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 style=float:right;padding-right:4px>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
2742 }
2743
2744 if (f.t < 3) { html1 += h; } else { html2 += h; }
@@ -2817,7 +2790,7 @@
2790 QE('p13UploadButton', false);
2791 QE('p13RenameFileButton', false);
2792 QE('p13SelectAllButton', false);
2820 - Q('p13SelectAllButton').value = 'All';
2793 + Q('p13SelectAllButton').value = "All";
2794 QE('p13RefreshButton', false);
2795 QE('p13CutButton', false);
2796 QE('p13CopyButton', false);
@@ -2830,7 +2803,7 @@
2803 QE('p13UploadButton', ((p13filetreelocation.length > 0) || (winAgent == false)));
2804 QE('p13RenameFileButton', (cc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2805 QE('p13SelectAllButton', tc > 0);
2833 - Q('p13SelectAllButton').value = (cc > 0 ? 'None' : 'All');
2806 + Q('p13SelectAllButton').value = (cc > 0 ? "None" : "All");
2807 QE('p13RefreshButton', true);
2808 QE('p13CutButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
2809 QE('p13CopyButton', (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
@@ -2838,26 +2811,66 @@
2811 }
2812 }
2813
2841 - function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
2814 + function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
2815 + function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
2816 function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
2817 function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
2818 function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
2819 function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
2846 - function p13deletefile() { var cc = getFileSelCount(); setDialogMode(2, "Delete", 3, p13deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?') : ('Delete selected item?')); }
2847 - 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 }); p13folderup(999); }
2820 + 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)); }
2821 + 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); }
2822 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(); }
2823 function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
2824 function p13fileNameCheck(e) { var x = isFilenameValid(Q('p13renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); } }
2825 function p13uploadFile() { setDialogMode(2, "Upload File", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
2826 function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
2827 + function p13viewfile() {
2828 + var checkboxes = document.getElementsByName('fd');
2829 + for (var i = 0; i < checkboxes.length; i++) {
2830 + if (checkboxes[i].checked) {
2831 + if (p13filetree.dir[checkboxes[i].value].s <= 204800) {
2832 + p13downloadfile(encodeURIComponent(p13filetreelocation.join('/') + '/' + p13filetree.dir[checkboxes[i].value].n), encodeURIComponent(p13filetree.dir[checkboxes[i].value].n), p13filetree.dir[checkboxes[i].value].s, 'viewer');
2833 + } else { messagebox("File Editor", "Only files less than 200k can be edited."); }
2834 + break;
2835 + }
2836 + }
2837 + }
2838
2839 var p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0;
2855 - function p13copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p13clipboard = []; p13clipboardCut = cut, p13clipboardFolder = p13targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == "3")) { p13clipboard.push(p13filetree.dir[checkboxes[i].value].n); } } p13updateClipview(); }
2856 - function p13pasteFile() { var x = ''; if ((p13clipboard != null) && (p13clipboard.length > 0)) { x = 'Confim ' + (p13clipboardCut == 0 ? 'copy' : 'move') + ' of ' + p13clipboard.length + ' entrie' + ((p13clipboard.length > 1) ? 's' : '') + ' to this location?' } setDialogMode(2, "Paste", 3, p13pasteFileEx, x); }
2840 + function p13copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p13clipboard = []; p13clipboardCut = cut, p13clipboardFolder = p13targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) { p13clipboard.push(p13filetree.dir[checkboxes[i].value].n); } } p13updateClipview(); }
2841 + function p13pasteFile() {
2842 + var x = '';
2843 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
2844 + if (p13clipboardCut == 0) {
2845 + if (p13clipboard.length > 1) { x = format("Confirm copy of {0} entries's to this location?", p13clipboard.length); } else { x = format("Confirm copy of 1 entrie to this location?"); }
2846 + } else {
2847 + if (p13clipboard.length > 1) { x = format("Confirm move of {0} entries's to this location?", p13clipboard.length); } else { x = format("Confirm move of 1 entrie to this location?"); }
2848 + }
2849 + }
2850 + setDialogMode(2, "Paste", 3, p13pasteFileEx, x);
2851 + }
2852 function p13pasteFileEx() { files.sendText({ action: (p13clipboardCut == 0 ? 'copy' : 'move'), reqid: 1, scpath: p13clipboardFolder, dspath: p13targetpath, names: p13clipboard }); p13folderup(999); if (p13clipboardCut == 1) { p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0; p13updateClipview(); } }
2858 - function p13updateClipview() { var x = ''; if ((p13clipboard != null) && (p13clipboard.length > 0)) { x = 'Holding ' + p13clipboard.length + ' entrie' + ((p13clipboard.length > 1) ? 's' : '') + ' for ' + (p13clipboardCut == 0 ? 'copy' : 'move') + ', <a onclick=p13clearClip() style=cursor:pointer>Clear</a>.' } QH('p13bottomstatus', x); p13setActions(); }
2859 - function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); }
2860 - function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
2853 + function p13updateClipview() {
2854 + var x = '';
2855 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
2856 + if (p13clipboardCut == 0) {
2857 + if (p13clipboard.length > 1) {
2858 + x = format("Holding {0} entries for copy" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.', p13clipboard.length);
2859 + } else {
2860 + x = format("Holding 1 entrie for copy" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.');
2861 + }
2862 + } else {
2863 + if (p13clipboard.length > 1) {
2864 + x = format("Holding {0} entries for move" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.', p13clipboard.length);
2865 + } else {
2866 + x = format("Holding 1 entrie for move" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.');
2867 + }
2868 + }
2869 + }
2870 + QH('p13bottomstatus', x);
2871 + p13setActions();
2872 + }
2873 + function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); return false; } function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
2874 function getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
2875 function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
2876
@@ -2975,7 +2988,7 @@
2988 uploadFile.xpath = p13filetreelocation.join('/');
2989 uploadFile.xfiles = files;
2990 uploadFile.xfilePtr = -1;
2978 - setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>Connecting...</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
2991 + setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Connecting..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
2992 p13uploadReconnect();
2993 }
2994
@@ -3075,31 +3088,31 @@
3088 function p20updateMesh() {
3089 if (currentMesh == null) return;
3090 QH('p20meshName', EscapeHtml(currentMesh.name));
3078 - var meshtype = 'Unknown #' + currentMesh.mtype;
3091 + var meshtype = format("Unknown #{0}", currentMesh.mtype);
3092 var meshrights = currentMesh.links[userinfo._id].rights;
3080 - if (currentMesh.mtype == 1) meshtype = 'Intel&reg; AMT group';
3081 - if (currentMesh.mtype == 2) meshtype = 'Software agent group';
3093 + if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMT only, no agent";
3094 + if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
3095
3096 var x = '';
3084 - x += addHtmlValue('Name', addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
3085 - x += addHtmlValue('Description', addLinkConditional(((currentMesh.desc && currentMesh.desc != '') ? EscapeHtml(currentMesh.desc) : '<i>None</i>'), 'p20editmesh(2)', (meshrights & 1) != 0));
3086 - x += addHtmlValue('Type', meshtype);
3097 + x += addHtmlValue("Name", addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
3098 + x += addHtmlValue("Description", addLinkConditional(((currentMesh.desc && currentMesh.desc != '') ? EscapeHtml(currentMesh.desc) : ('<i>' + "None" + '</i>')), 'p20editmesh(2)', (meshrights & 1) != 0));
3099 + x += addHtmlValue("Type", meshtype);
3100 //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
3101
3089 - //x += '<br><input type=button value=Notes title="View notes about this mesh" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
3102 + //x += '<br><input type=button value=Notes onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
3103
3104 x += '<br style=clear:both><br>';
3105 var currentMeshLinks = currentMesh.links[userinfo._id];
3093 - if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a></div>'; }
3106 + if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12>' + " Add User" + '</a></div>'; }
3107
3108 /*
3109 if ((meshrights & 4) != 0) {
3110 if (currentMesh.mtype == 1) {
3098 - x += '<a onclick=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>';
3099 - x += '<a onclick=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>';
3111 + x += '<a onclick=addCiraDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install CIRA</a>';
3112 + x += '<a onclick=addDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-installmesh.png border=0 height=12 width=12> Install local</a>';
3113 }
3114 if (currentMesh.mtype == 2) {
3102 - x += '<a onclick=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>';
3115 + x += '<a onclick=addAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
3116 }
3117 }
3118 */
@@ -3109,17 +3122,17 @@
3122 if ((meshrights & 4) == 0) return '';
3123 var r = '';
3124 if (mesh.mtype == 1) {
3112 - r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel&reg; AMT computer that is located on the internet." onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
3113 - r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel&reg; AMT computer that is located on the local network." onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
3125 + r += ' <a style=cursor:pointer;font-size:10px onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
3126 + r += ' <a style=cursor:pointer;font-size:10px onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
3127 }
3128 if (mesh.mtype == 2) {
3116 - r += ' <a style=cursor:pointer;font-size:10px title="Add a new computer to this mesh by installing the mesh agent." onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
3129 + r += ' <a style=cursor:pointer;font-size:10px onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
3130 }
3131 return r;
3132 }
3133 */
3134
3122 - 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></tr>';
3135 + 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></tr>';
3136
3137 // Sort the users for this mesh
3138 var count = 1, sortedusers = [];
@@ -3128,9 +3141,9 @@
3141
3142 // Display all users for this mesh
3143 for (var i in sortedusers) {
3131 - var trash = '', rights = 'Partial&nbsp;Rights', r = sortedusers[i].rights;
3132 - if (r == 0xFFFFFFFF) rights = 'Full&nbsp;Administrator'; else if (r == 0) rights = 'No&nbsp;Rights';
3133 - if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=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>'; }
3144 + var trash = '', rights = "Partial Rights", r = sortedusers[i].rights;
3145 + if (r == 0xFFFFFFFF) rights = "Full Administrator"; else if (r == 0) rights = "No Rights";
3146 + if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
3147 x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=height:32px;cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td>';
3148 x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m2></div><div>&nbsp;' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div>';
3149 x += '</td></tr>';
@@ -3140,18 +3153,18 @@
3153 x += '</tbody></table>';
3154
3155 // If we are full administrator on this mesh, allow deletion of the mesh
3143 - if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Mesh</a></span></div>'; }
3156 + if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>' + "Delete Group" + '</a></span></div>'; }
3157
3158 QH('p20info', x);
3159 }
3160
3148 -
3161 function p20showDeleteMeshDialog() {
3150 - if (xxdialogMode) return;
3151 - var x = "Are you sure you want to delete mesh \"" + EscapeHtml(currentMesh.name) + "\"? Deleting the mesh will also delete all information about computers within this mesh.<br /><br />";
3152 - x += "<input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />Confirm";
3153 - setDialogMode(2, "Delete Mesh", 3, p20showDeleteMeshDialogEx, x);
3162 + if (xxdialogMode) return false;
3163 + 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 />';
3164 + x += '<label><input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />' + "Confirm" + '</label>';
3165 + setDialogMode(2, "Delete Group", 3, p20showDeleteMeshDialogEx, x);
3166 p20validateDeleteMeshDialog();
3167 + return false;
3168 }
3169
3170 function p20validateDeleteMeshDialog() {
@@ -3164,8 +3177,8 @@
3177
3178 function p20editmesh(focus) {
3179 if (xxdialogMode) return;
3167 - var x = addHtmlValue('Name', '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
3168 - x += addHtmlValue('Description', '<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />');
3180 + var x = addHtmlValue("Name", '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
3181 + x += addHtmlValue("Description", '<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />');
3182 setDialogMode(2, "Edit Device Group", 3, p20editmeshEx, x);
3183 Q('dp20meshname').value = currentMesh.name;
3184 if (currentMesh.desc) Q('dp20meshdesc').value = currentMesh.desc;
@@ -3185,19 +3198,22 @@
3198 if (xxdialogMode) return;
3199 var x = addHtmlValue('User', '<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
3200 x += '<div style="border:2px groove gray;background-color:white;max-height:120px;overflow-y:scroll">';
3188 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator<br>';
3189 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Device Group<br>';
3190 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>Manage Device Group Users<br>';
3191 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>Manage Device Group Computers<br>';
3192 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>Remote Control<br>';
3193 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>Remote View Only<br>';
3194 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>No Terminal Access<br>';
3195 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>No File Access<br>';
3196 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>No Intel&reg; AMT<br>';
3197 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console<br>';
3198 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Server Files<br>';
3199 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices<br>';
3200 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes<br>';
3201 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>' + "Full Administrator" + '</label><br>';
3202 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>' + "Edit Device Group" + '</label><br>';
3203 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>' + "Manage Device Group Users" + '</label><br>';
3204 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>' + "Manage Device Group Computers" + '</label><br>';
3205 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>' + "Remote Control" + '</label><br>';
3206 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remoteview style=margin-left:12px>' + "Remote View Only" + '</label><br>';
3207 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotelimitedinput style=margin-left:12px>' + "Limited Input Only" + '</label><br>';
3208 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noterminal style=margin-left:12px>' + "No Terminal Access" + '</label><br>';
3209 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20nofiles style=margin-left:12px>' + "No File Access" + '</label><br>';
3210 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20noamt style=margin-left:12px>' + "No Intel&reg; AMT" + '</label><br>';
3211 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>' + "Mesh Agent Console" + '</label><br>';
3212 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>' + "Server Files" + '</label><br>';
3213 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>' + "Wake Devices" + '</label><br>';
3214 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>' + "Edit Device Notes" + '</label><br>';
3215 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20limitevents>' + "Show Only Own Events" + '</label><br>';
3216 + x += '<label><input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20chatnotify>' + "Chat & Notify" + '</label><br>';
3217 x += '</div>';
3218 setDialogMode(2, "Add User to Mesh", 3, p20showAddMeshUserDialogEx, x);
3219 p20validateAddMeshUserDialog();
@@ -3244,30 +3260,32 @@
3260 function p20viewuser(userid) {
3261 if (xxdialogMode) return;
3262 userid = decodeURIComponent(userid);
3247 - var r = '', cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
3248 - if (meshrights == 0xFFFFFFFF) r = ', Full Administrator'; else {
3249 - if ((meshrights & 1) != 0) r += ', Edit Device Group';
3250 - if ((meshrights & 2) != 0) r += ', Manage Device Group Users';
3251 - if ((meshrights & 4) != 0) r += ', Manage Device Group Computers';
3252 - if ((meshrights & 8) != 0) r += ', Remote Control';
3253 - if ((meshrights & 16) != 0) r += ', Agent Console';
3254 - if ((meshrights & 32) != 0) r += ', Server Files';
3255 - if ((meshrights & 64) != 0) r += ', Wake Devices';
3256 - if ((meshrights & 128) != 0) r += ', Edit Notes';
3257 - if ((meshrights & 256) != 0) r += ', Remote View Only';
3258 - if ((meshrights & 512) != 0) r += ', No Terminal';
3259 - if ((meshrights & 1024) != 0) r += ', No Files';
3260 - if ((meshrights & 2048) != 0) r += ', No Intel&reg; AMT';
3263 + var r = [], cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
3264 + if (meshrights == 0xFFFFFFFF) r.push("Full Administrator"); else {
3265 + if ((meshrights & 1) != 0) r.push("Edit Device Group");
3266 + if ((meshrights & 2) != 0) r.push("Manage Device Group Users");
3267 + if ((meshrights & 4) != 0) r.push("Manage Device Group Computers");
3268 + if ((meshrights & 8) != 0) r.push("Remote Control");
3269 + if ((meshrights & 16) != 0) r.push("Agent Console");
3270 + if ((meshrights & 32) != 0) r.push("Server Files");
3271 + if ((meshrights & 64) != 0) r.push("Wake Devices");
3272 + if ((meshrights & 128) != 0) r.push("Edit Notes");
3273 + if ((meshrights & 256) != 0) r.push("Remote View Only");
3274 + if ((meshrights & 512) != 0) r.push("No Terminal");
3275 + if ((meshrights & 1024) != 0) r.push("No Files");
3276 + if ((meshrights & 2048) != 0) r.push("No Intel&reg; AMT");
3277 + if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r.push("Limited Input");
3278 + if ((meshrights & 8192) != 0) r.push("Self Events Only");
3279 + if ((meshrights & 16384) != 0) r.push("Chat & Notify");
3280 }
3262 - r = r.substring(2);
3263 - if (r == '') { r = 'No Rights'; }
3264 - var buttons = 1, x = addHtmlValue('User', EscapeHtml(decodeURIComponent(userid.split('/')[2])));
3265 - x += addHtmlValue('Permissions', r);
3281 + if (r.length == 0) { r.push("No Rights"); }
3282 + var buttons = 1, x = addHtmlValue("User", EscapeHtml(decodeURIComponent(userid.split('/')[2])));
3283 + x += addHtmlValue("Permissions", r.join(", "));
3284 if (((userinfo._id) != userid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
3267 - setDialogMode(2, "Mesh User", buttons, p20viewuserEx, x, userid);
3285 + setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, userid);
3286 }
3287
3270 - function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + userid.split('/')[2] + "?", userid); }
3288 + function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, format("Confirm removal of user {0}?", userid.split('/')[2]), userid); }
3289 function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
3290 function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
3291
@@ -3326,7 +3344,7 @@
3344
3345 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) }); } }
3346 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; } }
3329 - function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + "px"); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ }
3347 + function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + 'px'); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ }
3348 function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
3349 function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
3350 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; }
@@ -3337,10 +3355,10 @@
3355 function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
3356 function addHtmlValue(t, v) { return '<table><td style=width:120px>' + t + '<td><b>' + v + '</b></table>'; }
3357 function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
3340 - function addLink(x, f) { return "<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='" + f + "'>&diams; " + x + "</a>"; }
3358 + function addLink(x, f) { return '<a style=cursor:pointer;color:darkblue;text-decoration:none onclick=\'' + f + '\'>&diams; ' + x + '</a>'; }
3359 function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
3360 function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
3343 - function getFileSizeStr(size) { if (size == 1) return "1 byte"; return "" + size + " bytes"; }
3361 + function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format('{0} bytes', size); }
3362 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('/'); }
3363 function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
3364 var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
@@ -3348,6 +3366,7 @@
3366 function printDate(d) { return d.toLocaleDateString(args.locale); }
3367 function printTime(d) { return d.toLocaleTimeString(args.locale); }
3368 function printDateTime(d) { return d.toLocaleString(args.locale); }
3369 + 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; }); };
3370
3371 </script>
3372 </body>
views/default.handlebars
+10 -11
@@ -4586,7 +4586,7 @@
4586 var te = Math.min(Math.min(end, block[1]), now);
4587 var width = Math.round(((te - ts) * totalWidth) / 86400000);
4588 if (width > 0) {
4589 - var title = powerStateStrings2[block[2]] + ' from ' + printTime(new Date(ts)) + ' to ' + printTime(new Date(te)) + '.';
4589 + var title = format('{0} from {1} to {2}.', powerStateStrings2[block[2]], printTime(new Date(ts)), printTime(new Date(te)));
4590 datavalue += '<div class="pwState ' + powerColor(block[2]) + '" title="' + title + '" style="width:' + width + 'px;"></div>';
4591 }
4592 }
@@ -4693,8 +4693,7 @@
4693
4694 function p10showDeleteNodeDialog(nodeid) {
4695 if (xxdialogMode) return false;
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>';
4696 + var x = format("Are you sure you want to delete node {0}?", EscapeHtml(currentNode.name)) + '<br /><br /><label><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />' + "Confirm" + '</label>';
4697 setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, x, nodeid);
4698 p10validateDeleteNodeDialog();
4699 return false;
@@ -5971,7 +5970,7 @@
5970 }
5971
5972 function p13updateFiles(checkedNames) {
5974 - var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">Root</a>', fullPath = 'Root';
5973 + var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">' + "Root" + '</a>', fullPath = 'Root';
5974
5975 // Work on parsing the file path
5976 var x = p13filetree.path.split('\\');
@@ -6880,15 +6879,15 @@
6879 x += '<br /><br />';
6880 //x += "<form action='" + domainUrl + "changepassword' method=post>";
6881 x += '<table style=margin-left:60px>';
6883 - 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>';
6884 - 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>';
6885 - 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>';
6882 + 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>';
6883 + 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>';
6884 + 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>';
6885 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>'; }
6886 x += '</table>'
6887 if (passRequirements) {
6888 var r = [], rc = 0;
6889 for (var i in passRequirements) { if ((i != 'reset') && (i != 'hint')) { r.push(i + ':' + passRequirements[i]); rc++; } }
6891 - if (rc > 0) { x += '<br /><span style=font-size:x-small>Requirements: ' + r.join(', ') + '.</span>'; }
6890 + if (rc > 0) { x += '<br /><span style=font-size:x-small>' + "Requirements: " + r.join(', ') + '.</span>'; }
6891 }
6892 x += '<br />';
6893 //x += '<br /><div style=padding:10px;margin-bottom:4px>';
@@ -7175,7 +7174,7 @@
7174 for (var i in sortedusers) {
7175 var trash = '', rights = "Partial Rights", r = sortedusers[i].rights;
7176 if (r == 0xFFFFFFFF) rights = "Full Administrator"; else if (r == 0) rights = "No Rights";
7178 - 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>'; }
7177 + 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 device group" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
7178 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>';
7179 ++count;
7180 }
@@ -7548,7 +7547,7 @@
7547 var buttons = 1, x = addHtmlValue("User Name", EscapeHtml(decodeURIComponent(uname)));
7548 if (xuserid.split('/')[2] != uname) { x += addHtmlValue("User Identifier", EscapeHtml(xuserid.split('/')[2])); }
7549
7551 - x += addHtmlValue("Permissions", r);
7550 + x += addHtmlValue("Permissions", r.join(", "));
7551 if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
7552 setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, xuserid);
7553 }
@@ -7597,7 +7596,7 @@
7596 function updateFiles() {
7597 QV('MainMenuMyFiles', ((features & 8) == 0));
7598 if ((features & 8) != 0) return; // If running on a server without files, exit now.
7600 - var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p5folderup(0)">Root</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
7599 + var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p5folderup(0)">' + "Root" + '</a>', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
7600
7601 // Navigate to path location, build the paths at the same time
7602 var filetreelocation2 = [], oldlinkpath = filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');